RESTful resources in a many-to-many relationship
|
|
So, I have two resources on a many-to-many relationship: Suppliers, and the Materials they sell. A Supplier sells many Materials and a Material can be sold by many Suppliers. I want to work on the suppliers and materials individually (show suppliers, show materials, add a supplier, add a material, etc.) and on their relationship (add a material to a supplier, show which suppliers sell a material, show which materials a supplier sells). What’s the best way of making this RESTful? I’m thinking about putting this in my routes.rb: map.resources :materials, :has_many => :suppliers map.resources :suppliers, :has_many => :materials The thing that troubles me is that if I do this, then for each action in my controllers, I have two routes pointing to it (e.g. a GET on the “suppliers” route and the “material_suppliers” route both point to the index action in the suppliers controller), so I’d have to code my controllers’ actions to do two different things depending on which route gets called. Is there a better or easier way of doing this or am I on the right track? |
|
|
I think in this case, you might actually have another resource here – the join of the supplier and material. I’m not sure what the best name would be, but let’s call it a “distribution” for now. Your models would look something like: class Supplier has_many :distributions has_many :materials, :through => :distributions end class Material has_many :distributions has_many :suppliers, :through => :distributions end class Distribution belongs_to :material belongs_to :supplier end In this way, we’ve made the join model concrete. You can then layer on top of this a standard Distributions resource. it’s not necessary to create this model if you don’t want to. You can still create a controller-only resource, and pick up the supplier/material ids from the params in a before_filter. But I think exploring the join model might be worth it, it sometimes opens up some new avenues of thinking about the problem. |
|
|
I have a similar situation with creating a RESTful :has_many :through relationship. Using the example above, say on the index action for the materials controller, you want to add a link to the create a new distribution on the view. What’s the best way to create a link to the distribution controller’s create action while still passing through the material_id? Is there a RESTful way of doing this? Also, I’m not sure if I did this wrong, but should the join table have its own ID so you can reference it RESTfully? Currently, I did a :id => false when I created my join model. Is that wrong? Anyway, thanks in advance! |
|
|
jvb, Well, you generally won’t have a link to a create action, you’d have a link to a the new action. Generally only forms will point at create actions. To pass a material_id to the new action, you could do:link_to "New Distribution", new_distribution_path, :material_id => @material.id I would suggest keeping the id column in the join model, so that you can easily refer back to the specific Distribution row without needing to pass around the material_id and supplier_id every time. |
|
|
Thanks for the reply Jeff. I figure once you have the id, you would do something like @distribution.material_id = params[:material_id]. However, how would you pass that material_id then to the create action? Is that best way to have a hidden field for that parameter since you have it set on @material? |