我想在JSONB列中存储对象数组。我正在使用Rails 5.2。我正在使用一个自定义序列化程序,以确保分配给JSONB字段的值是一个数组而不是哈希。并且在向字段分配类似[{a: 1}]
之类的消息时出现错误。这是代码:
型号:
class Printing
serialize :card_faces, CardFacesSerializer
end
序列化器:
class CardFacesSerializer
include JSONBArraySerializer
def allowed_attributes
%i[name image]
end
end
序列化程序问题:
module JSONBArraySerializer
extend ActiveSupport::Concern
def initialize(data)
return [] if data.blank?
if data.is_a?(String)
json = Oj.load(data, symbol_keys: true)
end
raise ArgumentError, "#{json} must be [{},{}], not {}" if json.is_a?(Hash)
# Will only set the properties that are allowed
json.map do |hash|
hash.slice(self.allowed_attributes)
end
end
class_methods do
def load(json)
return [] if json.blank?
self.new(json)
end
def dump(obj)
# Make sure the type is right.
if obj.is_a?(self)
obj.to_json
else
raise StandardError, "Expected #{self}, got #{obj.class}"
end
end
end
end
评估时:
pr = Printing.first
pr.card_faces = [{hay: 12}]
pr.save!
我得到一个错误:
StandardError:预期的CardFacesSerializer,具有数组
我认为转储/加载的工作方式不清楚。为什么在保存过程中调用dump
?如何修复我的代码以使其正常工作?
更新
我设法使其与以下序列化程序代码有关:
module JSONBArraySerializer
extend ActiveSupport::Concern
class_methods do
def load(data)
return [] if data.blank?
if data.is_a?(String)
json = Oj.load(data, symbol_keys: true)
end
raise ArgumentError, "#{json} must be [{},{}], not {}" if json.is_a?(Hash)
# Will only set the properties that are allowed
json.map do |hash|
hash.slice(*allowed_attributes)
end
end
def dump(obj)
# Make sure the type is right.
if obj.is_a?(Array)
obj.to_json
else
raise ArgumentError, "Expected Array, got #{obj.class}"
end
end
end
end
答案 0 :(得分:2)
不要将序列化与JSON / JSONB列一起使用。
请记住,数据库适配器会处理某些序列化任务 为了你。例如:PostgreSQL中的json和jsonb类型将是 在JSON对象/数组语法和Ruby Hash或Array之间转换 透明对象。在这种情况下,无需使用序列化。 https://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/Serialization/ClassMethods.html
serialize
是一种古老的黑客工具,用于在字符串列中存储JSON / YAML /任何内容。认真-请勿使用。只会导致双重转换的问题。
您应该通过常规的模型验证和/或自定义设置器来处理您的工作。