按多个字段过滤项目

时间:2017-06-21 16:21:11

标签: ruby-on-rails

按标题,created_at日期过滤项目,但其中一个是空的,它会引发错误,我该如何处理?

where("country_translations.title ILIKE ? AND country_translations.created_at > ? AND country_translations.created_at < ?", "%#{search[:title]}%", search[:created_at_gt], search[:created_at_lt])

4 个答案:

答案 0 :(得分:1)

您可以这样做:

YourModel.where(filter_by_translations_title).where(filter_by_translations_created)

def filter_by_translations_title
  ['country_translations.title ILIKE ?', search[:title]] if search[:title].present?
end
#...add rest of methods here

链接#where将通过AND加入所有查询。这种方式允许您根据需要添加任意数量的子问题,并控制其行为。

答案 1 :(得分:1)

您可以非常轻松地链接where条款。

@results = Model.all
@results = @results.where('country_translations.title ILIKE ?', "%#{search[:title]}%") if search[:title].present?

如果您正在使用Postgres,您还可以使用正则表达式而不是ILIKE来删除此%#{}%内容。

@results = @results.where('country_translations.title ~* ?', search[:title]) if search[:title].present?

以及其他领域。

答案 2 :(得分:1)

这实际上取决于你想如何处理它。

首先,我将查询分解为多个where,默认为AND操作。这是为了便于阅读:

Model.where("country_translations.title ILIKE ?", "%#{search[:title]}%")
     .where("country_translations.created_at > ?", search[:created_at_gt])
     .where("country_translations.created_at < ?", search[:created_at_lt])

您可以使用||运算符传递默认值,如下所示:

Model.where("country_translations.title ILIKE ?", "%#{search[:title] || ''}%")
     .where("country_translations.created_at > ?", search[:created_at_gt] || Time.now)
     .where("country_translations.created_at < ?", search[:created_at_lt] || Time.now)

或者您可以将其拆分为三个必须仅在需要时应用的过滤器:

query = Model.all
query = query.where("country_translations.title ILIKE ?", "%#{search[:title]}%") if search[:title]
query = query.where("country_translations.created_at > ?", search[:created_at_gt]) if search[:created_at_gt]
query = query.where("country_translations.created_at < ?", search[:created_at_lt]) if search[:created_at_lt]

# query now is filtered only with present filters.

答案 3 :(得分:1)

在这种情况下你总是可以使用范围,它们几乎无处不在

scope :filter_by_title, -> (title) { where('title ILIKE ?', "%#{title}%") if title.present? }
scope :filter_by_created_at_lt, -> (date) { where('created_at < ?', date) if date.present? }
scope :filter_by_created_at_gt, -> (date) { where('created_at > ?', date) if date.present? }

然后您可以将查询重组为

Model.filter_by_title(search[:title])
     .filter_by_created_at_lt(search[:created_at_lt])
     .filter_by_created_at_gt(search[:created_at_gt])