ARes: Suggestions needed for fixing the lack of attributes on a new object

Let's say I have 2 rails app, a "server" and a "client" for a REST resource.

When you create a new ActiveRecord, you have all attributes whit its defaults values on place:

Article.new # On "server" application

=> #<Article id: nil, name: nil, description: nil, price: nil, created_at: nil, updated_at: nil>

Let's compare that with what happens when we create an ActiveResource on client:

Article.new

=> #<Article:0xb7735124 @prefix_options={}, @attributes={}>

Where do the "id", "name", "description", "price", etc... attributes went? When creating a record, it does not initialize the attributes.

       In my opinion, the best way to fix this would be to request a new record to the "server" application via a HTTP request. That way the attributes names of the resource would return it's default values. In my "server" app, requesting http://localhost:3000/articles/new.xml responds the right thing:

<article>        <created-at type="datetime" nil="true"/>        <description nil="true"/>        <name nil="true"/>        <price type="decimal" nil="true"/>        <updated-at type="datetime" nil="true"/> </article>

       There's a caveat for this: making a request in every "new" is expensive for both server and client. In the end, I think this is the right solution anyway.

Someone made a PATCH to "fix" the problem (http://dev.rubyonrails.org/ ticket/9862), although the proposed solution is not the ideal IMHO.

What's your opinion?

Caveat: that's my patch :stuck_out_tongue:

Initially we did try to use the exact method you described, where a requests to /new/ would return a xml with each attribute set to nil.

Sadly, like you mention, this is costly to both the server and the client.

Additionally, ARes makes a good REST client for services not made in Rails and the convention of "requests to /new/ return XML with empty elements" isn't out there. So, depending on a new convention inside of round-trip Rails solution limits the usefulness of ARes as a client to non-Rails services.

The patch referenced (http://dev.rubyonrails.org/ticket/9862) fixes the problem internal to ARes by returning "nil" on missing getter methods for new ARes objects.

So, assuming a new, blank ARes Article object article.title #=> nil (instead of method_missing). if the object hasn't yet talked to the server and received data to load into attributes.

An ARes object that is not new (i.e. we know it's attrs because it came from the remote service with them detailed) article.category #=> method_missing. The non-new ARes doesn't have a category attr. The remote server listed the existing attributes and category wasn't one of them.

This better fits with the *existing* pattern of setter methods on ARes setting the attribute (even if it doesn't yet exist). Assuming a blank ARes object again: article.body = "lorem impsum" #=> "lorem impsum"

Since ARes is really just a nice object wrapper around XML or json it seems useful that the setting/getting pattern should be about crafting that XML you send out or accessing that XML you get back (in a manner pleasing to the remote service).

An interim solution we've been using is aliasing the constructor and manually setting each attribute we work with in forms to nil.

-Trek

I think your patch is really useful, and should be comited.

But beside commiting that fix, it could be say that there are 3 options here:

1) Leave things as they are: no initialization of attributes by requesting of resource/new.xml to server. 2) Change initialize to request resource/new.xml to server 3) "Manually" configure the attributes of the resource on the class. I.E.: self.site="http://bla"; self.attributes=%w|name price etc| or self.attributes= {   :attribute => "default",   ... }

But what I think would be even better is

4) Allow any of previous behaviors, leave 1) (current behavior: no attrs) as default.