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.