Kev*_*ker 1 ruby activerecord select ruby-on-rails
假设你有一个"作者"对象,它有几本书,你想要在模型中构建一些方法.您的基本设置如下所示:
class Author
def book_count(fiction = nil, genre = nil, published = nil)
end
end
Run Code Online (Sandbox Code Playgroud)
对于每个参数,您有几种方法可以操作:
fiction = true #retrieve all fiction books
fiction = false #retrieve all nonfiction
fiction = nil #retrieve books, not accounting for type
genre = nil #retrieve books, not accounting for genre
genre = some_num #retrieve books with a specific genre id
published = true #retrieve all published
published = false #retrieve all unpublished
published = nil #retrieve books, not accounting for published
Run Code Online (Sandbox Code Playgroud)
现在,我为其中的一些写了一个基本的select语句,类似于:
if published == true
return self.books.select{ |b| b.published == true }.size
elsif published == false
return self.books.select{ |b| b.published == false}.size
else
return self.books.size
end
Run Code Online (Sandbox Code Playgroud)
当我只有一两个论点时,这很笨拙,但很容易.但是,随着客户端请求向该方法添加更多条件,编写越来越繁琐.
处理这个问题最好的"轨道"方式是什么?
谢谢!
范围,(或"named_scopes",如果你使用Rails <3)可能是最好的方法.
以下是针对rails 3,但可以通过较小的语法调整来完成您可以在模型中创建一组范围.即
scope :with_genre, lambda {|genre| where(:genre => genre) unless genre.nil?}
scope :published, lambda{|published| where(:published => published) unless published.nil?}
scope :fiction,, lambda{|fiction| where(:fiction => fiction) unless fiction.nil?}
Run Code Online (Sandbox Code Playgroud)
等等
然后,无论何时需要访问它们,您都可以执行以下操作
def book_count(..)
self.books.with_genre(genre).published(published).fiction(fiction).size
end
Run Code Online (Sandbox Code Playgroud)
此外,您可以将book_count参数设置为哈希值,然后您可以拥有任意数量的选项,而无需使该函数具有大量参数.