我正在使用rails 4.2.0 - 这是我的模型:
class Customer < ApplicationRecord
has_many :meters, -> { includes :contracts }
end
class Meter < ApplicationRecord
belongs_to :customer
has_many :contracts
end
class Contract < ApplicationRecord
belongs_to :meter
end
现在,我想显示客户的所有合同。根据Rails指南,我应该能够做到这一点:
@customer.meters.contracts
但是,它不起作用。这是错误消息:
undefined method `contracts' for #<Meter::ActiveRecord_Associations_CollectionProxy:0x007fb0385730b0>
在这种情况下,最好的方法是什么? 感谢您的帮助!
每个模型类(如示例中所示)仅表示数据库记录的一个实例,即Meter
类仅表示meters
表中的一行meter
。因此,考虑到这一点,您可以看到声明meter
has_many
contracts
意味着这些meter
实例中的每一个都有许多contracts
。
让我们分解一下这条线:@customer.meters.contracts
您有您的@customer
实例,并且您要求它提供所有仪表:@customer.meters
.该meters
方法的返回是属于该@customer
的meters
的集合。由于它是具有许多合同的meter
的实例,因此您不能以这种方式要求收集其合同的仪表。
不过,您可以询问单个仪表:@customer.meters.first.contracts
或者您可以遍历所有仪表并获取所有合约:
@customer.meters.flat_map(&:contracts) # => an array of all the contracts
或者,更一般地说,您可能希望在视图中显示客户的合同列表:
<% @customer.meters.each do |meter| %>
<% meter.contracts.each do |contract|
// display the contract
<% end %>
<% end %>
但是,您可以通过meters
关联将所有contracts
关联到customer
:
class Customer < ApplicationRecord
has_many :meters, -> { includes :contracts }
# ActiveRecord's shorthand declaration for associating
# records through a join table, in this case 'meters'
has_many :contracts, through: :meters
end
通过添加该has_many X, through: Y
,您是在说客户记录与另一个表中的记录相关联,X
通过联接表Y
。有了这个,给定具有现有meters
的customer
,并且这些仪表具有现有contracts
,您将能够调用@customer.contracts
,ActiveRecord 将通过将客户的meters
与其contracts
加入来获取contracts
并返回contracts
集合。
更多关于 Rails 有很多通过关联: http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association