如何基于JSON结构初始化带jsonb属性的ActiveRecord对象?
解决方案
要实现初始化User对象时,address自动生成包含city和postcode且值为nil的结构,可以通过模型初始化回调结合现有JSON Schema来实现,无需硬编码默认结构,确保和校验规则同步。
实现代码
修改User模型,添加after_initialize回调:
class User < ApplicationRecord # name :string, age :integer, address :jsonb include SchemaStructures validates :address, allow_blank: true, json: { message: lambda { |errors| errors }, schema: JSON_SCHEMA_ADDRESS } after_initialize do # 仅当address为nil时生成默认结构 next unless address.nil? # 从JSON_SCHEMA_ADDRESS的properties中提取字段,生成默认nil结构 default_address = JSON_SCHEMA_ADDRESS['properties'].each_with_object({}) do |(key, _), hash| hash[key.to_sym] = nil end self.address = default_address end end
说明
- 回调时机:
after_initialize会在User.new执行后触发,仅在address初始为nil时生成默认结构,不影响显式设置address的场景。 - 依赖Schema:直接从
JSON_SCHEMA_ADDRESS的properties字段提取字段名,确保默认结构和校验规则完全同步——如果后续Schema新增/修改字段,默认结构会自动更新。 - 类型兼容:生成的哈希使用符号键(
city:),和示例需求一致,同时兼容ActiveRecord对jsonb字段的处理。
前提条件
确保你的JSON_SCHEMA_ADDRESS定义包含properties字段,结构类似:
JSON_SCHEMA_ADDRESS = { 'type' => 'object', 'properties' => { 'city' => { 'type' => ['string', 'null'] }, 'postcode' => { 'type' => ['string', 'null'] } }, 'additionalProperties' => false }
内容的提问来源于stack exchange,提问作者Abhilash
相关产品推荐
相关产品推荐

