Rails and REST: ActiveResource doesn't play nice with domain-driven resource identifiers
2008-08-28 06:39:00 -0400An update from my post from a few days ago where I talk about REST and domain identifiers. This is the entirety of the code from ActiveResource::Base#save:
def save
new? ? create : update
end
Here’s the punchline:
def new?
id.nil?
end
ActiveResource doesn’t document it, but you can override the primary key that it uses to communicate with your backend system (self.primary_key = :username) and indeed this is the most effective way I know of ensuring that it performs deletes and updates with the appropriate key. The trouble is that if you attempt to create a resource remotely and pre-populate the username (which you’d want to be able to do; it is, after all, a domain identifier) ActiveResource chokes and tries to update the remote resource instead of saving it.
To put it another way: ActiveResource thinks that if your resource has an ID it’s not new. It cannot separate the concepts of auto-increment database-generated ID and resource identifier.
The correct way to solve this problem is to flag any resources retrieved from a remote system as “not new” and consider any other created resources as new. Until that’s fixed I recommend using a conditional approach in which your controller checks incoming IDs and finds on the appropriate column based on whether or not the ID looks like a resource identifier or a database integer. More on that next post.
This is part of a series of posts on Rails and REST. Read the rest.