Rails 4 ActiveRecord 范围根据是否存在查询不同的日期字段

Rails 4 ActiveRecord scope to query different date field based on whether it exists

我有一个包含许多日期字段的 VoyageLeg 模型。我有一个如下所示的实例方法,可以根据日期是否已填充来获取其中一个日期:

def calc_arrival_date
  if ada
    ada #return actual date of arrival
  elsif updated_eda
    updated_eda #return updated estimated date of arrival
  else
    eda #return estimated date of arrival
  end
end

我还有一个 has_many voyage_legs 的 Voyage 型号。我将如何在 Voyage 模型上创建范围将引用 calc_arrival_date,或者关于在范围中查询哪个日期执行相同的逻辑?

即我希望能够在 Voyage 上有一个可以做类似事情的范围:

scope :archived, -> { joins(:voyage_legs).where("voyage_legs.calc_arrival_date < ?", Time.zone.now) }

为了达到您的要求,还有一些额外的工作要做。

范围方法,

scope :archived, -> {joins(:voyage_legs).select('(CASE WHEN voyage_legs.ada IS NOT NULL THEN voyage_legs.ada WHEN voyage_legs.updated_eda IS NOT NULL THEN voyage_legs.updated_eda WHEN voyage_legs.ada IS NULL and voyage_legs.updated_eda IS NULL THEN voyage_legs.eda END) as calc_arrival_date')}

并对结果进行一些计算,

result = Voyage.archived.select { |b| b.calc_arrival_date.to_datetime < Time.zone.now  }

我最终使用了你的部分代码@Shabini Rajadas,但将逻辑中的日期子句组合为 VoyageLeg 模型上的 class 方法,如下所示:

def self.departed
  where("CASE WHEN voyage_legs.add IS NOT NULL THEN
      voyage_legs.add < :now
    WHEN voyage_legs.updated_edd IS NOT NULL THEN
      voyage_legs.updated_edd < :now
    WHEN voyage_legs.add IS NULL and voyage_legs.updated_edd IS NULL THEN
      voyage_legs.edd  < :now END", now: Time.zone.now.to_date)
end

然后我可以像 Voyage.joins(:voyage_legs).merge(VoyageLeg.departed)

这样过滤 Voyages