如何向 ActiveRecord 集合添加方法?

2024-06-26

我想为特定模型的所有集合添加一个方法。假设我想添加方法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 https://stackoverflow.com/questions/2505067/class-self-idiom-in-ruby出),但随着人们向模型中添加更多业务逻辑并盲目遵循“瘦控制器,胖模型”的概念,模型变得一团糟。

为了避免这种混乱,最好引入服务对象,在您的情况下,它会是这样的:

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

我鼓励您通过阅读此博客来了解更多有关此方法的信息:http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/ http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/

UPD

您是对的,使用实例变量是搞乱对象内部的一种可能方法(而且它不是公共接口,将来可能会改变)。我的建议是使用方法scoped。基本替换@relation with scoped.

检查这个例子。我使用了我自己项目中的模型来证明它确实有效

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 中scoped已被弃用,因此使用是正确的all.

all.map(&:id)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何向 ActiveRecord 集合添加方法? 的相关文章

随机推荐

  • 我必须实现 Applicative 和 Functor 来实现 Monad

    我正在尝试实现一个 Monad 实例 作为一个更简单的示例 假设如下 data Maybee a Notheeng Juust a instance Monad Maybee where return x Juust x Notheeng
  • 如何在 C 中将 int 和数组保存在共享内存中?

    我正在尝试编写一个程序 让子进程在 Linux 上相互通信 这些进程都是从同一个程序创建的 因此它们共享代码 我需要它们能够访问两个整数变量以及一个整数数组 我不知道共享内存是如何工作的 我搜索过的每一个资源除了让我困惑之外什么也没做 任何
  • Spark中DataFrame、Dataset、RDD的区别

    我只是想知道有什么区别RDD and DataFrame Spark 2 0 0 DataFrame 只是一个类型别名Dataset Row 在阿帕奇火花 你能将其中一种转换为另一种吗 首先是DataFrame是从SchemaRDD 是的
  • java 未知深度的嵌套哈希图

    我有一个要求 我需要有一个嵌套的哈希图 但深度将在运行时决定 例如 如果在运行时 用户说 3 那么我的哈希图应该是这样的 HashMap
  • 在无形状中,有两个列表,其中一个包含另一个的类型类

    在无形中 我正在尝试编写一个需要两个 HList 的函数l1 and l2任意长度 具有以下属性 的长度l1 and l2是相同的 l2包含的确切类型l1 包装在常量外部类型构造函数中 So if l1 was 1 1 2 hello HN
  • 对数据绑定组合框进行排序的最佳方法是什么?

    我对此做了一些研究 似乎对数据绑定组合框进行排序的唯一方法是对数据源本身进行排序 在本例中为数据集中的数据表 如果是这种情况 那么问题就变成对数据表进行排序的最佳方法是什么 组合框绑定在设计器中设置初始化使用 myCombo DataSou
  • Python:如何即时生成代码?

    我遇到了一个问题 我必须动态生成程序然后执行它 我们怎样才能做到这一点 您可以使用 eval 函数从字符串执行代码 一个例子是 import math test r dir math eval test Output doc name pa
  • 如何在 Sublime Text 3 中设置语法的默认文件扩展名?

    我不是在询问将语法与文件扩展名相关联 而是在询问将文件扩展名与语法相关联 也就是说 在创建新文件后设置保存文件对话框中建议的文件扩展名 然后设置语法 然后单击 保存 您可以在保存对话框中更改扩展名 但最好不要每次都这样做 用于保存纯文本文件
  • 如何找到权重为 1、0、-1 且成本精确为 0 的多维路径

    我得到了一个有向图 其中有 n 个节点和边 向量的权重 每个向量的长度为 m 为数字 1 0 1 我想找到从一个节点到另一个节点 我们可以多次访问节点 的任何路径 或者说这样的路径不存在 使其权重之和等于仅由零组成的向量 我正在考虑暴力回溯
  • 关于调试打印样式表的建议?

    我最近一直在为一个网站制作打印样式表 我意识到我不知道如何有效地调整它 在屏幕布局上工作时有一个重新加载周期是一回事 更改代码 命令选项卡 reload 但是当您尝试打印时 整个过程会变得更加困难 更改代码 命令选项卡 reload pri
  • Postgres:跨行连接 JSONB 值?

    我正在掌握 Postgres gt 9 5 中的 JSONB 功能 并且很喜欢它 但遇到了障碍 我读过有关连接 JSON 字段的功能 所以 a 1 b 2 创造 a 1 b 2 但我想在多行的同一字段中执行此操作 例如 select row
  • TPL架构问题

    我目前正在开展一个项目 我们面临并行处理项目的挑战 到目前为止没什么大不了的 现在来说说问题 我们有一个 ID 列表 我们定期 每 2 秒 为每个 ID 调用一个 StoredProcedure 需要单独检查每个项目的 2 秒 因为它们是在
  • symfony2 选择单选框的默认值

    我的项目是使用 Silex 和 Symfony 组件 即表单组件 编写的 我尝试创建一组从类中构建的单选按钮 并且我想预先选择其中一个单选按钮 我创建这样的表格 form app form factory gt createBuilder
  • 选项卡集 $rootScope 范围未更新

    我的屏幕结构如下 UserExperienceScreen
  • ValueError:张量必须与张量来自同一个图

    我正在尝试在张量流中构建图表 但遇到以下错误 ValueError 张量 transformation 0 输出 输出 0 形状 dtype float32 必须来自同一个图表 张量 变量 总输出 0 形状 dtype float32 re
  • 大十进制减法

    我想减去2double值 我尝试了以下代码 double val1 2 0 double val2 1 10 System out println val1 val2 我得到的输出为 0 8999999999999999 为了获得输出0 9
  • 如何防止Rails“复数”列名?

    我正在使用 dwilkie 的外国人 http github com dwilkie foreignerRails 插件 我有一个表创建语句 如下所示 create table agents games force gt true id g
  • 如何在 Tomcat 6 中合理配置安全策略

    我使用的是为 Ubuntu Karmic 打包的 Tomcat 6 0 24 Ubuntu 的 Tomcat 软件包的默认安全策略相当严格 但看起来很简单 在 var lib tomcat6 conf policy d 有多种建立默认策略的
  • 使用 mongodb-reactive 的反应式 Spring boot 应用程序中的多租户

    我们如何使用 Mongodb reactive 存储库在 spring webflux 中创建多租户应用程序 我在网上找不到任何有关反应式应用程序的完整资源 所有可用资源均适用于非反应式应用程序 UPDATE 在非响应式应用程序中 我们过去
  • 如何向 ActiveRecord 集合添加方法?

    我想为特定模型的所有集合添加一个方法 假设我想添加方法my complicated averaging method到 WeatherData 集合 WeatherData all limit 3 my complicated averag