Rails搜索多个条件(如果值不为空)
假设我有一个带有字段word_count
的模型Book
,可能还有很多其他类似字段。
在数据库的“高级搜索”中将条件串在一起的好方法是什么? 在上面的例子中,我有一个搜索表单,其中包含“ word count between ___ and ___
”框。 如果用户填写第一个框,那么我想要返回字数大于该值的所有图书; 同样,如果用户填写第二个框,那么我想要返回字数少于该值的所有书籍。 如果两个值都填入,那么我想返回该范围内的字数。
显然,如果我这样做
Book.where(:word_count => ..)
如果只填写其中一个字段,这将会中断。有没有办法优雅地处理这个问题? 请记住,可能存在许多类似的搜索条件,因此我不想为每种可能的组合构建单独的查询。
很抱歉,如果之前已经提出此问题,但搜索网站尚未产生任何有用的结果。
怎么样的:
@books = Book @books = @books.where("word_count >= ?", values[0]) if values[0].present? @books = @books.where("word_count <= ?", values[1]) if values[1].present?
ActiveRecord将链接where子句
唯一的问题是,如果值[0] &&值[1],如果值[0]大于值[1],查询将不返回任何内容。
对于我们的高级搜索,我们创建了一个filter对象,它将activerecord查询封装到简单的方法中。 它最初基于这个Thoughtbotpost
书籍filter看起来像这样:
class BookFilter def initialize @relation = Book.scoped end def restrict(r) minimum_word_count!(r[:first]) if r[:first].present? maximum_word_count!(r[:second]) if r[:second].present? recent! if r.try(:[], :recent) == '1' @relation end protected def recent! where('created_at > ? ', 1.week.ago) end def minimum_word_count!(count) where('word_count >= ? ', count) end def maximum_word_count!(count) where('word_count <= ?', count) end def where(*a) @relation = @relation.where(*a) end end #to use books = BookFilter.new.restrict(params)
看一下ransack gem,它是meta_search gem的inheritance者,它似乎仍然拥有更好的文档。
如果您确实想要自己滚动,那么没有什么可以阻止您使用相同的属性链接子句:
scope = Book scope = scope.where("word_count >= ?", params[:first]) if params[:first] scope = scope.where("word_count <= ?", params[:last]) if params[:last]
但是真的没有必要推出自己的搜索,有很多现成的解决方案,如上面的gem。