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

时间:2014-04-17 00:17:39

标签: ruby-on-rails associations scopes

Rails 4允许您对has_many关系进行范围调整:

class Customer < ActiveRecord::Base
  has_many :orders, -> { where processed: true }
end

因此,只要您执行customer.orders,您就只能获得已处理的订单。

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

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

以下是我所拥有的:

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

但是,在我的控制器或视图中,我如何通过正确的帐户?在我做的时候使用上面的代码:

customers.orders

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

3 个答案:

答案 0 :(得分:26)

方法是为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)

该方法在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)

答案 1 :(得分:23)

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

来自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

在你的例子中,它将是:

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

答案 2 :(得分:0)

我知道这已经过时了,但由于还没有接受答案,我认为加上我对这一点的看法不会伤害任何人。

问题在于,每当您将范围传递给has_many关系时,将所有者类的实例作为参数传递不仅是可能的,而且是唯一的可能性传递一个论点。我的意思是,你不允许传递更多的参数,而且总是是所有者类的实例。

所以@RobSobers,当你

  

“获取id为1的帐户的所有订单,看似随意。”

这不是任意的,您获得了id customer所谓的关系的所有订单。我想你的代码就像是

Customer.first.orders(@some_account_which_is_ignored_anyway)

似乎has_many关系并不意味着接受参数。

就个人而言,我更喜欢@МалъСкрылевъ的解决方案。