Topic: Polymorphic Associations and RESTful design

Hi everyone,

Wanted to throw an idea out there, see if it would work.

I have an application in development which has users and locations.  I'm using a polymorphic association for addresses.

in user.rb

  has_many :addresses, :as => :addressable

in location.rb
  has_one :address, :as => :addressable

in address.rb
  belongs_to :addressable, :polymorphic => true

So far, so good, and it all works.

Now, in setting up a RESTful interface, I'd like to be able to do the following:

map.resources :users do |users|
  users.resources :addresses, :name_prefix => 'user_'

map.resources :locations do |locations|
  locations.resources :addresses, :name_prefix => 'location_'

This assumes 3 controllers, users_controller, locations_controller and addresses_controller.

Any potential gotchas in there, or should that work the way I expect, e.g.:


Re: Polymorphic Associations and RESTful design

So, I found some good information over on the Rails Weenie forum, but there's still a few gaps in my knowledge.

ebryn, in this thread Nested Restful Resources, gave the example of a "find_polymorphic_type_and_id" method in the addresses controller which will return the type and id for the association, allowing the index and create methods to properly load and associate the address with it's parent.

  def find_polymorphic_type_and_id
    # lazy regex, just finds instances of /controller/id
    sections = request.env['REQUEST_URI'].scan(%r{/(\w+)/(\d*)})! do |controller_name, id|
      [controller_name.singularize.camelize, id]
    sections.pop # return the last one, only support one level of polymorphism

The problem this leaves me is, in my app/views/addresses directory, I'm getting all sorts of errors using code like:
address_path(address.addressable, address)

because the above example uses :name_prefix.  So, since I need the links to redirect properly in the nesting, how do I handle using user_address_path(params[:user_id], address) or location_address_path(params[:location_id], address) in a single view template?  Do I need to read the parent controller name from the response.request_uri and set the name prefix dynamically?