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.