module InheritedResources::ClassMethods

def actions(*actions_to_keep)


actions :all, :except => :index
actions :index, :show, :edit

Syntax is borrowed from resource_controller.
Defines wich actions to keep from the inherited controller.
def actions(*actions_to_keep)
  raise ArgumentError, 'Wrong number of arguments. You have to provide which actions you want to keep.' if actions_to_keep.empty?
  options = actions_to_keep.extract_options!
  actions_to_remove = Array(options[:except])
  actions_to_remove += ACTIONS - actions_to_keep.map { |a| a.to_sym } unless actions_to_keep.first == :all
  actions_to_remove.map! { |a| a.to_sym }.uniq!
  (instance_methods.map { |m| m.to_sym } & actions_to_remove).each do |action|
    undef_method action, "#{action}!"
  end
end

def acts_as_polymorphic! #:nodoc:

:nodoc:
def acts_as_polymorphic! #:nodoc:
  unless self.parents_symbols.include?(:polymorphic)
    include PolymorphicHelpers
    helper_method :parent, :parent_type, :parent_class, :parent?
  end
end

def acts_as_singleton! #:nodoc:

:nodoc:
def acts_as_singleton! #:nodoc:
  unless self.resources_configuration[:self][:singleton]
    self.resources_configuration[:self][:singleton] = true
    include SingletonHelpers
    actions :all, :except => :index
  end
end

def belongs_to(*symbols, &block)


type of polymorphic association)
* :optional - Tell the association is optional (it's a special

* :singleton - Tell it's a singleton association.

* :polymorphic - Tell the association is polymorphic.

You supply the collection name.

@company.admin_projects

But if you want to retrieve instead:

@company.projects

down the road:
which belongs to companies. This will do somewhere
suppose you have Tasks which belongs to Projects
* :collection_name - Tell how to retrieve the next collection. Let's

helper. By default is association name.
* :route_name - Allows you to specify what is the route name in your url

Default is :association_id, which in this case is :project_id.
* :param - Allows you to specify params key to retrieve the id.

Project.find(params[:project_id])

Instead of:

Project.find_by_title!(params[:project_id])

This will make your projects be instantiated as:

belongs_to :project, :finder => :find_by_title!

* :finder - Specifies which method should be called to instantiate the parent.

belongs_to :project, :instance_name => :my_project

* :instance_name - The instance variable name. By default is the name of the association.

give a string. Added for ActiveRecord belongs to compatibility.
* :class_name - Also allows you to specify the parent class, but you should

belongs_to :project, :parent_class => AdminProject

* :parent_class - Allows you to specify what is the parent class.

== Options

belongs_to :projects

Defines that this controller belongs to another resource.
def belongs_to(*symbols, &block)
  options = symbols.extract_options!
  options.symbolize_keys!
  options.assert_valid_keys(:class_name, :parent_class, :instance_name, :param,
                            :finder, :route_name, :collection_name, :singleton,
                            :polymorphic, :optional)
  optional    = options.delete(:optional)
  singleton   = options.delete(:singleton)
  polymorphic = options.delete(:polymorphic)
  finder      = options.delete(:finder)
  include BelongsToHelpers if self.parents_symbols.empty?
  acts_as_singleton!   if singleton
  acts_as_polymorphic! if polymorphic || optional
  raise ArgumentError, 'You have to give me at least one association name.' if symbols.empty?
  raise ArgumentError, 'You cannot define multiple associations with options: #{options.keys.inspect} to belongs to.' unless symbols.size == 1 || options.empty?
  symbols.each do |symbol|
    symbol = symbol.to_sym
    if polymorphic || optional
      self.parents_symbols << :polymorphic unless self.parents_symbols.include?(:polymorphic)
      self.resources_configuration[:polymorphic][:symbols]   << symbol
      self.resources_configuration[:polymorphic][:optional] ||= optional
    else
      self.parents_symbols << symbol
    end
    config = self.resources_configuration[symbol] = {}
    config[:parent_class] = options.delete(:parent_class) || begin
      class_name = (options.delete(:class_name) || symbol).to_s.pluralize.classify
      class_name.constantize
    rescue NameError => e
      raise unless e.message.include?(class_name)
      nil
    end
    config[:collection_name] = options.delete(:collection_name) || symbol.to_s.pluralize.to_sym
    config[:instance_name]   = options.delete(:instance_name) || symbol
    config[:param]           = options.delete(:param) || :"#{symbol}_id"
    config[:route_name]      = options.delete(:route_name) || symbol
    config[:finder]          = finder || :find
  end
  if block_given?
    class_eval(&block)
  else
    create_resources_url_helpers!
  end
end

def defaults(options)


* :singleton - Tells if this controller is singleton or not.

controllers. Default to :admin on Admin::ProjectsController.
* :route_prefix - The route prefix which is automically set in namespaced

* :route_instance_name - The name of the singular route. Defaults to :instance_name.

* :route_collection_name - The name of the collection route. Defaults to :collection_name.

:project in ProjectsController.
is set on all actions besides index action. Defaults to
* :instance_name - The name of the singular instance variable which

ProjectsController.
is set on the index action. Defaults to :projects in
* :collection_name - The name of the collection instance variable which

ProjectsController.
by the controller name. Defaults to Project in
* :resource_class - The resource class which by default is guessed

== Options

almost other methods depends on the values given to <>defaults.
this method is called, it should be on the top of your controller, since
Used to overwrite the default assumptions InheritedResources do. Whenever
def defaults(options)
  raise ArgumentError, 'Class method :defaults expects a hash of options.' unless options.is_a? Hash
  options.symbolize_keys!
  options.assert_valid_keys(:resource_class, :collection_name, :instance_name,
                            :class_name, :route_prefix, :route_collection_name,
                            :route_instance_name, :singleton)
  self.resource_class = options.delete(:resource_class)         if options.key?(:resource_class)
  self.resource_class = options.delete(:class_name).constantize if options.key?(:class_name)
  acts_as_singleton! if options.delete(:singleton)
  config = self.resources_configuration[:self]
  config[:route_prefix] = options.delete(:route_prefix) if options.key?(:route_prefix)
  options.each do |key, value|
    config[key] = value.to_sym
  end
  create_resources_url_helpers!
end

def inherited(base) #:nodoc:

:nodoc:

Hook called on inheritance.
def inherited(base) #:nodoc:
  super(base)
  base.send :initialize_resources_class_accessors!
  base.send :create_resources_url_helpers!
end

def initialize_resources_class_accessors! #:nodoc:

:nodoc:

Initialize resources class accessors and set their default values.
def initialize_resources_class_accessors! #:nodoc:
  # Initialize resource class
  self.resource_class = begin
    class_name = self.controller_name.classify
    class_name.constantize
  rescue NameError => e
    raise unless e.message.include?(class_name)
    nil
  end
  # Initialize resources configuration hash
  self.resources_configuration ||= {}
  config = self.resources_configuration[:self] = {}
  config[:collection_name] = self.controller_name.to_sym
  config[:instance_name]   = self.controller_name.singularize.to_sym
  config[:route_collection_name] = config[:collection_name]
  config[:route_instance_name]   = config[:instance_name]
  # Deal with namespaced controllers
  namespaces = self.controller_path.split('/')[0..-2]
  config[:route_prefix] = namespaces.join('_') unless namespaces.empty?
  # Initialize polymorphic, singleton, scopes and belongs_to parameters
  self.parents_symbols ||= []
  self.resources_configuration[:polymorphic] ||= { :symbols => [], :optional => false }
end

def optional_belongs_to(*symbols, &block)


A quick method to declare optional belongs to.
def optional_belongs_to(*symbols, &block)
  options = symbols.extract_options!
  options.merge!(:optional => true)
  belongs_to(*symbols << options, &block)
end

def polymorphic_belongs_to(*symbols, &block)


A quick method to declare polymorphic belongs to.
def polymorphic_belongs_to(*symbols, &block)
  options = symbols.extract_options!
  options.merge!(:polymorphic => true)
  belongs_to(*symbols << options, &block)
end

def singleton_belongs_to(*symbols, &block)


A quick method to declare singleton belongs to.
def singleton_belongs_to(*symbols, &block)
  options = symbols.extract_options!
  options.merge!(:singleton => true)
  belongs_to(*symbols << options, &block)
end