ruby on rails - rails - encontrar vs find_by vs donde
find() rails (10)
Además de la respuesta aceptada, seguir también es válido
Model.find()
puede aceptar una matriz de identificadores y devolverá todos los registros que coincidan. Model.find_by_id(123)
también acepta una matriz pero solo procesará el primer valor de identificación presente en la matriz
Model.find([1,2,3])
Model.find_by_id([1,2,3])
Soy nuevo en los rieles. Lo que veo es que hay muchas formas de encontrar un registro:
find_by_<columnname>(<columnvalue>)
-
find(:first, :conditions => { <columnname> => <columnvalue> }
-
where(<columnname> => <columnvalue>).first
Y parece que todos terminan generando exactamente el mismo SQL. Además, creo que lo mismo es cierto para encontrar registros múltiples:
-
find_all_by_<columnname>(<columnvalue>)
-
find(:all, :conditions => { <columnname> => <columnvalue> }
-
where(<columnname> => <columnvalue>)
¿Existe una regla general o recomendación sobre cuál usar?
Ambos # 2 en sus listas están siendo desaprobados. Sin embargo, todavía puede usar find(params[:id])
.
Generalmente, where()
funciona en la mayoría de las situaciones.
Aquí hay una gran publicación: http://m.onkey.org/active-record-query-interface
Desde Rails 4 puedes hacer:
User.find_by(name: ''Bob'')
que es el equivalente find_by_name
en Rails 3.
Use #where
cuando #find
y #find_by
no son suficientes.
Hay una diferencia entre find
y find_by
en que find
devolverá un error si no se encuentra, mientras que find_by
devolverá null.
A veces es más fácil de leer si tienes un método como find_by email: "haha"
, en lugar de .where(email: some_params).first
.
La respuesta aceptada generalmente lo cubre todo, pero me gustaría agregar algo, solo en caso de que esté planeando trabajar con el modelo de una manera similar a la actualización, y está recuperando un solo registro (cuyo id
no conoce), luego find_by
es el camino a seguir, porque recupera el registro y no lo pone en una 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
pero si usa el where
entonces no puede actualizarlo 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)
en tal caso, debería especificarlo así
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
Supongamos que tengo un modelo de usuario
-
User.find(id)
Devuelve una fila señalada por el id. Supongamos que si id = 1, devolverá la primera fila. El tipo de devolución será un objeto Usuario.
-
User.find_by(email:"[email protected]")
Devuelve la primera fila con el atributo o el correo electrónico correspondiente en este caso. El tipo de devolución será el objeto Usuario nuevamente.
-
User.where(project_id:1)
Devuelve todos los usuarios en la tabla de usuarios donde coinciden los atributos. Aquí el tipo de devolución será una matriz de objetos de Usuario.
Utilice el que considere más adecuado para sus necesidades.
El método de find
se usa generalmente para recuperar una fila por ID:
Model.find(1)
Otros usos del find
generalmente se reemplazan con cosas como esta:
Model.all
Model.first
Find_by
se usa como ayuda cuando busca información dentro de una columna y se asigna a las convenciones de nomenclatura. Por ejemplo, si tiene una columna llamada name
en su base de datos, usaría la siguiente sintaxis:
Model.find_by_name("Bob")
Sin embargo, creo que find_by
está en desuso.
.where
es más de una captura todo lo que le permite utilizar una lógica un poco más compleja para cuando los ayudantes convencionales no lo hacen.
Yo personalmente recomendaré usar
where(< columnname> => < columnvalue>)
Model.find
1- Parámetro: ID del objeto a encontrar.
2- Si se encuentra: Devuelve el objeto (Un solo objeto).
3- Si no se encuentra: genera una excepción ActiveRecord::RecordNotFound
.
Model.find_by
1- Parámetro: clave / valor
Ejemplo:
User.find_by name: ''John'', email: ''[email protected]''
2- Si se encuentra: Devuelve el objeto.
3- Si no se encuentra: devuelve nil
.
Nota: Si desea que ActiveRecord::RecordNotFound
use find_by!
Model.where
1- Parámetro: igual que find_by
2- Si se encuentra: Devuelve ActiveRecord::Relation
contiene uno o más registros que coinciden con los parámetros.
3- Si no se encuentra: ActiveRecord::Relation
un Empty ActiveRecord::Relation
.
donde devuelve ActiveRecord :: Relation
Ahora eche un vistazo a la implementación de find_by:
def find_by
where(*args).take
end
Como puede ver, find_by es igual que where, pero solo devuelve un registro. Este método se debe usar para obtener 1 registro y dónde se debe usar para obtener todos los registros con algunas condiciones.