我正在尝试为每个用户检索名为“contribution_amount”的关联列,但我收到了未定义的方法错误,我无法弄清楚原因。
控制器有:
@payments = Payment.where(:contribution_date => Date.today).pluck(:user_id)
@users = User.where(:id => @payments).find_each do |user|
user.payments.contribution_amount
end
模型有:
class User < ActiveRecord::Base
has_many :payments
end
class Payment < ActiveRecord::Base
belongs_to :user
end
控制台中的确切错误是
`undefined method `contribution_amount' for #<ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_Payment:0x007fb89b6b2c08>`
答案 0 :(得分:2)
user.payments
是一个范围;也就是说,它代表Payment
条记录的集合。 contribution_amount
方法仅适用于单个Payment
条记录。你可以说user.payments.first.contribution_amount
,但我不确定这是你的目标。
您是否想要累计捐款金额?在这种情况下,您需要使用聚合记录集合的方法:user.payments.sum(:contribution_amount)
。
暂时偏离主题,将范围方法推入模型通常会更好。例如:
class User < ActiveRecord::Base
def self.with_payment_contribution_after(date)
joins(:payments).merge(Payment.with_contribution_after(date))
end
def self.with_contribution_amount
joins(:payments).group("users.id")
.select("users.*, sum(payments.contribution_amount) as contribution_amount")
end
end
class Payment < ActiveRecord::Base
def self.with_contribution_after(date)
where(:contribution_date => date)
end
end
# In your controller
@users = User.with_payment_contribution_after(Date.today)
.with_contribution_amount
# In a view somewhere
@users.first.contribution_amount
以这种方式构建代码的优点是:
您的范围不会再被锁定在控制器方法中,因此您可以轻松地在其他地方重复使用它们。
您的控制器方法可以变得更简单,更具声明性。也就是说,它可以表达它想要的信息,而不是如何获取该信息。
将范围缩小为较小的部分意味着我们的代码被更好地分解,并且已经分解的代码可以重新组合。
通过模型单元测试然后通过控制器测试更容易测试范围。