views:

151

answers:

1

I have a serialized field called options(of type Hash) in my User model. The options field behaves like a Hash most of the time. When I convert the user object to XML, the 'options' field is serialized as a YAML type instead of Hash.

I am sending the result to a Flash client via REST. This behaviour is causing problems at the client side. Is there a way to address this?

class User < ActiveRecord::Base
  serialize :options, Hash
end

u = User.first
u.options[:theme] =  "Foo"
u.save

p u.options # prints the Hash

u.to_xml    # options is serialized as a yaml type: 
            # <options type=\"yaml\">--- \n:theme: Foo\n</options>

EDIT:

I am working around this issue by passing a block to to_xml.(similar to the solution suggested by molf)

u.to_xml(:except => [:options])  do |xml|
  u.options.to_xml(:builder => xml, :skip_instruct => true, :root => 'options')
end

I wondering if there is a better way.

+1  A: 

Serialisation is done with YAML in the database. What they don't tell you is that it is also passed as YAML to the XML serializer. The last argument to serialize indicates that the objects you assign to options should be of type Hash.

One solution to your problem is to override to_xml with your own implementation. It's relatively easy to borrow the original xml builder object and pass it to to_xml of your options hash. Something like this should work:

class User < ActiveRecord::Base
  serialize :options, Hash

  def to_xml(*args)
    super do |xml|
      # Hash#to_xml is unaware that the builder is in the middle of building
      # XML output, so we tell it to skip the <?xml...?> instruction. We also
      # tell it to use <options> as its root element name rather than <hash>.
      options.to_xml(:builder => xml, :skip_instruct => true, :root => "options")
    end
  end

  # ...
end
molf
I am using a similar approach now. Refer to my EDIT to the original question. Since I wasn't clear about that I will vote +1 for your answer. In your solution you do need to add :except to the args to ignore 'options'. Otherwise you end up with two 'options' field in the serialized XML string.
KandadaBoggu