You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rails Engine中实现自定义ActiveRecord类型的注册

Rails Engine 中注册自定义ActiveRecord类型的实现方法

核心注意点:要确保注册逻辑在ActiveRecord类型系统加载完成后执行,避免因加载顺序不对抛出未初始化常量的错误,不能直接照搬普通应用把注册代码丢到initializers目录下的写法,需要绑定到Engine的初始化钩子上指定加载顺序。


步骤1:定义自定义类型

推荐把类型文件放在Engine的app/types/你的引擎名称/duration_type.rb路径下,Rails默认会自动加载app目录下的所有子目录,不需要额外配置自动加载规则,代码和普通应用的定义一致:

module 你的引擎名称
  class DurationType < ActiveRecord::Type::String
    def cast(value)
      return value if value.blank? || value.is_a?(ActiveSupport::Duration)

      ActiveSupport::Duration.parse(value)
    end

    def serialize(duration)
      duration ? duration.iso8601 : nil
    end
  end
end

如果你不想把类型放在app目录下,也可以放到lib/你的引擎名称/types/duration_type.rb路径下,只需要在Engine配置里额外加一行自动加载lib目录的配置即可。


步骤2:在Engine主类中注册类型

找到Engine的主类文件,路径一般为lib/你的引擎名称/engine.rb,添加初始化钩子,指定在active_record.load_types之后执行注册逻辑:

module 你的引擎名称
  class Engine < ::Rails::Engine
    # 如果你把类型放在lib目录下,需要打开下面的配置加自动加载路径
    # config.autoload_paths << root.join("lib")

    initializer "你的引擎名称.register_custom_types", after: "active_record.load_types" do
      # 可选兼容逻辑:如果你的引擎可能被用于未启用ActiveRecord的应用,加判断避免报错
      if defined?(ActiveRecord::Type)
        ActiveRecord::Type.register(:duration, 你的引擎名称::DurationType)
      end
    end
  end
end

效果说明

上述配置完成后,该自定义duration类型默认全局生效,不管是Engine内部的模型还是宿主应用的模型,都可以直接通过attribute :字段名, :duration的方式使用。

内容的提问来源于stack exchange,提问作者alexs333

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 08:27:04