A Fresh Cup is Mike Gunderloy's software development weblog, covering Ruby on Rails and whatever else I find interesting in the universe of software. I'm a full-time software developer: most of my time in recent years has been spent writing Rails, though I've dabbled in many other things and like most people who have been writing code for decades I can learn new stuff as needed.

Currently I'm employed as the Vice President of Engineering at Faria Education Group. If you're interested in working with me, we're often hiring smart developers. Drop me a comment if you're interested or email MikeG1 [at] larkfarm.com.

Navigation
« Double Shot #328 | Main | Double Shot #327 »
Wednesday
Nov052008

Customizing to_xml and to_json in Rails

You probably already know (well, if you're a Rails developer) that you can use to_xml or to_json to quickly get XML or JSON representations of Active Record model instances. But did you know that these methods are configurable? By default they simply dump all of the attributes of the model along with their values, but if you want to do something different, you can - and usually without overriding the base methods.

To start, you can specify exactly which attributes to export with the :only or :except options:

[sourcecode language='ruby']
@user.to_xml :only => [ :name, :phone ]
@user.to_xml :except => :password
@user.to_json :only => [ :name, :phone ]
@user.to_json :except => :password
[/sourcecode]

You can include associated records, nesting as needed, with the :include option:

[sourcecode language='ruby']
@user.to_xml :include => {:orders =>
{ :include => [:shipments, :backorders] }}
@user.to_json {:orders =>
{ :include => [:shipments, :backorders] }}
[/sourcecode]

:only and :except also work on includes:

[sourcecode language='ruby']
@user.to_xml :include => {:orders =>
{ :include => [:shipments, :backorders] },
:only => :order_date }
@user.to_json {:orders =>
{ :include => [:shipments, :backorders] },
:only => :order_date }
[/sourcecode]

You can create XML or JSON attributes from model methods by using the :methods option:

[sourcecode language='ruby']
@user.to_xml :methods => :permalink
@user.to_json :methods => :permalink
[/sourcecode]

Additionally, there are some options that apply only to to_xml. :skip_instruct suppresses the XML processing instruction. :skip_types suppresses the output of types to the XML. :dasherize => false turns off dasherization of column names.

Reader Comments (5)

This is a great tip!

I've been using this a lot to send data into adobe flex as the frontend and works beautifully. Instead of worrying about nesting, you can simply include which data you want, when you want it, and then use that data accordingly.

Smart and elegant.

November 7, 2008 | Unregistered Commentermalkomalko

Thanks for the information. I'm wondering if you know the syntax for including 2 different associated records, requiring nesting, and one not. I've tried a few combinations, but can't seem to get any working :(

November 20, 2008 | Unregistered CommenterMattFS218

Never mind, stupid me figured it out :)

November 20, 2008 | Unregistered CommenterMattFS218

(:include=>{:user_group =>{ :include => [:keys] }, :user_datagrid_prefs => {}})

Works.

November 20, 2008 | Unregistered CommenterMattFS218

Thanks, this was great. It turned out I also needed CamelCased names in my XML - I just submitted a patch (http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/1534) to give a :camelize option - please review & approve/comment if you'd like to see it make it in the core...

December 8, 2008 | Unregistered CommenterBruce Krysiak

PostPost a New Comment

Enter your information below to add a new comment.
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>