如何将参数传递给Rails 4中的has_many关联作用域?

Rob*_*ers 31 ruby-on-rails associations scopes

Rails 4允许您has_many像这样关系范围:

class Customer < ActiveRecord::Base
  has_many :orders, -> { where processed: true }
end
Run Code Online (Sandbox Code Playgroud)

因此,只要您这样做,customer.orders您只能获得已处理的订单.

但是如果我需要使where条件动态呢?如何将参数传递给范围lambda?

例如,我只希望显示客户当前在多租户环境中登录的帐户的订单.

这是我得到的:

class Customer < ActiveRecord::Base
  has_many :orders, (account) { where(:account_id => account.id) }
end
Run Code Online (Sandbox Code Playgroud)

但是,在我的控制器或视图中,我如何通过正确的帐户?在我执行以下代码时,请执行以下操作:

customers.orders
Run Code Online (Sandbox Code Playgroud)

我得到账户ID为1的所有订单,看似随意.

Мал*_*евъ 27

方法是为has_many范围定义其他扩展选择器:

class Customer < ActiveRecord::Base
   has_many :orders do
      def by_account(account)
         # use `self` here to access to current `Customer` record
         where(:account_id => account.id)
      end
   end
end

customers.orders.by_account(account)
Run Code Online (Sandbox Code Playgroud)

该方法Association Extension在Rails Association页面的头部描述.

Customer在嵌套方法中访问记录,您只能访问self对象,它应该具有当前Customer记录的值.

rails的Sinse(大约5.1)你可以将模型范围与其他类型相同类型的has_many范围合并,例如,你可以在两个模型中编写如下相同的代码:

class Customer < ApplicationRecord
   has_many :orders
end

class Order < ApplicationRecord
   scope :by_account, ->(account) { where(account_id: account.id) }
end

customers.orders.by_account(account)
Run Code Online (Sandbox Code Playgroud)


小智 24

您传入已定义的类的实例.在您的情况下,您将传递客户,然后获得该帐户.

来自API http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

访问所有者对象

有时,在构建查询时访问所有者对象很有用.所有者作为参数传递给块.例如,以下关联将查找用户生日时发生的所有事件:

class User < ActiveRecord::Base
  has_many :birthday_events, ->(user) { where starts_on: user.birthday }, 
    class_name: 'Event'
end
Run Code Online (Sandbox Code Playgroud)

在您的示例中,它将是:

class Customer < ActiveRecord::Base
  has_many :orders, ->(customer) { where(account_id: customer.account.id) }
end
Run Code Online (Sandbox Code Playgroud)

  • 此答案的前提是客户与帐户之间的1:1关系。但是,该问题指定了一种情况相反的情况,即多租户系统,给定客户可以代表多个帐户下订单。 (2认同)