我正在使用DataMapper进行数据库访问。我的目标是将模型作为只读对象发送到Web服务。这是我目前的尝试:
class User
include DataMapper::Resource
def to_yaml(opts = {})
mini_me = OpenStruct.new
instance_variables.each do |var|
next if /^@_/ =~ var.to_s
mini_me.send("#{var.to_s.gsub(/^@/, '')}=", instance_variable_get(var))
end
mini_me.to_yaml(opts)
end
....
end
YAML::ENGINE.yamler = 'psych'
u = User.get("hulk")
p u.to_yaml
# => "--- !ruby/object:OpenStruct\ntable:\n :uid: hulk\n :uidNumber: 1000\n :gidNumber: 1001\n :email: hulk@example.com\n :dn: uid=hulk,ou=People,o=example\n :name: Hulk\n :displayName: Hulk\n :description: Hulk\n :homeDirectory: /home/hulk\n :accountFlags: ! '[U ]'\n :sambaSID: S-1-5-21-......\nmodifiable: true\n"
p [ u ].to_yaml # TypeError: can't dump anonymous class Class
任何想法如何使这项工作摆脱异常?
谢谢, krissi
答案 0 :(得分:2)
使用to_yaml
is deprecated in Psych,在我的测试中,似乎在这种情况下实际上已经破解了。
当您直接在对象上调用to_yaml
时,您的方法会被调用,并获得您期望的结果。当您在包含对象的数组上调用它时,Psych会将其序列化,但不能正确处理您的to_yaml
方法,最终会回退到默认序列化。在您的情况下,这会导致尝试序列化导致错误的匿名类。
要解决此问题,您应该使用encode_with
方法。如果序列化表单在生成的yaml中标记为OpenStruct对象很重要,则可以使用represent_object
(似乎没有使用第一个nil
参数):
def encode_with(coder)
mini_me = OpenStruct.new
instance_variables.each do |var|
next if /^@_/ =~ var.to_s
mini_me.send("#{var.to_s.gsub(/^@/, '')}=", instance_variable_get(var))
end
coder.represent_object(nil, mini_me)
end
如果您只是为了方便而使用OpenStruct,那么替代方案可能是:
def encode_with(coder)
instance_variables.each do |var|
next if /^@_/ =~ var.to_s
coder[var.to_s.gsub(/^@/, '')]= instance_variable_get(var)
end
end
请注意,为模型提供yaml序列化的Datamapper has its own serializer plugin可能值得研究。