【问题标题】:Rails 4 ActiveRecord scope to query different date field based on whether it existsRails 4 ActiveRecord范围根据是否存在查询不同的日期字段
【发布时间】:2016-10-25 03:03:49
【问题描述】:

我有一个包含许多日期字段的 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

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

即我希望能够在 Voyage 上有一个范围,可以执行以下操作:

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

【问题讨论】:

  • 您的意思是将日期作为范围内的参数传递?
  • 不,我不这么认为。我想查询字段ada如果不是nil,否则updated_ada如果不是nil,否则eda然后如果是过去。

标签: ruby-on-rails activerecord active-record-query


【解决方案1】:

为了满足您的要求,还需要做一些额外的工作。

范围方法,

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  }

【讨论】:

  • 我认为范围不起作用,我在运行第二个语句时收到错误 NoMethodError: undefined method 'calc_arrival_date' for #&lt;Voyage:0x000000068ceaa0&gt;。如果我做Voyage.archived.to_sql 我得到"SELECT \"voyages\".* FROM \"voyages\" INNER JOIN \"voyage_legs\" ON \"voyage_legs\".\"voyage_id\" = \"voyages\".\"id\" AND \"voyage_legs\".\"deleted_at\" IS NULL WHERE \"voyages\".\"deleted_at\" IS NULL AND (voyage_legs.ada &lt; '2016-10-25 19:19:53.640705')" 所以它没有在选择中执行SQL。
【解决方案2】:

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

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)这样的航行

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多