Rails has_many через has_many с несколькими моделями

Как лучше смоделировать следующую ситуацию:

Word
  belongs_to :wordable, :polymorphic => true


Phrase
  has_many :words, :as => :workable
  belongs_to :story

Line
  has_many :words, :as => :wordable    
  belongs_to :story


Story
 has_many :lines      
 has_many :phrases
 has_many :words, :through => :phrases
 has_many :words, :through => :lines

я хочу уметь делать

 @story.words 

чтобы получить список всех слов, которые связаны с историей либо строками, либо фразами...

Это возможно?


person Stpn    schedule 25.06.2012    source источник


Ответы (2)


Попробуй это:

class Story

  has_many :lines      
  has_many :phrases

  def words(reload=false)
    @words = nil if reload
    @words ||= Word.where("(wordable_type = ? AND wordable_id IN (?)) OR
                            (wordable_type = ? AND wordable_id IN (?))", 
                           "Phrase", phrase_ids, "Line", line_ids)    
  end
end

Сейчас

story.words # returns line and phrase words
story.words.limit(5) 
person Harish Shetty    schedule 25.06.2012
comment
Спасибо, это идеально. Не могли бы вы объяснить, для чего нужен = nil if reload? Спасибо большое. - person umezo; 06.05.2013
comment
Объект Story кэширует результаты в переменной экземпляра с именем @words. В некоторых сценариях вы можете захотеть разорить кеш. Вы можете сделать это, передав значение true для параметра reload. - person Harish Shetty; 06.05.2013
comment
О, понятно, спасибо. Я вижу, что было бы неплохо иметь эту опцию для доступа из консоли или задачи rake, если возникнет необходимость. - person umezo; 06.05.2013

Вы можете удалить отношения 2 has_many :words, :through => XXX из класса Story и вместо этого определить метод words:

def words 
  ([] << lines.collect {|line| line.words} << phrases.collect {|phrase| phrase.words}).flatten
end
person Baldrick    schedule 25.06.2012
comment
Спасибо, переключаться с полиморфного на отношение через фразу_id и строку_ид в модели Word - плохая идея? - person Stpn; 25.06.2012
comment
С полиморфным отношением вам будет проще добавить новый Wordable. С вашим вторым предложением вам понадобится миграция, чтобы добавить столбец для каждого нового Wordable - person Baldrick; 25.06.2012
comment
спасибо, так как вы были первым, я приму это как ответ. - person Stpn; 26.06.2012
comment
@stpn, вы не сможете связать sql и разбить набор результатов на страницы, когда вы добавляете списки в Ruby (а не в SQL). - person Harish Shetty; 26.06.2012
comment
@stpn Решение KandadaBoggu лучше. - person Baldrick; 26.06.2012
comment
хорошо, думаю, я почитаю об этом больше .. принимая ответ KandadaBoggu сейчас, большое спасибо. - person Stpn; 26.06.2012