Module Merb::Router::Resources
In: merb-core/lib/merb-core/dispatch/router/resources.rb

Methods

Public Instance methods

Behavior#resource is a route helper for defining a singular RESTful resource. It yields to a block for child routes.

Parameters

name<String, Symbol>:The name of the resource.
options<Hash>:Overides and parameters to be associated with the route.

Options (options)

:namespace<~to_s>: The namespace for this route. :name_prefix<~to_s>:

  A prefix for the named routes. If a namespace is passed and there
  isn't a name prefix, the namespace will become the prefix.

:controller<~to_s>: The controller for this route

Block parameters

next_level<Behavior>:The child behavior.

Returns

Array:Routes which define a RESTful single resource.

Examples

 r.resource :account # will result in the typical RESTful CRUD
   # shows new resource form
   # GET     /account/new                :action => "new"

   # creates resource
   # POST    /account/?(\.:format)?,     :action => "create"

   # shows resource
   # GET     /account/(\.:format)?       :action => "show"

   # shows edit form
   # GET     /account//edit           :action => "edit"

   # updates resource
   # PUT     /account/(\.:format)?       :action => "update"

   # shows deletion confirmation page
   # GET     /account//delete         :action => "delete"

   # destroys resources
   # DELETE  /account/(\.:format)?       :action => "destroy"

You can optionally pass :namespace and :controller to refine the routing or pass a block to nest resources.

  r.resource :account, :namespace => "admin" do |account|
    account.resources :preferences, :controller => "settings"
  end

:api: public

[Source]

     # File merb-core/lib/merb-core/dispatch/router/resources.rb, line 227
227:       def resource(name, *args, &block)
228:         name    = name.to_s
229:         options = extract_options_from_args!(args) || {}
230:         params  = { :controller => options.delete(:controller) || name.pluralize }
231:         member  = { :new => :get, :edit => :get, :delete => :get }.merge(options.delete(:member) || {})
232: 
233:         options[:name_prefix]       ||= nil # Don't use a name_prefix if not needed
234:         options[:resource_prefix]   ||= nil # Don't use a resource_prefix if not needed
235:         options[:controller_prefix] ||= options.delete(:namespace)
236: 
237:         self.namespace(name, options).to(params) do |resource|
238:           # => show
239:           
240:           resource.match("(.:format)", :method => :get).to(:action => "show").
241:             name(name).register_resource(name)
242:             
243:           # => create
244:           resource.match("(.:format)", :method => :post).to(:action => "create")
245:             
246:           # => update
247:           resource.match("(.:format)", :method => :put).to(:action => "update")
248:             
249:           # => destroy
250:           resource.match("(.:format)", :method => :delete).to(:action => "destroy")
251:           
252:           member.each_pair do |action, method|
253:             action = action.to_s
254:             resource.match("/#{action}(.:format)", :method => method).to(:action => action).
255:               name(action, name).register_resource(name, action)
256:           end
257: 
258:           if block_given?
259:             builders = {}
260:             
261:             builders[:member] = lambda do |action, to, method|
262:               resource.match("/#{action}(.:format)", :method => method).to(:action => to).
263:                 name(action, name).register_resource(name, action)
264:             end
265:             
266:             resource.options(:name_prefix => name, :resource_prefix => name).
267:               resource_block(builders, &block)
268:           end
269:         end
270:       end

Behavior#resources is a route helper for defining a collection of RESTful resources. It yields to a block for child routes.

Parameters

name<String, Symbol>:The name of the resources
options<Hash>:Ovverides and parameters to be associated with the route

Options (options)

:namespace<~to_s>: The namespace for this route. :name_prefix<~to_s>:

  A prefix for the named routes. If a namespace is passed and there
  isn't a name prefix, the namespace will become the prefix.

:controller<~to_s>: The controller for this route :collection<~to_s>: Special settings for the collections routes :member<Hash>:

  Special settings and resources related to a specific member of this
  resource.

:identify<Symbol|Array>: The method(s) that should be called on the object

  before inserting it into an URL.

:keys<Array>:

  A list of the keys to be used instead of :id with the resource in the order of the url.

:singular<Symbol>

Block parameters

next_level<Behavior>:The child behavior.

Returns

Array:Routes which will define the specified RESTful collection of resources

Examples

 r.resources :posts # will result in the typical RESTful CRUD
   # lists resources
   # GET     /posts/?(\.:format)?      :action => "index"
   # GET     /posts/index(\.:format)?  :action => "index"

   # shows new resource form
   # GET     /posts/new                :action => "new"

   # creates resource
   # POST    /posts/?(\.:format)?,     :action => "create"

   # shows resource
   # GET     /posts/:id(\.:format)?    :action => "show"

   # shows edit form
   # GET     /posts/:id/edit        :action => "edit"

   # updates resource
   # PUT     /posts/:id(\.:format)?    :action => "update"

   # shows deletion confirmation page
   # GET     /posts/:id/delete      :action => "delete"

   # destroys resources
   # DELETE  /posts/:id(\.:format)?    :action => "destroy"

 # Nesting resources
 r.resources :posts do |posts|
   posts.resources :comments
 end

:api: public

[Source]

     # File merb-core/lib/merb-core/dispatch/router/resources.rb, line 70
 70:       def resources(name, *args, &block)
 71:         name       = name.to_s
 72:         options    = extract_options_from_args!(args) || {}
 73:         match_opts = options.except(*resource_options)
 74:         options    = options.only(*resource_options)
 75:         singular   = options[:singular] ? options[:singular].to_s : Extlib::Inflection.singularize(name)
 76:         klass_name = args.first ? args.first.to_s : singular.to_const_string
 77:         keys       = options.delete(:keys) || options.delete(:key)
 78:         params     = { :controller => options.delete(:controller) || name }
 79:         collection = options.delete(:collection) || {}
 80:         member     = { :edit => :get, :delete => :get }.merge(options.delete(:member) || {})
 81:         
 82:         # Use the identifier for the class as a default
 83:         begin
 84:           if klass = Object.full_const_get(klass_name)
 85:             keys ||= options[:identify]
 86:             keys ||= @identifiers[klass]
 87:           elsif options[:identify]
 88:             raise Error, "The constant #{klass_name} does not exist, please specify the constant for this resource"
 89:           end
 90:         rescue NameError => e
 91:           Merb.logger.debug!("Could not find resource model #{klass_name}")
 92:         end
 93:         
 94:         keys = [ keys || :id ].flatten
 95:         
 96: 
 97:         # Try pulling :namespace out of options for backwards compatibility
 98:         options[:name_prefix]       ||= nil # Don't use a name_prefix if not needed
 99:         options[:resource_prefix]   ||= nil # Don't use a resource_prefix if not needed
100:         options[:controller_prefix] ||= options.delete(:namespace)
101: 
102:         context = options[:identify]
103:         context = klass && options[:identify] ? identify(klass => options.delete(:identify)) : self
104:         context.namespace(name, options).to(params) do |resource|
105:           root_keys = keys.map { |k| ":#{k}" }.join("/")
106:           
107:           # => index
108:           resource.match("(/index)(.:format)", :method => :get).to(:action => "index").
109:             name(name).register_resource(name)
110:             
111:           # => create
112:           resource.match("(.:format)", :method => :post).to(:action => "create")
113:           
114:           # => new
115:           resource.match("/new(.:format)", :method => :get).to(:action => "new").
116:             name("new", singular).register_resource(name, "new")
117: 
118:           # => user defined collection routes
119:           collection.each_pair do |action, method|
120:             action = action.to_s
121:             resource.match("/#{action}(.:format)", :method => method).to(:action => "#{action}").
122:               name(action, name).register_resource(name, action)
123:           end
124: 
125:           # => show
126:           resource.match("/#{root_keys}(.:format)", match_opts.merge(:method => :get)).to(:action => "show").
127:             name(singular).register_resource(klass_name, :identifiers => keys)
128: 
129:           # => user defined member routes
130:           member.each_pair do |action, method|
131:             action = action.to_s
132:             resource.match("/#{root_keys}/#{action}(.:format)", match_opts.merge(:method => method)).
133:               to(:action => "#{action}").name(action, singular).register_resource(klass_name, action, :identifiers => keys)
134:           end
135: 
136:           # => update
137:           resource.match("/#{root_keys}(.:format)", match_opts.merge(:method => :put)).
138:             to(:action => "update")
139:             
140:           # => destroy
141:           resource.match("/#{root_keys}(.:format)", match_opts.merge(:method => :delete)).
142:             to(:action => "destroy")
143: 
144:           if block_given?
145:             parent_keys = keys.map do |k|
146:               k == :id ? "#{singular}_id".to_sym : k
147:             end
148:             
149:             nested_keys = parent_keys.map { |k| ":#{k}" }.join("/")
150: 
151:             nested_match_opts = match_opts.except(:id)
152:             nested_match_opts["#{singular}_id".to_sym] = match_opts[:id] if match_opts[:id]
153:             
154:             # Procs for building the extra collection/member resource routes
155:             placeholder = Router.resource_routes[ [@options[:resource_prefix], klass_name].flatten.compact ]
156:             builders    = {}
157:             
158:             builders[:collection] = lambda do |action, to, method|
159:               resource.before(placeholder).match("/#{action}(.:format)", match_opts.merge(:method => method)).
160:                 to(:action => to).name(action, name).register_resource(name, action)
161:             end
162:             
163:             builders[:member] = lambda do |action, to, method|
164:               resource.match("/#{root_keys}/#{action}(.:format)", match_opts.merge(:method => method)).
165:                 to(:action => to).name(action, singular).register_resource(klass_name, action, :identifiers => keys)
166:             end
167:             
168:             resource.options(:name_prefix => singular, :resource_prefix => klass_name, :parent_keys => parent_keys).
169:               match("/#{nested_keys}", nested_match_opts).resource_block(builders, &block)
170:           end
171:         end # namespace
172:       end

Protected Instance methods

:api: private

[Source]

     # File merb-core/lib/merb-core/dispatch/router/resources.rb, line 275
275:       def register_resource(*key)
276:         options     = extract_options_from_args!(key) || {}
277:         key         = [ @options[:resource_prefix], key ].flatten.compact
278:         identifiers = [ @options[:parent_keys], options[:identifiers] ]
279:         @route.resource = key
280:         @route.resource_identifiers = identifiers.flatten.compact.map { |id| id.to_sym }
281:         self
282:       end

:api: private

[Source]

     # File merb-core/lib/merb-core/dispatch/router/resources.rb, line 285
285:       def resource_block(builders, &block)
286:         behavior = ResourceBehavior.new(builders, @proxy, @conditions, @params, @defaults, @identifiers, @options, @blocks)
287:         with_behavior_context(behavior, &block)
288:       end

[Source]

     # File merb-core/lib/merb-core/dispatch/router/resources.rb, line 290
290:       def resource_options
291:         [:singular, :keys, :key, :controller, :member, :collection, :identify,
292:           :name_prefix, :resource_prefix, :controller_prefix, :namespace, :path]
293:       end

[Validate]