ruby-on-rails – 在一个对象数组上使用ActiveRecord getter
如何为
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或其他方法. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |