Rails model elements stored as YAML via :serialize

120 views
Skip to first unread message

dhawt

unread,
Apr 25, 2011, 8:26:30 AM4/25/11
to restfulx-...@googlegroups.com
Hi everyone.  I am a relative newbie to Rails (and Ruby) so I may be missing something ... but, is it possible to overload to_fxml in a model object to handle custom serialization (like to_xml)?

I ask because I have the following model:

class DayEventSet < ActiveRecord::Base

  serialize :day_events, Array


  def to_xml(*args)

    super(:except => [:day_events]) do |xml| 

      day_events.to_xml(:builder => xml, :skip_instruct => true, :root => 'day_events')

    end

  end

end


Standard to_xml (and to_fxml) don't work correctly because the :day_events attribute does not get converted from the YAML representation stored in the database.


Here's my controller.  Pretty standard:


  # GET /day_event_sets

  # GET /day_event_sets.xml

  # GET /day_event_sets.fxml

  def index

    if params[:subscription_id]

      @day_event_sets = DayEventSet.find(:all, :conditions => { :subscription_id => params[:subscription_id] })

    else

      @day_event_sets = DayEventSet.find(:all)

    end


    # this doesn't work....

    respond_to do |format|

      format.xml  { render :xml => @day_event_sets }

      format.fxml { render :fxml => @day_event_sets }

    end

  end


Here's the problem:


>> day_event_sets[8].to_fxml

=> "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<day_event_set>\n  <bell_schedule_id type=\"integer\">1044869952</bell_schedule_id>\n  <date type=\"datetime\">2011-04-04T04:00:00Z</date>\n  <day_events type=\"yaml\">--- \n- !ruby/object:DayEvent \n  attributes: \n    bell_id: \n    created_at: \n    scheduled_item_meeting_id: 719968942\n    updated_at: \n    timetable_cell_id: 545822324\n    end: 2011-04-04 05:55:00 -04:00\n    

.......

hanged_attributes: \n    id: \n    note: \n    event_type: \n  new_record: true\n</day_events>\n  <events_text></events_text>\n  <id type=\"integer\">1021006109</id>\n  <position type=\"integer\">8</position>\n  <subscription_id type=\"integer\">1023269258</subscription_id>\n  <timetable_column_id type=\"integer\">1056228806</timetable_column_id>\n  <week_even_odd_hint type=\"boolean\">false</week_even_odd_hint>\n</day_event_set>\n"


>> day_event_sets[8].to_xml

=> "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<day-event-set>\n  <bell-schedule-id type=\"integer\">1044869952</bell-schedule-id>\n  <created-at type=\"datetime\">2011-04-22T20:45:31Z</created-at>\n  <date type=\"datetime\">2011-04-04T04:00:00Z</date>\n  <events-text></events-text>\n  <id type=\"integer\">1021006109</id>\n  <position type=\"integer\">8</position>\n  <subscription-id type=\"integer\">1023269258</subscription-id>\n  <timetable-column-id type=\"integer\">1056228806</timetable-column-id>\n  <updated-at type=\"datetime\">2011-04-22T20:45:34Z</updated-at>\n  <week-even-odd-hint type=\"boolean\">false</week-even-odd-hint>\n  <day-events type=\"array\">\n    <day-event>\n      <bell-id type=\"integer\" nil=\"true\"></bell-id>\n      <created-at type=\"datetime\" nil=\"true\"></created-at>\n      <end type=\"datetime\">2011-04-04T09:55:00Z</end>\n      <event-type type=\"integer\">0</event-type>\n      <id type=\"integer\">20110404040000</id>\n      <layout-height type=\"integer\" nil=\"true\"></layout-height>\n      <layout-y 

.....

<start type=\"datetime\" nil=\"true\"></start>\n      <timetable-cell-id type=\"integer\" nil=\"true\"></timetable-cell-id>\n      <updated-at type=\"datetime\" nil=\"true\"></updated-at>\n    </day-event>\n  </day-events>\n</day-event-set>\n"


As you can see, to_xml gives me good output, while to_fxml gives me the YAML still.

All well and good, I would just use to_xml instead of to_fxml in my model controller, except:

>> day_event_sets.to_xml
=> "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<day-event-sets type=\"array\">\n</day-event-sets>\n"

.... Uh oh, an empty output.  Not helpful.  to_fxml gives me the included objects, but, again, they have YAML still inside:

>>day_event_sets.to_fxml
=> "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<day_event_sets type=\"array\">\n  <day_event_set>\n    <bell_schedule_id type=\"integer\" nil=\"true\"></bell_schedule_id>\n    <date type=\"datetime\">2011-03-27T04:00:00Z</date>\n    <day_events type=\"yaml\">---  
....

Here's the deal:

to_xml correctly converts the YAML in the database
to_fxml correctly gives me the nested objects, but does not convert the YAML correctly.

This doesn't work:

def to_fxml(*args)

    super(:except => [:day_events]) do |fxml| 

      day_events.to_fxml(:builder => fxml, :skip_instruct => true, :root => 'day_events')

    end

end



I give up... how do I get this to work correctly?

Dima Berastau

unread,
Apr 26, 2011, 4:35:32 PM4/26/11
to restfulx-...@googlegroups.com
Hi,

It should be possible to customize to_fxml on a per model basis. FXMLSerializer invokes to_fxml on each model it's serializing. You can have a look here for reference:


In the worst case you can simply add dasherize => false option and a to_fxml method that invokes to_xml on the model, e.g.

def to_fxml(*args)
  to_xml(:dasherize => false)
end

def to_xml(*args)
  super(:except => [:day_events], , etc)
end
  
FXML is XML but with a few tweaks to make Flash XML parser happy with end result.

Hope this helps,
Dima

This *doesn't* work:


def to_fxml(*args)

   super(:except => [:day_events]) do |fxml|

     day_events.to_fxml(:builder => fxml, :skip_instruct => true, :root =>
'day_events')

   end

end



I give up... how do I get this to work correctly?

--
You received this message because you are subscribed to the Google Groups "restfulx-framework" group.
To post to this group, send email to restfulx-...@googlegroups.com.
To unsubscribe from this group, send email to restfulx-framew...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/restfulx-framework?hl=en.


Daniel Hawthorn

unread,
Apr 26, 2011, 8:25:20 PM4/26/11
to restfulx-...@googlegroups.com
Thanks Dima, this did end up working ok:

class DayEventSet < ActiveRecord::Base
serialize :day_events, Array


def to_fxml(*args)
to_xml(:dasherize => false, :except => [:day_events]) do |xml| 
if day_events != nil
day_events.to_xml(:builder => xml, :dasherize => false, :skip_instruct => true, :root => 'day_events')
end
end
end
end

So with this, I can do dayEventSet.to_fxml and have my nested DayEvent objects serialize properly.

The problem comes here:

sets = DayEventSet.find(:all)
sets.to_fxml()
=> "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<day_event_sets type=\"array\">\n</day_event_sets>\n"

...and none of the DayEventSet objects in the array serialize.  If I don't overload DayEventSet::to_fxml, the array serializes properly but the DayEvents at the lowest level are not properly converted from YAML.

I've implemented a workaround by serializing via JSON in my index method... turns out it converts everything properly all the way down to the serialized DayEvent objects in the DayEventSet table.  Not without it's own issues but at least I have something working.

I would like to get to_fxml working eventually, since my workaround is far from pretty... perhaps I'll have to live with it for now.  Thanks for your help!

dhawt
Reply all
Reply to author
Forward
0 new messages