Требует ли написание расширений has_many для ActiveRecord базы данных? - PullRequest
0 голосов
/ 21 сентября 2010

Если у меня есть что-то вроде этого:

class Post < ActiveRecord::Base
  has_many :comments, :as => :commentable do
    def approved
      find(:all, :conditions => {:approved => true})
    end
  end
end

class Comment < ActiveRecord::Base
  belongs_to :commentable, :polymorphic => true
end

... когда я делаю это, я получаю 2 попадания в базу данных (не считая нахождения сообщения: p):

post = Post.first
post.comments #=> [Comment1, Comment2...]
post.comments.approved #=> [Comment1, Comment7...]

Кажется, он должен просто фильтровать текущий массив комментариев в памяти, нет? Это делает это? Я спрашиваю причину, потому что консоль показывает SELECT * FROM ... на post.comments.approved, хотя я уже звонил post.comments. Разве это не должно быть лучше оптимизировано в ActiveRecord?

Ответы [ 3 ]

1 голос
/ 21 сентября 2010

AR выполняет новый запрос для любых вызовов поиска в методе расширения ассоциации.Вы можете обратиться к кешированному набору результатов, используя self.

  has_many :comments, :as => :commentable do
    def approved
      # uses the cached result set
      self.select{|c| c.approved == true}
    end
  end
1 голос
/ 21 сентября 2010

Это необязательно, так как в некоторых случаях вы можете загружать связанные объекты только при необходимости. Если вы хотите, чтобы все они были загружены в память, вам нужно явно объявить объекты, которые вы хотите включить в начальный запрос, используя флаг: include. Пример:

post = Post.find(:first, :include => :comment)

Возможно, вам придется переписать ваше расширение, чтобы воспользоваться преимуществом этой функции ... подход будет состоять в том, чтобы изменить вашу "утвержденную" функцию, чтобы перебирать массив комментариев, прикрепленный к каждому сообщению, и возвращать новый массив с неутвержденными комментариями отфильтрованы Определенная вами «находка» явно возвращается в базу данных.

0 голосов
/ 21 сентября 2010

Если ваш запрос действительно такой простой, то вам нужна именованная область:

class Comment
  named_scope :approved, :conditions => {:approved => true}
end

Затем вы можете сделать:

@post.comments.approved.count #=> 1 DB hit!
@post.comments.count #=> Another DB hit - can't reuse same scope

Посмотрите на # scope (#named_scope в Rails 2.3).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...