Module: InheritedResources::PolymorphicHelpers
- Defined in:
- lib/inherited_resources/polymorphic_helpers.rb
Overview
polymorphic associations
In some cases you have a resource that belongs to two different resources but not at the same time. For example, let’s suppose you have File, Message and Task as resources and they are all commentable.
Polymorphic associations allows you to create just one controller that will deal with each case.
class Comment < InheritedResources::Base
belongs_to :file, :message, :task, :polymorphic => true
end
Your routes should be something like:
m.resources :files, :has_many => :comments #=> /files/13/comments
m.resources :tasks, :has_many => :comments #=> /tasks/17/comments
m.resources :messages, :has_many => :comments #=> /messages/11/comments
When using polymorphic associations, you get some free helpers:
parent? #=> true
parent_type #=> :task
parent_class #=> Task
parent #=> @task
This polymorphic controllers thing is a great idea by James Golick and he built it in resource_controller. Here is just a re-implementation.
optional polymorphic associations
Let’s take another break from ProjectsController. Let’s suppose we are building a store, which sell products.
On the website, we can show all products, but also products scoped to categories, brands, users. In this case case, the association is optional, and we deal with it in the following way:
class ProductsController < InheritedResources::Base
belongs_to :category, :brand, :user, :polymorphic => true, :optional => true
end
This will handle all those urls properly:
/products/1
/categories/2/products/5
/brands/10/products/3
/user/13/products/11
nested polymorphic associations
You can have polymorphic associations with nested resources. Let’s suppose that our File, Task and Message resources in the previous example belongs to a project.
This way we can have:
class CommentsController < InheritedResources::Base
belongs_to :project {
belongs_to :file, :message, :task, :polymorphic => true
}
end
Or:
class CommentsController < InheritedResources::Base
nested_belongs_to :project
nested_belongs_to :file, :message, :task, :polymorphic => true
end
Choose the syntax that makes more sense to you. :)
Finally your routes should be something like:
map.resources :projects do |m|
m.resources :files, :has_many => :comments #=> /projects/1/files/13/comments
m.resources :tasks, :has_many => :comments #=> /projects/1/tasks/17/comments
m.resources :messages, :has_many => :comments #=> /projects/1/messages/11/comments
end
The helpers work in the same way as above.