【问题标题】:Rails refactoring long where conditionsRails 重构 long where 条件
【发布时间】:2022-11-18 03:26:01
【问题描述】:

我不喜欢传递多个重复的参数,它看起来有点难看。
我该如何重构以下代码?

 prev_month_start = Date.today.prev_month.beginning_of_month
 prev_month_end = Date.today.prev_month.end_of_month
    
 contacts = contacts.where('
   persons.actual_delivery_date >= ? AND persons.actual_delivery_date <= ? OR 
   persons.expected_shipment_date >= ? AND persons.expected_shipment_date <= ?', 
   prev_month_start, prev_month_end, 
   prev_month_start, prev_month_end)

【问题讨论】:

  • 这里重构的最终目标是什么?有很多方法可以考虑重构它,但我可能会从有意义的范围开始(例如,delivered_last_monthshipment_expected_last_month 等)。
  • contacts是怎么组成的? Person 是生成contacts 变量的模型吗?就像contacts = Person.all。还是persons表是联合表?例如。 contracts = Contract.all.joins(:person)。您能否为我们提供更多背景信息? persons 表与contacts 范围有什么关系?

标签: ruby-on-rails ruby


【解决方案1】:

您可以在 ActiveRecord 5 及更高版本中尝试类似的操作:

contacts.where(actual_delivery_date: prev_month_start..prev_month_end).or(expected_shipment_date: prev_month_start..prev_month_end) 

https://guides.rubyonrails.org/active_record_querying.html#range-conditions

基于cmets编辑

【讨论】:

  • Rails 5 支持 or 所以可以这样做:
  • @TaimoorHassan 你不能像那样使用 or 因为 or 需要一个可合并的 AR::Relation 所以它更像是 contacts.where(actual_delivery_date: prev_month_start..prev_month_end).or(contacts.where(expected_shipment_date: prev_month_start..prev_month_end))
【解决方案2】:

在这种情况下,您可以将日期范围 (all_month) 与 or condition 结合使用:

prev_month = Date.today.prev_month.all_month
contacts = contacts
  .where(persons: { actual_delivery_date: prev_month })
  .or(contacts.where(persons: { expected_shipment_date: prev_month }))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-09
    • 1970-01-01
    • 1970-01-01
    • 2011-05-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多