Hay un atributo dinámico útil en el registro activo llamado find_or_create_by:
Model.find_or_create_by_<attribute>(:<attribute> => "")
Pero, ¿qué sucede si necesito encontrar_o_crear con más de un atributo?
Digamos que tengo un modelo para manejar una relación M: M entre Group y Member llamada GroupMember. Podría tener muchas instancias donde member_id = 4, pero nunca quiero más de una instancia donde member_id = 4 y group_id = 7. Estoy tratando de averiguar si es posible hacer algo como esto:
GroupMember.find_or_create(:member_id => 4, :group_id => 7)
Me doy cuenta de que puede haber mejores formas de manejar esto, pero me gusta la conveniencia de la idea de find_or_create.
Para cualquier otra persona que se encuentre con este hilo pero necesite encontrar o crear un objeto con atributos que puedan cambiar según las circunstancias, agregue el siguiente método a su modelo:
Consejo de optimización: independientemente de la solución que elija, considere agregar índices para los atributos que está consultando con más frecuencia.
fuente
find_or_create_by
hará.Model.where(attributes).instance_eval{|q| q.first || q.create}
.find_or_create
también tiene el beneficio de usar una transacción, dondewhere….first || create
introduce una condición de carreradef self.find_or_create(attributes) self.where(attributes).first || self.create(attributes) end
que no es necesario que repitasModel
self
dentro del cuerpo del método (¡ya que estás buscando eliminar palabras!).En Rails 4 podrías hacer:
Y el uso
where
es diferente:Esto llamará
create
aGroupMember.where(member_id: 4, group_id: 7)
:Por el contrario, el
find_or_create_by(member_id: 4, group_id: 7)
llamarácreate
aGroupMember
:Por favor, consulte este compromiso relevante sobre rieles / rieles.
fuente
Al pasar un bloque a
find_or_create
, puede pasar parámetros adicionales que se agregarán al objeto si se crea nuevo. Esto es útil si está validando la presencia de un campo en el que no está buscando.Asumiendo:
luego
creará un nuevo GroupMember con el nombre "John Doe" si no encuentra uno con
member_id 4
and group_id 7
fuente
Tu puedes hacer:
O simplemente para inicializar:
fuente