procurar vs procurar por vs onde

Sou novo nos carris. O que eu vejo é que há muitas maneiras de encontrar um registro:
  1. find_by_<columnname>(<columnvalue>)
  2. find(:first, :conditions => { <columnname> => <columnvalue> }
  3. where(<columnname> => <columnvalue>).first
E parece que todos eles acabam gerando exatamente o mesmo SQL. Além disso, eu acredito que o mesmo é verdade para encontrar vários registros:

  1. find_all_by_<columnname>(<columnvalue>)
  2. find(:all, :conditions => { <columnname> => <columnvalue> }
  3. where(<columnname> => <columnvalue>)

Existe uma regra ou recomendação sobre qual deles usar?

Author: ekremkaraca, 2012-06-22

10 answers

Use o que achar melhor para as suas necessidades.

O método find é normalmente utilizado para obter uma linha por ID:

Model.find(1)

Os outros usos de find são normalmente substituídos por coisas como esta:

Model.all
Model.first

Find_by é usado como um auxiliar quando você está procurando por informações dentro de uma coluna, e mapeia para tal com Convenções de nomeação. Por exemplo, se você tiver uma coluna chamada name na sua base de dados, você usaria a seguinte sintaxe:

Model.find_by_name("Bob")

No Entanto, Eu acredita que está a ser desacreditado.

.where é mais uma captura tudo que permite que você use uma lógica um pouco mais complexa para quando os ajudantes convencionais não vai fazer.

 68
Author: John, 2015-09-08 18:29:11

Onde devolve ActiveRecord:: Relation

Agora dá uma vista de olhos à implementação:

def find_by
  where(*args).take
end

Como pode ver o find_by é o mesmo que onde mas devolve apenas um registo. Este método deve ser utilizado para obter 1 registo e onde deve ser utilizado para obter todos os registos com algumas condições.

 92
Author: Mike Andrianov, 2016-11-20 11:00:52

Existe uma diferença entre find e find_by na medida em que {[[0]} irá retornar um erro se não for encontrado, enquanto find_by irá retornar nulo.

Às vezes é mais fácil de ler se você tem um método como find_by email: "haha", em oposição a .where(email: some_params).first.

 30
Author: Kasumi, 2016-02-07 02:58:52

Model.find

1-parâmetro: ID do objecto a encontrar.

2 - Se for encontrado: devolve o objecto (apenas um objecto).

3-Se não for encontrado: levanta uma excepção ActiveRecord::RecordNotFound.

Model.find_by

1-parâmetro: chave / valor

Exemplo:

User.find_by name: 'John', email: '[email protected]'

2 - Se for encontrado: devolve o objecto.

3-Se não for encontrado: devolve nil.

Nota: Se quiser que levante ActiveRecord::RecordNotFound use find_by!

Model.where

1-Parâmetro: igual a find_by

2-Se for encontrado: devolve ActiveRecord::Relation contendo um ou mais registos correspondentes aos parâmetros.

3-Se não for encontrado: devolve um ActiveRecord::Relation vazio.

 22
Author: Hossam Khamis, 2016-12-27 01:28:42

Desde os carris 4 podes fazer:

User.find_by(name: 'Bob')

Que é o equivalente find_by_name nos carris 3.

Utilizar #where Quando #find e #find_by não são suficientes.

 15
Author: Agis, 2016-05-26 07:48:53
A resposta aceita geralmente cobre tudo, mas gostaria de acrescentar algo., apenas caso você está planejando trabalhar com o modelo de uma maneira como de atualização, e a obtenção de um único registro(cujo id você não sabe), Então find_by é o caminho a percorrer, porque ele recupera o registro e não colocá-lo em uma matriz
irb(main):037:0> @kit = Kit.find_by(number: "3456")
  Kit Load (0.9ms)  SELECT "kits".* FROM "kits" WHERE "kits"."number" = 
 '3456' LIMIT 1
=> #<Kit id: 1, number: "3456", created_at: "2015-05-12 06:10:56",   
updated_at: "2015-05-12 06:10:56", job_id: nil>

irb(main):038:0> @kit.update(job_id: 2)
(0.2ms)  BEGIN Kit Exists (0.4ms)  SELECT 1 AS one FROM "kits" WHERE  
("kits"."number" = '3456' AND "kits"."id" != 1) LIMIT 1 SQL (0.5ms)   
UPDATE "kits" SET "job_id" = $1, "updated_at" = $2 WHERE  "kits"."id" = 
1  [["job_id", 2], ["updated_at", Tue, 12 May 2015 07:16:58 UTC +00:00]] 
(0.6ms)  COMMIT => true

Mas se utilizar where então não pode actualizá-lo directamente

irb(main):039:0> @kit = Kit.where(number: "3456")
Kit Load (1.2ms)  SELECT "kits".* FROM "kits" WHERE "kits"."number" =  
'3456' => #<ActiveRecord::Relation [#<Kit id: 1, number: "3456", 
created_at: "2015-05-12 06:10:56", updated_at: "2015-05-12 07:16:58", 
job_id: 2>]>

irb(main):040:0> @kit.update(job_id: 3)
ArgumentError: wrong number of arguments (1 for 2)

Nesse caso você teria que especificá - lo assim

irb(main):043:0> @kit[0].update(job_id: 3)
(0.2ms)  BEGIN Kit Exists (0.6ms)  SELECT 1 AS one FROM "kits" WHERE 
("kits"."number" = '3456' AND "kits"."id" != 1) LIMIT 1 SQL (0.6ms)   
UPDATE "kits" SET "job_id" = $1, "updated_at" = $2 WHERE "kits"."id" = 1  
[["job_id", 3], ["updated_at", Tue, 12 May 2015 07:28:04 UTC +00:00]]
(0.5ms)  COMMIT => true
 9
Author: Leonard Kakande, 2015-05-12 07:36:45
Ambos os números 2 das vossas listas estão a ser desacreditados. No entanto, ainda pode usar find(params[:id]).

Geralmente, where() funciona na maioria das situações.

Aqui está um grande post: http://m.onkey.org/active-record-query-interface
 6
Author: evanbikes, 2012-06-22 18:15:21

Para além da resposta aceite, o seguinte também é válido

Model.find() pode aceitar uma série de ids, e irá devolver todos os registros que coincidem. Model.find_by_id(123) também aceita a lista, mas só irá processar o primeiro valor de id presente na lista

Model.find([1,2,3])
Model.find_by_id([1,2,3])
 5
Author: Saumya Mehta, 2016-06-21 08:15:44

Suponha que tenho um utilizador de modelos

  1. User.find(id)

Devolve uma linha apontada pelo id. Então suponha, se id = 1, então ele retornará a primeira linha. O tipo de retorno será objeto do Usuário.

  1. User.find_by(email:"[email protected]")

Devolve a primeira linha com o atributo correspondente ou e-mail neste caso. O tipo de retorno será objeto do Usuário novamente.

  1. User.where(project_id:1)

Devolve todos os utilizadores na tabela de utilizadores onde o atributo corresponde. Aqui o tipo de retorno será ActiveRecord:: objecto de relação contém a lista de objectos do utilizador.

 1
Author: Nikhil Mohadikar, 2018-07-20 10:13:14

Vou recomendar pessoalmente a utilização de

where(< columnname> => < columnvalue>)
 -2
Author: Prateek Alakh, 2017-05-03 21:12:42