我在具有以下模式的模型上使用jsonb
列:
{
name: 'abc',
points: [{
x: 0,
y: 2,
}, {
x: 2,
y: 3,
}],
}
字符串
我想使用嵌套的ActiveModel::attribute方法来(反)序列化数据,以便能够在json上使用ActiveModel验证。
这就是我所尝试的:
# app/models/parent_model.rb
class ParentModel < ApplicationRecord
attribute :child, ChildModel.new
end
x
# app/models/child_model.rb
class ChildModel < ActiveModel::Type::Value
include ActiveModel::Model
attr_accessor :name
attribute :points, Point.new, array: true
def cast(value)
case value
when String
decoded = ActiveSupport::JSON.decode(value) rescue nil
ChildModel.new(decoded) unless decoded.nil?
when Hash
ChildModel.new(value)
when ChildModel
value
end
end
def serialize(value)
value&.attributes&.to_json
end
def changed_in_place?(raw_old_value, new_value)
deserialize(raw_old_value) != new_value
end
end
# app/models/point.rb
class Point < ActiveModel::Type::Value
include ActiveModel::Model
attr_accessor :x, :y
def cast(value)
case value
when String
decoded = ActiveSupport::JSON.decode(value) rescue nil
Point.new(decoded) unless decoded.nil?
when Hash
Point.new(value)
when Point
value
end
end
def serialize(value)
value&.attributes&.to_json
end
def changed_in_place?(raw_old_value, new_value)
deserialize(raw_old_value) != new_value
end
end
的字符串
这里有一些问题:
Point
和ChildModel
具有属性limit
、precision
和scale
。他们似乎来自ActiveModel::Type::Value
,但我想知道为什么?我应该使用不同的基类吗?child
属性似乎作为nil
保存到数据库中,即使它是在示例化ParentModel
时设置的
在rails中,我想做的事情的正确方法是什么?
3条答案
按热度按时间fhg3lkii1#
我知道这不能回答你的问题...但是我在这里看到了许多与使用jsonb或数组列类型的缺点有关的问题,如果使用了不同的表结构,这些问题是可以避免的。我的建议是:
字符串
你的生活会更轻松!
y53ybaqx2#
我现在使用的是attr_json gem,这正是我所需要的。不过,我认为使用“vanilla rails”是可能的。🤷♂️
bwitn5fc3#
您可能希望使用
serialize
而不是attributes
。例如:
字符串