【问题标题】:Apply the same chain of arel clauses to different relations将相同的 arel 子句链应用于不同的关系
【发布时间】:2015-01-08 03:52:04
【问题描述】:

我有两个 ActiveRecord 关系,分别称为 rel1rel2。它们每个都添加了各种不同的joinswhere 子句。

我想对它们中的每一个应用一个特定的相同序列的子句,我不想​​重复自己。

一种方法是创建一个函数:

def without_orders rel
   rel.joins("LEFT JOIN orders ON customers.id = orders.customer_id").where("customers.id IS NULL")
end

rel1 = Customer
rel2 = Customer

# add a bunch of clauses to rel1
# add some other clauses to rel2

rel1 = without_orders(rel1)
rel2 = without_orders(rel2)

理想情况下,我不会将 without_orders 作为单独的函数。我会以某种方式将joinswhere 放在func 的本地,然后将其应用于rel1rel2

这可能吗?如果不是,这里的正确方法是什么?

【问题讨论】:

    标签: sql ruby-on-rails activerecord arel


    【解决方案1】:

    您可以将它们全部放入单独的范围:

    scope :without_orders, -> { joins("LEFT JOIN orders ON customers.id = orders.customer_id").where(customers: { id: nil }) }
    

    然后你可以将它与其他作用域链接起来。

    Customer.without_orders.where(foo: bar)
    

    【讨论】:

      【解决方案2】:

      这是积极支持关注点的良好候选者

      # app/models/concerns/customer_related.rb
      
      module CustomerRelated
      
        extend ActiveSupport::Concern
      
        module ClassMethods
      
          def whithout_orders
            joins("LEFT JOIN orders ON customers.id = orders.customer_id").where("customers.id IS NULL")
          end
      
        end
      
      end
      

      然后在你的模型中包含它:

      include CustomerRelated
      

      然后您可以在任何包含关注点的模型上像范围一样使用它

      Rel1.without_orders
      

      Rel2.without_orders
      

      【讨论】:

      • 谢谢。这种方法比 evanbikes 建议的方法有优势吗?
      • 这是跨模型添加类似功能的标准方法。
      • 由于这个优势,我赞成您的答案,但将另一个标记为已接受,因为它需要更少的代码并将逻辑保持在模型的本地,这似乎更自然。范围有时可能需要跨模型共享,但更常见的情况可能不需要。
      • 是的 - 我想我误读了你的问题。我假设 rel1 和 rel2 是两个不同类的实例。范围是要走的路,evanbikes 的答案是正确的。
      猜你喜欢
      • 2011-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-22
      • 1970-01-01
      • 1970-01-01
      • 2016-08-24
      相关资源
      最近更新 更多