如何将参数传递给 Rails 4 中的 has_many 关联范围?
Posted
技术标签:
【中文标题】如何将参数传递给 Rails 4 中的 has_many 关联范围?【英文标题】:How do I pass an argument to a has_many association scope in Rails 4? 【发布时间】:2014-06-01 02:16:40 【问题描述】: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 的帐户的所有订单,这似乎是任意的。
【问题讨论】:
这样的?scope:account lambda |account| :conditions => :account_id => account
并查看此 SO ***.com/questions/16203576/…
@Pavan 在我的案例中,关键区别在于需要传递的值不是来自另一个模型的值,而是只有控制器知道的(即当前帐户)。
【参考方案1】:
方法是定义额外的扩展选择器到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)
Rails Association
页面中的 Association Extension
head 中描述了该方法。
要在嵌套方法中访问Customer
记录,您只需访问self
对象,它应该具有当前Customer
记录的值。
Sinse of rails(大约 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)
【讨论】:
如果您希望它成为您的条件的一部分,是否可以在by_account
方法中访问客户记录?【参考方案2】:
你传入你定义的类的一个实例。在您的情况下,您将传递一个客户,然后获取该帐户。
来自 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
【讨论】:
这个答案预设了客户和客户之间的 1:1 关系。然而,该问题指定了一个相反的场景,即一个多租户系统,一个给定的客户可以代表多个账户下订单。【参考方案3】:我知道这是旧的,但由于尚未接受任何答案,我认为添加我的观点不会伤害任何人。
问题在于,每当您将作用域传递给has_many
关系时,将所有者类的实例作为参数传递不仅是一种可能性,而且是唯一可能传递一个争论。我的意思是,您不能传递更多参数,而这个参数将始终是所有者类的实例。
所以@RobSobers,当你
“获取id为1的账户的所有订单,看似随意。”
这不是任意的,你得到所有带有id
的customer
的订单,你调用了关系。我猜你的代码是这样的
Customer.first.orders(@some_account_which_is_ignored_anyway)
似乎has_many
关系并不意味着接受参数。
我个人更喜欢@МалъСкрылевъ的解决方案。
【讨论】:
以上是关于如何将参数传递给 Rails 4 中的 has_many 关联范围?的主要内容,如果未能解决你的问题,请参考以下文章