Rails 抽象库 class 中的模型验证需要使用 child class 的名称

Rails Model Validation in abstract base class that needs to utilize name of child class

我正在使用单一 Table 继承进行 rails 设置,其中每个 class 的所有属性都存储在 JSON blob 中,结构它在 class 独有的 json 架构文件中定义。

我想 运行 根据其 json 模式对每个 class 进行验证,但每个 class 的逻辑都是相同的减去模式本身的路径取决于 STI class 和子 class.

的名称

此设置依赖于 gem 'activerecord_json_validator' 指定验证模式文件的格式和一些验证助手

所以所需的设置类似于

/app/models/data_generating_module(从未实例化的抽象 STI 基础 class)

class DataGeneratingModule < ActiveRecord::Base
  has_and_belongs_to_many :action_coordinates

  def self.schema_path
    "#{Rails.root}/app/models/json_schemas/#{superclass.to_s.underscore}/#{self.to_s.underscore}.json"
  end

  validates :module_data, presence: true, json:  { message: ->(errors) { errors },  schema: self.schema_path }
end 

app/models/sub_sti(实例化的 class)

class SubSti< DataGeneratingModule
end

schema_path 应评估为 repo/app/models/json_schemas/data_generating_module/sub_sti.json"

如果我将 schema_path 和验证码留在子 class 上,一切正常。

在这样做之后,SubSti 可以被实例化,但是如果我在它上面调用 .valid? 它会抛出一个错误,因为当 schema_path get 被调用时它正在使用 superclass 不是子class.

JSON::Schema::ReadFailed (Read of file at /git/repo/app/models/json_schemas/active_record/base/data_generating_module.json failed)

所以基本上我如何将所有这些数据移动到抽象 STI class 以避免重复它,但它仍然从 child class 插入正确的值?

将其放入继承的钩子中,然后class在子class内部进行评估得到了这个工作:


class DataGeneratingModule < ActiveRecord::Base
    def self.inherited(subclass)
      subclass.class_eval do
        validates :module_data, presence: true, json:  { message: ->(errors) { errors },  schema: "#{Rails.root}/app/models/json_schemas/#{subclass.superclass.to_s.underscore}/#{subclass.to_s.underscore.split("/").last}.json" }
      end

      super
    end
end