es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

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?

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para encontrar todos los usuarios de un rol específico sin ninguna dirección, puedes utilizar el siguiente buscador:

    users = User.includes(:roles, :addresses).where(roles: {name: 'User'}).where(addresses: {id: nil})
    

    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 de id en la condición de addresses. Esto es porque id es la clave primaria de la tabla addresses y debería utilizarse en su lugar.

Comments are closed.