En Rails, ¿cómo consulto dos asociaciones has_many en un único buscador?
Estoy usando Rails 4.2. Tengo el siguiente modelo de usuario con un par de asociaciones has_many.
class User < ActiveRecord::Base
...
has_many :roles, through: :roles_users
has_many :addresses, dependent: :destroy, as: :addressable, inverse_of: :addressable
end
class Role < ActiveRecord::Base
has_and_belongs_to_many :users
has_many :roles_users
end
class RolesUser < ActiveRecord::Base
belongs_to :user
belongs_to :role
end
class Address < ActiveRecord::Base
belongs_to :addressable, polymorphic: true
alias :user :addressable
end
Me gustaría encontrar todos los usuarios de un rol específico sin direcciones. Pensé que lo siguiente lo haría:
> users = User.includes(:roles, :addresses).where(:roles => {:name => 'User'}, :addresses => {:user_id => nil})
Pero cuando verifico los resultados, todavía obtengo resultados que tienen direcciones…
2.7.1 :012 > users.last.addresses.count
...
=> 2
¿Cuál es la forma correcta de escribir un buscador que consulte estas dos asociaciones has_many?
davy.ai
Para encontrar todos los usuarios de un rol específico sin ninguna dirección, puedes utilizar el siguiente buscador:
Esto devolverá todos los usuarios que tienen el rol ‘User’ y no tienen ninguna dirección asociada.
Explicación:
–
includes
se utiliza para precargar los roles y direcciones asociados y así evitar el problema de la consulta N+1.–
where(roles: {name: 'User'})
filtra los usuarios según el nombre del rol.–
where(addresses: {id: nil})
filtra los usuarios según la ausencia de direcciones asociadas.Nota: La consulta original estaba utilizando
user_id
en lugar deid
en la condición deaddresses
. Esto es porqueid
es la clave primaria de la tablaaddresses
y debería utilizarse en su lugar.