加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby-on-rails – 在一个对象数组上使用ActiveRecord getter

发布时间:2020-12-17 02:19:28 所属栏目:百科 来源:网络整理
导读:如何为 Ruby中的ActiveRecord对象定义自定义getter函数,这些函数将对ActiveRecord对象的数组执行操作? 例如,我想返回一个对象数组的加权平均值.因此,如果我有贷款对象(1,2,3)的字段数量(100,200,300)和default_rate(.1,.2,.3),那么使用正常的ActiveRecord函
如何为 Ruby中的ActiveRecord对象定义自定义getter函数,这些函数将对ActiveRecord对象的数组执行操作?

例如,我想返回一个对象数组的加权平均值.因此,如果我有贷款对象(1,2,3)的字段数量(100,200,300)和default_rate(.1,.2,.3),那么使用正常的ActiveRecord函数Loan.find(1).amount应该返回100,Loan.find(2).default_rate应该返回.2.

但如果我有Loan.find(2,3).default_rate,我希望它返回默认费率的加权平均值,即.26.我知道我可以使用SQL select语句执行此操作但是如何“重载”ActiveRecord getter以允许在我在Loan对象数组而不是单个Loan对象上调用getter时定义函数?

贷款表具有字段金额id,金额和default_rate

class Loan < ActiveRecord::Base
  module Collection
    def default_rate
      sum(:default_rate * :amount) / sum(:amount)
    end
  end
end

class LoanGroup
  has_many :loans,:extend => Loan::Collection
end

#Then I try
obj = LoanGroup.where('id < 10')

这给了我在LoanGroup中未定义has_many的错误

解决方法

为了避免使用特定于Loan记录集合的方法来污染Array的命名空间,您可以为这样的集合创建一个包装器并在其上调用您的方法.

就像是:

class LoanArray < Array
  def initialize(*args)
    find(*args)
  end

  def find(*args)
    replace Array.wrap(Loan.find(*args))
    self
  end

  def default_rate
    if length == 1
      self[0].default_rate 
    else
      inject(0) {|mem,loan| mem + loan.defualt_rate } / count
    end
  end
end

# then
arr = LoanArray.new(2,3).default_rate #=> 0.26
arr.find(1,3).default_rate          #=> 0.2
arr.length                            #=> 3
arr.find(1)                           #=> [<Loan id=1>]
arr.default_rate                      #=> 0.1
arr.length                            #=> 1

原始答案如下:使用关联扩展名

使用关联扩展.这样,无论是贷款还是贷款集合,该方法都是相同的.

class MyClass
  has_many :loans do
    def default_rate
      sum(:default_rate) / count
    end
  end
end

obj = MyClass.find(1)
obj.loans.first.default_rate               #=> 0.1
obj.loans.default_rate                     #=> 0.2
obj.loans.where(:id => [2,3]).default_rate #=> 0.26

如果你想保留贷款类贷款的逻辑,你也可以在那里写下延期,例如:

class Loan
  module Collection
    def default_rate
      sum(:default_rate) / count
    end

    # plus other methods,as needed,e.g.
    def average_amount
      sum(:amount) / count
    end
  end
end

class MyClass
  has_many :loans,:extend => Loan::Collection
end

编辑:因为@Santosh指出association.find不返回关系,所以它在这里不起作用.您必须使用返回关系的where或其他方法.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读