ruby-on-rails – 如何向activerecord集合添加方法?
发布时间:2020-12-16 19:38:46 所属栏目:百科 来源:网络整理
导读:我想为特定模型的所有集合添加一个方法.假设我想将方法??my_complicated_averaging_method添加到WeatherData集合中: WeatherData.all.limit(3).my_complicated_averaging_method()Station.first.weatherdata.my_complicated_averaging_method() 这样做最好
我想为特定模型的所有集合添加一个方法.假设我想将方法??my_complicated_averaging_method添加到WeatherData集合中:
WeatherData.all.limit(3).my_complicated_averaging_method() Station.first.weatherdata.my_complicated_averaging_method() 这样做最好的方法是什么?目前我发现的唯一方法是这样的: class WeatherData < ActiveRecord::Base def self.my_complicated_averaging_method weighted_average = 0 @relation.each do |post| # do something complicated # weighted_average = end return weighted_average end end 这是将方法添加到集合中的好方法吗?有没有更好/支持的方式来做到这一点? 解决方法
有很多方法如何做,而且你完全有效(尽管我个人更喜欢将类方法包装到单独的块检查
this中),但是随着人们向他们的模型添加更多的业务逻辑,并盲目追随“瘦的控制器”胖型“概念,型号变成了完整的混乱.
为了避免这种混乱,介绍服务对象是一个好主意,在你的情况下,它将是这样的: class AverageWeatherData class << self def data(collection) new(collection).data end end def initialize(collection) @collection = collection end def data @collection.reduce do |avg,post| # reduce goes through every post,each next iteration receives in avg a value of the last line of iteration # do something with avg and post end # no need for explicit return,every line of Ruby code returns it's value # so this method would return result of the reduce # more on reduce: http://ruby-doc.org/core-2.0.0/Enumerable.html#method-i-reduce end end 现在您可以通过将您的集合传递给它来直接调用此类.但您也可以代理这样的呼叫: def self.my_complicated_averaging_method AverageWeatherData.data(@relation) end 我鼓励你阅读这个博客来更多地了解这种方法: UPD 你是正确的使用实例变量是一个可能的方式来弄乱对象内部(加上它不是一个公共接口,它可能会在将来改变).我的建议是使用方法范围.基本上用范围替换@relation. 检查这个例子.我使用我自己的项目中的一个模型来表明它实际上是有效的 2.0.0p247 :001 > Tracking # just asking console to load this class before modifying it # => Tracking(id: integer,action: string,cookie_id: string,ext_object_id: integer,created_at: datetime,updated_at: datetime) 2.0.0p247 :002 > class Tracking 2.0.0p247 :003?> def self.fetch_ids 2.0.0p247 :004?> scoped.map(&:id) 2.0.0p247 :005?> end 2.0.0p247 :006?> end # => nil 2.0.0p247 :007 > 2.0.0p247 :008 > Tracking.where(id: (1..100)).fetch_ids # Tracking Load (2.0ms) SELECT "trackings".* FROM "trackings" WHERE ("trackings"."id" BETWEEN 1 AND 100) # => [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] UPD 在Rails 4范围内被弃用,所以使用全部是正确的. all.map(&:id) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |