2009-10-05 9 views
0

j'ai 4 modèles, Message, groupe, utilisateur, membresrails has_many - trop de requêtes

class Group < ActiveRecord::Base 
    has_many :memberships 
    has_many :users, :through => :memberships 
    has_many :groups_messages 
    has_many :messages, :through => :groups_messages, :order => "created_at desc" 

    named_scope :with_memberships, :include => :memberships 

end 

class Membership < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :group 
end 

class User < ActiveRecord::Base 
    has_many :memberships 
    has_many :groups, :through => :memberships 
end 

class Message < ActiveRecord::Base 
    has_and_belongs_to_many :recipients, :class_name => "User" 
    has_many :groups_messages 
    has_many :groups, :through => :groups_messages 

    def accessible 
    self.groups.with_memberships.map(&:user_ids).include?(User.current.id) 
    end 

end 

message peut être affiché à un groupe, et si l'utilisateur actuel est membre du groupe, il a un droit de le lire.

Je suis en train de vérifier si l'utilisateur est un membre du groupe avec Message.accessible, mais il produit une requête à beaucoup:

Group Load (0.1ms) SELECT `groups`.* FROM `groups` INNER JOIN `groups_messages` ON `groups`.id = `groups_messages`.group_id WHERE ((`groups_messages`.message_id = 381)) AND ((`groups_messages`.message_id = 381)) 
Membership Load (0.1ms) SELECT `memberships`.* FROM `memberships` WHERE (`memberships`.group_id = 1) 
User Load (0.1ms) SELECT `users`.id FROM `users` INNER JOIN `memberships` ON `users`.id = `memberships`.user_id WHERE ((`memberships`.group_id = 1)) 

Je ne ai pas besoin utilisateur requête de charge - user_id est contenue dans L'adhésion, donc la dernière requête est inutile.

J'ai essayé de changer la méthode accessible à

def accessible 
    self.groups.with_memberships.exists?(:user_id=>User.current.id) 
end 

Mais il essaie d'utiliser user_id dans la requête de charge du groupe et bien sûr échoue. Comment puis-je me débarrasser de la dernière requête? Rails 2.3.2

+0

'has_many: requêtes' –

Répondre

0

après rails meilleure compréhension, Je compris que ce qui se passait à cause de carte (&: user_ids) dans

def accessible 
    self.groups.with_memberships.map(&:user_ids).include?(User.current.id) 
end 

ce comportement était absolument pas rMal, mon erreur était que je m'y attendais à se comporter comme groups.membership_user_ids, et il se comportait comme groups.user_ids

fixes en changeant à

def accessible 
Membership.exists?(["user_id=? and group_id in (?)",User.current.id,self.group_ids]) 
end 

fait la partie comprennent? (User.current.id) ne fonctionnait même pas pour une raison quelconque.

0

Je pense que la requête sur les utilisateurs est provoquée par l'appel à User.current.id. Pouvez-vous essayer de passer un paramètre à la méthode accessible?

def accessible_to(user) 
    self.groups.with_memberships.map(&:user_ids).include?(user.id) 
end 

Je suppose que ce sera appelé à partir d'un contrôleur, où current_user est (par convention) ensemble, donc dans une action de contrôleur que vous feriez quelque chose comme:

@message.accessible_to(current_user) 
+1

Malheureusement, ce n'est pas le cas. User.current.id est configuré bien avant (mais j'ai essayé de le changer juste au cas où - ne fonctionnait pas). Veuillez noter que la requête inutile charge les utilisateurs qui ont des appartenances à un groupe. Dans ce cas, Message appartient à Group avec id = 1, donc il charge les utilisateurs qui sont membres du groupe avec id = 1. –

+0

Bon point. Que faire si vous demandez à l'utilisateur ses messages, au lieu des messages accessibles à un utilisateur: current_user.groups.messages – hgmnz

Questions connexes