Posts from September 2009


, , ,

Customizing Rails Serialization

I wanted to customize the ActiveRecord attributes which were being serialized by to_json. This is easy enough if you're serializing one record; add the attribute names as arguments of the to_json method. For demonstration purposes, lets use the following ActiveRecord models:

Survey(id: integer, name: string, created_at: datetime)
	has_many :questions

Question(id: integer, body: string, survey_id: integer, position: string, created_at: datetime)
	belongs_to :survey	

And serialize a survey without the timestamp:

@survey.to_json(:only => [:id, :name])

=> {"survey": {"name": "Favorite Foods", "id": 1}}

But to_json also allows you to serialize associated records with the :include option. So if we want to include the Survey questions, it would look like this:

@survey.to_json(:only => [:id, :name], :include => {:questions => {:except => [:id]}})

=> {"survey": {"name": "Favorite Foods", "id": 1, "questions": [{"id": 1}, {"id":2}]}}

But this isn't the output we wanted. You'll see that the survey's :only option overrode the question's :except option. In other words, the parent's options trickle down unless the association options override them. With to_json, :only overrides :except. So, to have full control over the JSON output, I need to pass in a list of approved attrs and methods for every association, which can be a little verbose.

Since I have a list of attributes and methods that I know I want to expose in my JSON by default, I don't want to pass those into to_json every time. So, I made a plugin that lets you define the attributes and methods that are serialized by to_json and to_xml in the class.

class Question < ActiveRecord::Base

  inheritable_attributes[:public_serialization_attrs] = ['id', 'name']

end

class Question < ActiveRecord::Base

  inheritable_attributes[:public_serialization_attrs] = ['body', 'survey_id']
  inheritable_attributes[:public_serialization_methods] << "thumbnail_path"

end

Furthermore, I don't want the parent's serialization options to trickle down to its associations. This plugin also overrides that behavior so every :include tier has it's own options and doesn't inherit the parents' options.

Sample output using the plugin with the above configurations:

@survey.to_json(:include => :questions)

=> {"survey": {"id": 1, "name": "Favorite Foods", "questions": [{"body": "What's your favorite pizza topping?", "survey_id": 1, "thumbnail_path": "/images/question_1.png"}, {"body": "What's your favorite ice cream flavor?", "survey_id": 1, "thumbnail_path": "/images/question_2.png"}]}}

The plugin is available at GitHub: wdlindmeier/Rails-Custom-Include-Serialization-.
This plugin has been tested on Rails version 2.2.2 and 2.3.4.

Permalink    Show Comments


, ,

Here's to the crazy ones

I was looking for some FPO icons online and I found a nice, large TextEdit icon. Interesting that the sample text written in the icon is from Apple's "Think Different" campaign.

Permalink    Show Comments