11

tengo 2 modelos:rieles HABTM y la búsqueda de registro con ninguna asociación

class User < ActiveRecord::Base 
    has_and_belongs_to_many :groups 
end 

class Group < ActiveRecord::Base 
    has_and_belongs_to_many :users 
end 

Quiero hacer un alcance (eso es importante - para la eficiencia y de capacidad de los alcances de la cadena) que devuelve Usuarios Eso no t pertenece al CUALQUIER Grupos. Después de muchos intentos, fallé al hacer un método en lugar de scope, lo que hace que collect en User.all sea feo y ... no correcto.

¿Algún ayuda?

Y tal vez para la 2da pregunta: Me las arreglé para hacer un ámbito que devuelve los usuarios que pertenecen a cualquiera de los grupos determinados (dado como una matriz de id).

scope :in_groups, lambda { |g| 
     { 
      :joins  => :groups, 
      :conditions => {:groups => {:id => g}}, 
      :select  => "DISTINCT `users`.*" # kill duplicates 
     } 
     } 

¿Puede ser mejor/más bonito? (usando Rails 3.0.9)

Respuesta

17

Su tabla de unión implícita se habría denominado groups_users según las convenciones de nomenclatura. Confirma una vez en tu db. Suponiendo que es:

En una versión más nueva Rieles:

scope :not_in_any_group -> { 
    joins("LEFT JOIN groups_users ON users.id = groups_users.user_id") 
    .where("groups_users.user_id IS NULL") 
} 

Para versiones anteriores de Rails:

scope :not_in_any_group, { 
    :joins  => "LEFT JOIN groups_users ON users.id = groups_users.user_id", 
    :conditions => "groups_users.user_id IS NULL", 
    :select  => "DISTINCT users.*" 
} 
+0

gracias, hizo el truco :) – schiza

+1

¿Necesitarías DISTIN? CT en este caso donde no existiría una relación de unión para los resultados devueltos, y por lo tanto no se repetirían los usuarios? –

+0

'DISTINCT' no es necesario. Agregué la nueva sintaxis requerida para Rails 4 y superior (creo). – slhck

2

Si convierte de HABTM a has_many través de la asociación (más flexible), entonces usted puede utilizar algo como esto:

class Group < ActiveRecord::Base 
    has_many :groups_users, dependent: :destroy 
    has_many :users, through: :groups_users, uniq: true 

    scope :in_groups, -> { includes(:groups_users).where(groups_users: {group_id: nil}) } 
end 

class User < ActiveRecord::Base 
    has_many :groups_users, dependent: :destroy 
    has_many :groups, through: :groups_users 
end 

class GroupsUser < ActiveRecord::Base 
    belongs_to :group 
    belongs_to :user 
end 
Cuestiones relacionadas