更好地解决“一个,另一个或两个”案例

时间:2018-05-15 07:35:40

标签: ruby-on-rails ruby conditional

我正在检查一些代码,类似于以下内容出现了:

def between_dates(date_1, date_2)
  if date_1 && date_2
    conditions "created_at >= date_1 AND created_at <= date_2"
  elseif date_1
    conditions "created_at >= date_1"
  elseif date_2
    conditions "created_at <= date_2"
  end
end

它看起来像是可以改进的代码,但我找不到更优雅的解决方案来处理这样一个简单而常见的条件语句。

当我们必须为一个,另一个或两者返回一个值时,我正在寻找一个更好的答案。

4 个答案:

答案 0 :(得分:9)

Rails允许您动态构建查询。这是使用scopes和类方法的示例。由于范围始终返回ActiveRecord::Relation对象(即使块返回nil),它们也是可链接的:

class Event < ApplicationRecord
  scope :created_before, -> (date) { where('created_at <= ?', date) if date }
  scope :created_after,  -> (date) { where('created_at >= ?', date) if date }

  def self.created_between(date_1, date_2)
    created_after(date_1).created_before(date_2)
  end
end

使用示例:

Event.created_between(nil, Date.today)
# SELECT `events`.* FROM `events` WHERE (created_at <= '2018-05-15')

Event.created_between(Date.yesterday, nil)
# SELECT `events`.* FROM `events` WHERE (created_at >= '2018-05-14')

Event.created_between(Date.yesterday, Date.today)
# SELECT `events`.* FROM `events` WHERE (created_at >= '2018-05-14') AND (created_at <= '2018-05-15')

答案 1 :(得分:5)

我会用这样的东西:

def between_dates(date_1, date_2)
  parts = []

  if date_1
    parts << "created_at >= date_1"
  end

  if date_2
    parts << "created_at <= date_2"
  end

  full = parts.join(' AND ')
  conditions(full)
end

这可以通过多种方式进一步美化,但你明白了。

答案 2 :(得分:4)

def between_dates(date_1, date_2)
  date_conditions = []
  date_conditions << 'created_at >= date_1' if date_1
  date_conditions << 'created_at <= date_2' if date_2
  conditions date_conditions.join(' AND ') unless date_conditions.empty?
end

答案 3 :(得分:2)

我不确定这是否更优雅,但我总是reduce一切都是为了避免拼写错误:

[[date_1, '>='], [date_2, '<=']].
  select(&:first).
  map { |date, sign| "created_at #{sign} #{date}" }.
  join(' AND ')