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>`

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. 通过模型单元测试比通过控制器测试更容易测试作用域。

最新更新