2017-02-09 143 views
2

想象一本書和一章模型。每章belongs_to :book,和一本書has_many :chapters。我們在章節中有範圍,例如:very_long返回超過300頁的章節。belongs_to協會的Rails範圍

很多時候,我們想要獲得所有書籍的任何章節超過300頁。通常我們實現這一目標的方式是像這樣:

# book.rb 
scope :has_very_long_chapter, -> { where(id: Chapter.very_long.select(:book_id) } 

然而,正如你可以想像,它變得相當乏味的代理,我們希望通過本章範圍篩選圖書每次範圍。有沒有更多的慣用或更清潔的方式來實現這一目標?

回答

-1

我認爲有一兩件事你可以做的是使用joins/merge

class Book < ARBase 
    scope :with_long_chapters, ->{ joins(:chapter).merge(Chapter.very_long) } 
end 

class Chapter < ARBase 
    scope :very_long, -> { logic for querying chapters with over 300 pages } 
end 

EDIT(#2):更可重複使用的範圍

class Book < ARBase 
    scope :by_chapter_page_count, ->(pages){ joins(:chapter).merge(Chapter.by_page_count pages) } 
    scope :with_climax, -> { joins(:chapter).merge(Chapter.by_category :climax) } 

    scope :long_with_climax, -> { by_chapter_page_count(400).with_climax } 
end 

class Chapter < ARBase 
    scope :by_page_count, ->(pages) { where("pages > ?", pages } 
    scope :by_category, ->(category) { where category: category } 
end 

Book.by_chapter_page_count(100) 

你可以得到你如何寫相當的創意你的示波器

+1

這是一個更清潔一點,但它不能解決每次我想重新使用子模型時必須編寫新範圍的問題。 – jtmarmon

+0

@jtmarmon你能澄清你的意思嗎?每次你想重新使用子模型時,你需要編寫一個新的範圍。我不太確定我是否明白你的意思。如果你想有不同的查詢,你將不得不定義新的範圍。 – Sean

+0

@jtmarmon讓我稍微修改我的答案,看看我們是否可以使範圍更加可重用。 – Sean