Rails: структурирование запроса с участием полиморфной ассоциации и STI - PullRequest
4 голосов
/ 05 июля 2011

Я пытаюсь найти 10 самых последних комментариев к фотографиям, чтобы я мог интегрировать их в ленту активности в своем приложении Rails 3.0.3.

У меня есть Фотография модель, которая наследуется от модели Upload , использующей наследование одной таблицы:

class Upload < ActiveRecord::Base
    ...
end

class Photo < Upload
    has_many :comments, :as => :commentable
    ...
end

Полиморфная ассоциация commentable описана в Comment модель:

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

Пока все хорошо, верно?Проблема возникает, когда я пытаюсь построить запрос.После некоторых проб и ошибок я пришел к этому коду, который находится в модели Photo:

def self.latest_comments(count = 10)
    Comment.where(:commentable_type => "Upload")\
       .joins("INNER JOIN uploads ON comments.commentable_id = uploads.id")\
       .where("uploads.type" => "Photo").order("comments.created_at DESC").limit(count)
end

Этот код работает на моей машине разработки с SQLite, но мне пришлось внести некоторые изменения, чтобы получить егоработать на производственном сервере, используя PostgreSQL.Вышеупомянутое воплощение запроса еще не было протестировано на производственном сервере, но я искал более чистый способ структурирования запроса, так как вышеприведенный вариант не выглядит слишком устойчивым и не выглядит очень «Railsy».

То, что я хотел бы сказать - это

Comment.joins(:commentable => :photo)

... но это вызывает исключение, вероятно, потому что Rails не знает, как сделать соединение:

ActiveRecord :: EagerLoadPolymorphicError: Невозможно загрузить полиморфную ассоциацию: commentable

Я наткнулся на сообщение в StackOverflow , в котором описан другой способ запросаполиморфная ассоциация.Я смог придумать следующий код, основанный на этом посте:

Comment.find_all_by_commentable_type("Upload", :include => :commentable,
        :order => "created_at DESC", :limit => 10)

Однако это не работает для STI: так как Photo наследуется от Upload, я не могу напрямую получить комментарии, относящиеся кк фотографиям - только комментарии для всех классов, унаследованных от Upload.

Я просмотрел немало других постов, касающихся либо полиморфизма, либо ИППП, но ни один из них не совмещает то, что я ищу.Я мог бы просто запутаться с начальным запросом, но есть ли у кого-нибудь мысли об альтернативных способах структурирования запроса, включающего полиморфизм и STI?

Edit : я нашел другой вопрос здесь по той же схеме, что и у меня.К сожалению, топовый ответ не дал решения, которое я ищу.Если бы я применил это к моей проблеме, я бы переместил ассоциацию has_many :comments из модели Photo в модель Upload и добавил бы некоторый код в класс Comment, чтобы определить правильный класс commentable.Это не идеально, так как это нарушает моделирование, так как любой подкласс Upload будет иметь комментарии.Должен быть лучший способ ...?

1 Ответ

1 голос
/ 10 июля 2011

Вы предоставляете ассоциацию для комментариев в классе Upload. Фотография, которая наследуется от Upload, будет связана с наследованием. Поскольку метод комментариев доступен как для экземпляра Upload, так и для экземпляра Photo, вы можете написать следующий метод для получения комментариев:

# app/models/upload.rb

def latest_comments(count=10)
  self.comments.order("created_at DESC").limit(count)
end

Это присоединится к таблице комментариев, используя тип «Upload» при работе с экземпляром Upload, и будет присоединено с использованием типа «Photo» при работе с экземплярами этого класса. Rails автоматически обрабатывает соединение с таблицей комментариев, используя имя класса, когда проходит через связь комментариев.

...