I am using DataMapper for Database access. My goal is to send the models to an webservice as read-only object. This is my current try:
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
Any ideas how to make this work and get rid of the exception?
Thanks,
krissi
Using
to_yamlis deprecated in Psych, and from my testing it seems to be actually broken in cases like this.When you call
to_yamldirectly on your object, your method gets called and you get the result you expect. When you call it on the array containing your object, Psych serializes it but doesn’t correctly handle yourto_yamlmethod, and ends up falling back onto the default serialization. In your case this results in an attempt to serialize an anonymous Class which causes the error.To fix this, you should use the
encode_withmethod instead. If it’s important that the serialized form is tagged as an OpenStruct object in the generated yaml you can use therepresent_object(that firstnilparameter doesn’t seem to be used):If you were just using OpenStruct for convenience, an alternative could be something like:
Note that Datamapper has its own serializer plugin that provides yaml serialization for models, it might be worth looking into.