2012-06-25 4 views
2

Что бы лучший способ смоделировать следующую ситуацию: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 

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

Возможно ли это?

ответ

6

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

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

Спасибо, это прекрасно. Не могли бы вы объяснить, что означает '= nil if reload'? Большое спасибо. – umezo

+1

Объект 'Story' кэширует результаты в переменной экземпляра, называемой' @ words'. В определенных сценариях вы можете захотеть перекрыть кеш. Вы можете сделать это, передав значение 'true' для параметра' reload'. –

+0

О, я вижу, спасибо. Я вижу, что было бы неплохо иметь эту возможность для доступа с консоли или рейк-задачи, если возникнет такая необходимость. – umezo

0

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

def words 
    ([] << lines.collect {|line| line.words} << phrases.collect {|phrase| phrase.words}).flatten 
end 
+0

Спасибо, переключение с полиморфного на отношение через фразы_ид и line_id в Word-модель - плохая идея? – Stpn

+0

С полиморфным отношением вы сможете легко добавить новый Wordable. С вашим вторым предложением вам потребуется переход, чтобы добавить столбец для каждого нового словаря WordBox – Baldrick

+0

, так как вы были первыми, я буду принимать это как ответ. – Stpn

Смежные вопросы