【问题标题】:Most efficient way to calculate payments by group of users按用户组计算付款的最有效方法
【发布时间】:2019-03-24 18:06:48
【问题描述】:

在我的模型中

class Group < ApplicationRecord      
    has_many :payments, as: :paymentable   
    has_many :users
end

class User < ApplicationRecord  
  has_many   :payments, as: :paymentable   
  belongs_to :group    
end

class Payment < ApplicationRecord  
  belongs_to :paymentable, polymorphic: true
end

我想计算每组用户支付的总和,所以在控制器中我有这个:

Group.includes(users: :payments).each do |group|  
  group.users.each do |user|
    user.payments.each do |payment|
         ............
         ...............
    end
  end
end

最初,我认为Group.includes(users: :payments) 是消除那些 n+1 查询的好主意。但是,这会导致内存膨胀,因为所有用户和付款都加载到内存中。

然后我想尝试使用这样的付款范围来获取单个组的付款

scope :for_paymentable_type,  -> (class_name) { where("for_paymentable_type= ?", class_name) }

scope :belongs_to_group, -> (group) { for_paymentable_type("User").includes(:paymentable).where("paymentable.group_id = ? ", group.id) }

但我无法让它工作。 for_paymentable_type("User").includes(:paymentable) 部分工作正常,但 where("paymentable.group_id = ? ", group.id) 生成以下错误:

ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: paymentable.tgroup_id: SELECT  "payments".* FROM "payments" WHERE (paymentable_type = 'User') AND (paymentable.group_id = 1 ) LIMIT ?

有什么想法吗?

【问题讨论】:

    标签: ruby-on-rails memory activerecord eager-loading


    【解决方案1】:

    通过反转联接表的方向,您只能加载与Payment 关联的用户和组:

    class Payment < ApplicationRecord  
      belongs_to :paymentable, polymorphic: true
      belongs_to :user, -> { where(payments: { paymentable_type: 'User' }) }, foreign_key: 'paymentable_id'
    end
    
    Payment.includes(user: :group).each do |payment|
      ...
    end
    

    【讨论】:

    • 这会在尝试编辑付款时产生此错误 - SQLite3::SQLException: no such column: payment.paymentable_type: SELECT "users".* FROM "users" WHERE "users"."id" = ?和“付款”。“付款类型”=?限制 ?。 - 似乎belongs_to :paymentable 和belongs_to :user 不太兼容...
    • 您的payments 表中有paymentable_type 列吗?
    • 是的。 paymentable_type 和 paymentable_id。
    • 编辑是什么意思?你的意思是payment.update()?你能告诉我给你这个错误的命令吗?
    • 在支付控制器的更新操作中是这一行:if @payment.update(payment_params)。当我注释掉 belongs_to :user 行时,它工作正常:)
    猜你喜欢
    • 1970-01-01
    • 2021-05-23
    • 1970-01-01
    • 1970-01-01
    • 2010-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    相关资源
    最近更新 更多