Mongoid嵌入模型能否设置虚拟属性?嵌入类虚拟属性未返回问题咨询
解决Mongoid嵌入模型虚拟属性在父模型as_json中不显示的问题
这个问题很常见——Mongoid默认序列化父文档时,只会处理嵌入文档的持久化字段,不会自动应用子文档自定义的as_json逻辑,也不会主动包含虚拟属性。下面给你几个可行的解决办法:
方法一:重写父模型B的as_json方法,手动处理嵌入文档
在B类里自定义序列化逻辑,主动调用嵌入模型A的as_json方法,这样就能带上A的虚拟属性了:
class B include Mongoid::Document field :name, type: String embeds_one :a # 这里注意:Mongoid中单个嵌入用embeds_one,多个用embeds_many,你原来的embeds :a可能是笔误 def as_json(options = {}) # 先调用父类的as_json获取基础字段 super.tap do |json| # 如果存在嵌入的A实例,就用A自己的as_json序列化它 json['a'] = a.as_json(options) if a.present? end end end
这样当你调用b.as_json时,嵌入的A文档会使用你自定义的逻辑,自然就包含pnl属性了。
方法二:调用as_json时传入指定选项,按需包含虚拟属性
如果不想修改模型代码,可以在调用序列化的时候,通过include选项明确指定要包含嵌入文档的虚拟方法:
b = B.first b.as_json(include: { a: { methods: [:pnl] } })
这个方式更灵活,适合只在特定场景需要虚拟属性的情况。
方法三:修改A的serializable_hash方法,默认包含虚拟属性
因为as_json底层依赖serializable_hash方法,你可以在A类里重写这个方法,让它默认带上pnl:
class A include Mongoid::Document field :name, type: String embedded_in :b def pnl=(p) end def pnl "p" end def serializable_hash(options = nil) # 合并传入的选项,确保默认包含pnl方法 super((options || {}).merge(methods: [:pnl])) end end
这样不管是单独序列化A,还是通过B序列化,都会自动包含pnl属性,不需要额外传参。
另外提醒一下:你原来的B类里写的embeds :a是不正确的Mongoid语法,单个嵌入关系应该用embeds_one :a,多个才用embeds_many :a,这个小细节可能会导致其他潜在问题,记得修正哦。
内容的提问来源于stack exchange,提问作者Michael H.
相关产品推荐
相关产品推荐

