moduleInheritedResourcesmoduleClassMethodsprotected# Used to overwrite the default assumptions InheritedResources do. Whenever# this method is called, it should be on the top of your controller, since# almost other methods depends on the values given to <<tt>>defaults</tt>.## == Options## * <tt>:resource_class</tt> - The resource class which by default is guessed# by the controller name. Defaults to Project in# ProjectsController.## * <tt>:collection_name</tt> - The name of the collection instance variable which# is set on the index action. Defaults to :projects in# ProjectsController.## * <tt>:instance_name</tt> - The name of the singular instance variable which# is set on all actions besides index action. Defaults to# :project in ProjectsController.## * <tt>:route_collection_name</tt> - The name of the collection route. Defaults to :collection_name.## * <tt>:route_instance_name</tt> - The name of the singular route. Defaults to :instance_name.## * <tt>:route_prefix</tt> - The route prefix which is automically set in namespaced# controllers. Default to :admin on Admin::ProjectsController.## * <tt>:singleton</tt> - Tells if this controller is singleton or not.#defdefaults(options)raiseArgumentError,'Class method :defaults expects a hash of options.'unlessoptions.is_a?Hashoptions.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)ifoptions.key?(:resource_class)self.resource_class=options.delete(:class_name).constantizeifoptions.key?(:class_name)acts_as_singleton!ifoptions.delete(:singleton)config=self.resources_configuration[:self]config[:route_prefix]=options.delete(:route_prefix)ifoptions.key?(:route_prefix)options.eachdo|key,value|config[key]=value.to_symendcreate_resources_url_helpers!end# Defines wich actions to keep from the inherited controller.# Syntax is borrowed from resource_controller.## actions :index, :show, :edit# actions :all, :except => :index#defactions(*actions_to_keep)raiseArgumentError,'Wrong number of arguments. You have to provide which actions you want to keep.'ifactions_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}unlessactions_to_keep.first==:allactions_to_remove.map!{|a|a.to_sym}.uniq!(instance_methods.map{|m|m.to_sym}&actions_to_remove).eachdo|action|undef_methodaction,"#{action}!"endend# Defines that this controller belongs to another resource.## belongs_to :projects## == Options## * <tt>:parent_class</tt> - Allows you to specify what is the parent class.## belongs_to :project, :parent_class => AdminProject## * <tt>:class_name</tt> - Also allows you to specify the parent class, but you should# give a string. Added for ActiveRecord belongs to compatibility.## * <tt>:instance_name</tt> - The instance variable name. By default is the name of the association.## belongs_to :project, :instance_name => :my_project## * <tt>:finder</tt> - Specifies which method should be called to instantiate the parent.## belongs_to :project, :finder => :find_by_title!## This will make your projects be instantiated as:## Project.find_by_title!(params[:project_id])## Instead of:## Project.find(params[:project_id])## * <tt>:param</tt> - Allows you to specify params key to retrieve the id.# Default is :association_id, which in this case is :project_id.## * <tt>:route_name</tt> - Allows you to specify what is the route name in your url# helper. By default is association name.## * <tt>:collection_name</tt> - Tell how to retrieve the next collection. Let's# suppose you have Tasks which belongs to Projects# which belongs to companies. This will do somewhere# down the road:## @company.projects## But if you want to retrieve instead:## @company.admin_projects## You supply the collection name.## * <tt>:polymorphic</tt> - Tell the association is polymorphic.## * <tt>:singleton</tt> - Tell it's a singleton association.## * <tt>:optional</tt> - Tell the association is optional (it's a special# type of polymorphic association)#defbelongs_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)includeBelongsToHelpersifself.parents_symbols.empty?acts_as_singleton!ifsingletonacts_as_polymorphic!ifpolymorphic||optionalraiseArgumentError,'You have to give me at least one association name.'ifsymbols.empty?raiseArgumentError,'You cannot define multiple associations with options: #{options.keys.inspect} to belongs to.'unlesssymbols.size==1||options.empty?symbols.eachdo|symbol|symbol=symbol.to_symifpolymorphic||optionalself.parents_symbols<<:polymorphicunlessself.parents_symbols.include?(:polymorphic)self.resources_configuration[:polymorphic][:symbols]<<symbolself.resources_configuration[:polymorphic][:optional]||=optionalelseself.parents_symbols<<symbolendconfig=self.resources_configuration[symbol]={}config[:parent_class]=options.delete(:parent_class)||begin(options.delete(:class_name)||symbol).to_s.pluralize.classify.constantizerescueNameErrornilendconfig[:collection_name]=options.delete(:collection_name)||symbol.to_s.pluralize.to_symconfig[:instance_name]=options.delete(:instance_name)||symbolconfig[:param]=options.delete(:param)||:"#{symbol}_id"config[:route_name]=options.delete(:route_name)||symbolconfig[:finder]=finder||:findendifblock_given?class_eval(&block)elsecreate_resources_url_helpers!endendalias:nested_belongs_to:belongs_to# A quick method to declare polymorphic belongs to.#defpolymorphic_belongs_to(*symbols,&block)options=symbols.extract_options!options.merge!(:polymorphic=>true)belongs_to(*symbols<<options,&block)end# A quick method to declare singleton belongs to.#defsingleton_belongs_to(*symbols,&block)options=symbols.extract_options!options.merge!(:singleton=>true)belongs_to(*symbols<<options,&block)end# A quick method to declare optional belongs to.#defoptional_belongs_to(*symbols,&block)options=symbols.extract_options!options.merge!(:optional=>true)belongs_to(*symbols<<options,&block)endprivatedefacts_as_singleton!#:nodoc:unlessself.resources_configuration[:self][:singleton]self.resources_configuration[:self][:singleton]=trueincludeSingletonHelpersactions:all,:except=>:indexendenddefacts_as_polymorphic!#:nodoc:unlessself.parents_symbols.include?(:polymorphic)includePolymorphicHelpershelper_method:parent,:parent_type,:parent_class,:parent?endend# Initialize resources class accessors and set their default values.#definitialize_resources_class_accessors!#:nodoc:# Initialize resource classself.resource_class=beginself.controller_name.classify.constantizerescueNameErrornilend# Initialize resources configuration hashself.resources_configuration||={}config=self.resources_configuration[:self]={}config[:collection_name]=self.controller_name.to_symconfig[:instance_name]=self.controller_name.singularize.to_symconfig[:route_collection_name]=config[:collection_name]config[:route_instance_name]=config[:instance_name]# Deal with namespaced controllersnamespaces=self.controller_path.split('/')[0..-2]config[:route_prefix]=namespaces.join('_')unlessnamespaces.empty?# Initialize polymorphic, singleton, scopes and belongs_to parametersself.parents_symbols||=[]self.resources_configuration[:polymorphic]||={:symbols=>[],:optional=>false}end# Hook called on inheritance.#definherited(base)#:nodoc:super(base)base.send:initialize_resources_class_accessors!base.send:create_resources_url_helpers!endendend