procurar vs procurar por vs onde
find_by_<columnname>(<columnvalue>)
find(:first, :conditions => { <columnname> => <columnvalue> }
where(<columnname> => <columnvalue>).first
find_all_by_<columnname>(<columnvalue>)
find(:all, :conditions => { <columnname> => <columnvalue> }
where(<columnname> => <columnvalue>)
Existe uma regra ou recomendação sobre qual deles usar?
10 answers
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.
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.
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
.
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.
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.
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
find(params[:id])
.
Geralmente, where()
funciona na maioria das situações.
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])
Suponha que tenho um utilizador de modelos
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.
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.
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.
Vou recomendar pessoalmente a utilização de
where(< columnname> => < columnvalue>)