假设我有一个带有字段Book
的模型word_count
,可能还有很多其他类似的字段。
对我来说,在数据库的“高级搜索”中将条件串起来有什么好方法?在上面的例子中,我有一个带有“word count between ___ and ___
”框的搜索表单。如果用户填写第一个框,那么我想要返回字数大于该值的所有图书;同样,如果用户填写第二个框,那么我想要返回字数少于该值的所有书籍。如果两个值都被填入,那么我想返回该范围内的字数。
显然,如果我这样做
Book.where(:word_count => <first value>..<second value>)
如果只填写其中一个字段,则会中断。有没有办法优雅地处理这个问题?请记住,可能存在许多类似的搜索条件,因此我不想为每种可能的组合构建单独的查询。
很抱歉,如果之前已经提出此问题,但搜索网站尚未产生任何有用的结果。
答案 0 :(得分:1)
如下:
@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]&amp;&amp;值[1]如果值[0]大于值[1],查询将不返回任何内容。
答案 1 :(得分:1)
对于我们的高级搜索,我们创建了一个过滤器对象,它将activerecord查询封装到简单的方法中。它最初基于此Thoughtbot post
图书过滤器可能如下所示:
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)
答案 2 :(得分:0)
看一下ransack gem,它是meta_search gem的继承者,它似乎仍然有更好的文档。
如果您确实想要自己推送,那么没有什么能阻止您使用相同的属性来链接子句:
scope = Book
scope = scope.where("word_count >= ?", params[:first]) if params[:first]
scope = scope.where("word_count <= ?", params[:last]) if params[:last]
但是真的没有必要推出自己的搜索,有很多现成的解决方案,如上面的宝石。