rails has_many - слишком много запросов - PullRequest
0 голосов
/ 05 октября 2009

У меня 4 модели, Сообщение, Группа, Пользователь, Членство

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.accessible, но он выдает один запрос на много:

 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)) 

Мне не нужен запрос User Load - user_id содержится в Membership, поэтому последний запрос бесполезен.

Я попытался изменить доступный метод на

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

Но затем он пытается использовать user_id в запросе на групповую загрузку и, конечно же, терпит неудачу. Как я могу избавиться от последнего запроса? Рельсы 2.3.2

Ответы [ 2 ]

0 голосов
/ 19 января 2010

после лучшего понимания рельсов я понял, что это происходит из-за карты (&: user_ids) в

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

это поведение было абсолютно нормальным, моя ошибка была в том, что я ожидал, что он будет вести себя как groups.membership_user_ids , и он вел себя как groups.user_ids

исправлено путем изменения на

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

на самом деле часть include? (User.current.id) даже по какой-то причине не работала.

0 голосов
/ 05 октября 2009

Я думаю, что запрос пользователей вызван вызовом User.current.id. Можете ли вы попробовать передать параметр доступному методу?

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

Полагаю, это будет вызвано из контроллера, где установлен current_user (по соглашению), поэтому в некоторых действиях контроллера вы должны сделать что-то вроде:

@message.accessible_to(current_user)
...