无法链接ActiveRecord :: Associations记录

时间:2014-03-24 01:05:27

标签: ruby-on-rails activerecord associations

我正在尝试为每个用户检索名为“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>`

1 个答案:

答案 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

以这种方式构建代码的优点是:

  1. 您的范围不会再被锁定在控制器方法中,因此您可以轻松地在其他地方重复使用它们。

  2. 您的控制器方法可以变得更简单,更具声明性。也就是说,它可以表达它想要的信息,而不是如何获取该信息。

  3. 将范围缩小为较小的部分意味着我们的代码被更好地分解,并且已经分解的代码可以重新组合。

  4. 通过模型单元测试然后通过控制器测试更容易测试范围。