【问题标题】:Rails query: Compare calculation of two attribute valuesRails查询:比较两个属性值的计算
【发布时间】:2014-09-28 17:16:39
【问题描述】:

我有一个模型 Product,它同时具有 :created_at 时间戳和 :expiration_in_days 属性。产品在创建后的特定天数被视为过期。如何编写只返回未过期产品的查询?

Rails 4、Ruby 2.1、PG 0.17

我一直在尝试这样的查询,但没有成功:

#product.rb
def self.not_expired
  where('created_at + expiration_in_days * 86400 >= ?', Time.now)
end

我有一个运行良好的纯 Ruby 版本,只是速度较慢:

#product.rb
def self.not_expired
  select{ |p| (p.created_at.to_i + p.expiration_in_days * 86400) >= Time.now.to_i}
end
  • 注意,86400 计算将 :expiration_in_days 整数转换为秒

任何关于比文档 (http://guides.rubyonrails.org/active_record_querying.html) 更高级的 Rails 查询的指针也非常受欢迎。

提前致谢。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4 postgresql-9.1 ruby-2.1


    【解决方案1】:

    试试这个:

    def self.not_expired
      where("created_at + (expiration_in_days * 86400)::text::interval >= ?", Time.now)
    end
    

    更新:添加引用

    您可以了解更多关于日期和时间功能here

    鉴于您的案例有特殊要求,即expiration_in_days的值是表中的一列,我们不能使用created_at + interval expiration_in_days day。相反,我们需要将type cast 的值改为interval。但是您不能直接将类型转换为整数,这就是我们首先将其转换为 text 的原因。

    【讨论】:

    • 测试通过了,这行得通。谢谢你。不过,我完全不知道我会在哪里学会这样做。对这方面的资源有什么建议吗?
    • 嗨@steel,我已经用一些参考资料更新了答案。 HTH!
    【解决方案2】:

    我不确定这是否可行,但请尝试类似的方法

    def self.not_expired
      where("TIMESTAMP created_at + INTERVAL '1 day' * expiration_in_days >= NOW()")
    end
    

    【讨论】:

      【解决方案3】:

      A + B > 如果 A

      因此,与其尝试将过期时间添加到 created_at,不如从 Time.now 中减去过期时间。

      def expiration_threshold
        Time.now - amount_of_time # I'm not sure what type to use
      end
      
      def self.not_expired
        where( "created_at > ? ", expiration_threshold )
      end
      

      我一直对 Rails/Ruby 在处理各种日期/时间时需要什么类型感到有些困惑,你可能不得不玩弄。

      【讨论】:

      • 问题是每条记录的过期阈值都不同。我不确定这是如何解决这个问题的。
      • 啊哈。这是我的解决方案的问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-27
      • 2019-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-20
      相关资源
      最近更新 更多