Baking ActiveRecord Cookies With JSON


Our upcoming Mightyvites site has a nifty form where users can calculate the cost of their invitations. There are a number of options to choose from, and once a user makes the effort to price a package they shouldn’t lose their settings if they leave the page. It’s imperative that the form pick up where the user left off so that it is easy for them to continue with their purchase. That said I needed a way to persist their configuration, but I couldn’t rely on the database because the user very well may be anonymous. I also didn’t want to use the session because it will expire soon.

Solution: a new cookie to store the user’s last set of form parameters.

Hurdles:

  • I need a reliable way to serialize the data so I can store it as a string in the cookie
  • When I retrieve the cookie I need to deserialize the data and get it into an ActiveRecord object for form display

This is easily done with Rails using JSON because

  1. Cookie management in Rails is dead simple
  2. Rails extends Ruby’s Object class to include a #to_json method
  3. ActiveSupport provides easy JSON deserialization

Saving the POST in a cookie as JSON

1
2
3
4
5
6
cookies[:last_order]={
  :expires => 1.year.from_now,
  :value => params.to_json(
    :except => [ 'commit', 'authenticity_token', 'action', 'controller' ]
  )
}

When a request comes in I store the user’s order settings in a cookie named ‘last_order’. The cookie expires in 1 year. The value of the cookie is everything returned by #params, minus the stuff I don’t need, in JSON format. The :except filter given to #to_json ensures that I only save what is necessary for recalling the order and nothing more.

Deserializing the cookie into an ActiveRecord

1
2
3
4
5
6
7
8
9
10
def find_order
  serialized=cookies[:last_order]
  return if serialized.blank?
 
  last_order=ActiveSupport::JSON.decode(serialized)
  return if last_order.blank?
 
  @order=Order.new
  @order.attributes=last_order
end

The method checks the request cookies for ‘last_order’. If found we use ActiveSupport::JSON#decode to deserialize the previous POST into a Hash object. If deserialization is successful, instantiate a new ActiveRecord and set its attributes to the parameters retrieved from the cookie. The @order variable is then used in the view with form_for to populate the form with the user’s last selections.

Wrap Up

This works well, and I actually got it working on the first try. I like the solution because JSON is a light-weight serialization format. You could do the same thing using XML or YAML since Rails provides support for the former and Ruby support for the latter, but the output of both was more verbose than what I needed. Since I’m storing in a cookie space is a concern.

This example is based on Rails 2.2.2. The current Rails API seems to be different, so your calls may vary, but the idea stays the same.

You’ll likely want to inspect your cookie. A good way to do that is with Firebug.

Incoming search terms:

  • rails json cookie
  • rails json cookies
  • activerecord store json
  • mighty nice blog
  • rails cookie json
  • rails json session
  • json cookie
  • json cookie rails
  • rails session json
  • store json activerecord

Leave a Reply