3.times { print "Ruby! " }
Fun with ActiveResource

So I’ve been using ActiveResource to consume a RESTful Rails API, and had embarked upon setting up forms for the ActiveResource web client. I’m a big fan of Formtastic, and have been using that for standard ActiveRecord forms for a while now, and figured I’d go ahead and try it with ActiveResource. 

Well, just like the form_for helper, Formtastic relies on the the attributes specified by the object. With ActiveRecord, the attributes are pulled from the database when the object is initialized.  ActiveResource, on the other hand, generates a pretty plain object upon initialization. 

>> User.new()
=> #<User:0x102fd0e00 @prefix_options={}, @attributes={}>

My first instinct was to go ahead and create the attribute accessors in my ActiveResource class by hand. However, as soon as I started typing out all those attributes by hand, I had flash backs of C# and knew I was straying from the Righteous Rails Path to DRY Salvation. (RRPDS)

I then realized that when scaffolding out REST Resources on the API side, Rails generates methods that serialize a new object to XML, which can be reached at /resource/new.xml. It seemed to me that the whole point of serializing a new object would be to make the attributes discoverable. The Rails docs for ActiveResource, however, are strangely mum on the finer points of populating the attributes, and all of the examples simply show passing in an attributes hash to the new method. 

So then it suddenly hit me. Since the find(id) method simply makes a GET request to /resource/id, if I passed in ‘new’ as the id, it should do a GET request to the serialized representation of a new object. 

>> User.find(:new)
=> #<User:0x102e541a8 @prefix_options={}, 
        @attributes={
           "first_name"=>nil,  
           "last_name"=>nil, ... }>

So now I can simply pass Formtastic a User.find(:new), and I’m back to bathing in the glorious DRY light.

UPDATE: As of Rails 3.0, calling Model.build() will do the same thing as Model.find(:new)

blog comments powered by Disqus