| Module | Merb::Router::Resources |
| In: |
merb-core/lib/merb-core/dispatch/router/resources.rb
|
Behavior#resource is a route helper for defining a singular RESTful resource. It yields to a block for child routes.
| name<String, Symbol>: | The name of the resource. |
| options<Hash>: | Overides and parameters to be associated with the route. |
: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
| next_level<Behavior>: | The child behavior. |
| Array: | Routes which define a RESTful single resource. |
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
# 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.
| name<String, Symbol>: | The name of the resources |
| options<Hash>: | Ovverides and parameters to be associated with the route |
: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>
| next_level<Behavior>: | The child behavior. |
| Array: | Routes which will define the specified RESTful collection of resources |
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
# 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
:api: private
# 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
# 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