root/trunk/actionpack/lib/action_controller/resources.rb
| Revision 9093, 23.0 kB (checked in by pratik, 6 months ago) |
|---|
| Line | |
|---|---|
| 1 | module ActionController |
| 2 | # == Overview |
| 3 | # |
| 4 | # ActionController::Resources are a way of defining RESTful resources. A RESTful resource, in basic terms, |
| 5 | # is something that can be pointed at and it will respond with a representation of the data requested. |
| 6 | # In real terms this could mean a user with a browser requests an HTML page, or that a desktop application |
| 7 | # requests XML data. |
| 8 | # |
| 9 | # RESTful design is based on the assumption that there are four generic verbs that a user of an |
| 10 | # application can request from a resource (the noun). |
| 11 | # |
| 12 | # Resources can be requested using four basic HTTP verbs (GET, POST, PUT, DELETE), the method used |
| 13 | # denotes the type of action that should take place. |
| 14 | # |
| 15 | # === The Different Methods and their Usage |
| 16 | # |
| 17 | # +GET+ Requests for a resource, no saving or editing of a resource should occur in a GET request |
| 18 | # +POST+ Creation of resources |
| 19 | # +PUT+ Editing of attributes on a resource |
| 20 | # +DELETE+ Deletion of a resource |
| 21 | # |
| 22 | # === Examples |
| 23 | # |
| 24 | # # A GET request on the Posts resource is asking for all Posts |
| 25 | # GET /posts |
| 26 | # |
| 27 | # # A GET request on a single Post resource is asking for that particular Post |
| 28 | # GET /posts/1 |
| 29 | # |
| 30 | # # A POST request on the Posts resource is asking for a Post to be created with the supplied details |
| 31 | # POST /posts # with => { :post => { :title => "My Whizzy New Post", :body => "I've got a brand new combine harvester" } } |
| 32 | # |
| 33 | # # A PUT request on a single Post resource is asking for a Post to be updated |
| 34 | # PUT /posts # with => { :id => 1, :post => { :title => "Changed Whizzy Title" } } |
| 35 | # |
| 36 | # # A DELETE request on a single Post resource is asking for it to be deleted |
| 37 | # DELETE /posts # with => { :id => 1 } |
| 38 | # |
| 39 | # By using the REST convention, users of our application can assume certain things about how the data |
| 40 | # is requested and how it is returned. Rails simplifies the routing part of RESTful design by |
| 41 | # supplying you with methods to create them in your routes.rb file. |
| 42 | # |
| 43 | # Read more about REST at http://en.wikipedia.org/wiki/Representational_State_Transfer |
| 44 | module Resources |
| 45 | class Resource #:nodoc: |
| 46 | attr_reader :collection_methods, :member_methods, :new_methods |
| 47 | attr_reader :path_prefix, :name_prefix, :path_segment |
| 48 | attr_reader :plural, :singular |
| 49 | attr_reader :options |
| 50 | |
| 51 | def initialize(entities, options) |
| 52 | @plural ||= entities |
| 53 | @singular ||= options[:singular] || plural.to_s.singularize |
| 54 | @path_segment = options.delete(:as) || @plural |
| 55 | |
| 56 | @options = options |
| 57 | |
| 58 | arrange_actions |
| 59 | add_default_actions |
| 60 | set_prefixes |
| 61 | end |
| 62 | |
| 63 | def controller |
| 64 | @controller ||= "#{options[:namespace]}#{(options[:controller] || plural).to_s}" |
| 65 | end |
| 66 | |
| 67 | def requirements(with_id = false) |
| 68 | @requirements ||= @options[:requirements] || {} |
| 69 | @id_requirement ||= { :id => @requirements.delete(:id) || /[^#{Routing::SEPARATORS.join}]+/ } |
| 70 | |
| 71 | with_id ? @requirements.merge(@id_requirement) : @requirements |
| 72 | end |
| 73 | |
| 74 | def conditions |
| 75 | @conditions = @options[:conditions] || {} |
| 76 | end |
| 77 | |
| 78 | def path |
| 79 | @path ||= "#{path_prefix}/#{path_segment}" |
| 80 | end |
| 81 | |
| 82 | def new_path |
| 83 | @new_path ||= "#{path}/new" |
| 84 | end |
| 85 | |
| 86 | def member_path |
| 87 | @member_path ||= "#{path}/:id" |
| 88 | end |
| 89 | |
| 90 | def nesting_path_prefix |
| 91 | @nesting_path_prefix ||= "#{path}/:#{singular}_id" |
| 92 | end |
| 93 | |
| 94 | def nesting_name_prefix |
| 95 | "#{name_prefix}#{singular}_" |
| 96 | end |
| 97 | |
| 98 | def action_separator |
| 99 | @action_separator ||= Base.resource_action_separator |
| 100 | end |
| 101 | |
| 102 | def uncountable? |
| 103 | @singular.to_s == @plural.to_s |
| 104 | end |
| 105 | |
| 106 | protected |
| 107 | def arrange_actions |
| 108 | @collection_methods = arrange_actions_by_methods(options.delete(:collection)) |
| 109 | @member_methods = arrange_actions_by_methods(options.delete(:member)) |
| 110 | @new_methods = arrange_actions_by_methods(options.delete(:new)) |
| 111 | end |
| 112 | |
| 113 | def add_default_actions |
| 114 | add_default_action(member_methods, :get, :edit) |
| 115 | add_default_action(new_methods, :get, :new) |
| 116 | end |
| 117 | |
| 118 | def set_prefixes |
| 119 | @path_prefix = options.delete(:path_prefix) |
| 120 | @name_prefix = options.delete(:name_prefix) |
| 121 | end |
| 122 | |
| 123 | def arrange_actions_by_methods(actions) |
| 124 | (actions || {}).inject({}) do |flipped_hash, (key, value)| |
| 125 | (flipped_hash[value] ||= []) << key |
| 126 | flipped_hash |
| 127 | end |
| 128 | end |
| 129 | |
| 130 | def add_default_action(collection, method, action) |
| 131 | (collection[method] ||= []).unshift(action) |
| 132 | end |
| 133 | end |
| 134 | |
| 135 | class SingletonResource < Resource #:nodoc: |
| 136 | def initialize(entity, options) |
| 137 | @singular = @plural = entity |
| 138 | options[:controller] ||= @singular.to_s.pluralize |
| 139 | super |
| 140 | end |
| 141 | |
| 142 | alias_method :member_path, :path |
| 143 | alias_method :nesting_path_prefix, :path |
| 144 | end |
| 145 | |
| 146 | # Creates named routes for implementing verb-oriented controllers |
| 147 | # for a collection resource. |
| 148 | # |
| 149 | # For example: |
| 150 | # |
| 151 | # map.resources :messages |
| 152 | # |
| 153 | # will map the following actions in the corresponding controller: |
| 154 | # |
| 155 | # class MessagesController < ActionController::Base |
| 156 | # # GET messages_url |
| 157 | # def index |
| 158 | # # return all messages |
| 159 | # end |
| 160 | # |
| 161 | # # GET new_message_url |
| 162 | # def new |
| 163 | # # return an HTML form for describing a new message |
| 164 | # end |
| 165 | # |
| 166 | # # POST messages_url |
| 167 | # def create |
| 168 | # # create a new message |
| 169 | # end |
| 170 | # |
| 171 | # # GET message_url(:id => 1) |
| 172 | # def show |
| 173 | # # find and return a specific message |
| 174 | # end |
| 175 | # |
| 176 | # # GET edit_message_url(:id => 1) |
| 177 | # def edit |
| 178 | # # return an HTML form for editing a specific message |
| 179 | # end |
| 180 | # |
| 181 | # # PUT message_url(:id => 1) |
| 182 | # def update |
| 183 | # # find and update a specific message |
| 184 | # end |
| 185 | # |
| 186 | # # DELETE message_url(:id => 1) |
| 187 | # def destroy |
| 188 | # # delete a specific message |
| 189 | # end |
| 190 | # end |
| 191 | # |
| 192 | # Along with the routes themselves, #resources generates named routes for use in |
| 193 | # controllers and views. <tt>map.resources :messages</tt> produces the following named routes and helpers: |
| 194 | # |
| 195 | # Named Route Helpers |
| 196 | # ============ ===================================================== |
| 197 | # messages messages_url, hash_for_messages_url, |
| 198 | # messages_path, hash_for_messages_path |
| 199 | # |
| 200 | # message message_url(id), hash_for_message_url(id), |
| 201 | # message_path(id), hash_for_message_path(id) |
| 202 | # |
| 203 | # new_message new_message_url, hash_for_new_message_url, |
| 204 | # new_message_path, hash_for_new_message_path |
| 205 | # |
| 206 | # edit_message edit_message_url(id), hash_for_edit_message_url(id), |
| 207 | # edit_message_path(id), hash_for_edit_message_path(id) |
| 208 | # |
| 209 | # You can use these helpers instead of #url_for or methods that take #url_for parameters. For example: |
| 210 | # |
| 211 | # redirect_to :controller => 'messages', :action => 'index' |
| 212 | # # and |
| 213 | # <%= link_to "edit this message", :controller => 'messages', :action => 'edit', :id => @message.id %> |
| 214 | # |
| 215 | # now become: |
| 216 | # |
| 217 | # redirect_to messages_url |
| 218 | # # and |
| 219 | # <%= link_to "edit this message", edit_message_url(@message) # calls @message.id automatically |
| 220 | # |
| 221 | # Since web browsers don't support the PUT and DELETE verbs, you will need to add a parameter '_method' to your |
| 222 | # form tags. The form helpers make this a little easier. For an update form with a <tt>@message</tt> object: |
| 223 | # |
| 224 | # <%= form_tag message_path(@message), :method => :put %> |
| 225 | # |
| 226 | # or |
| 227 | # |
| 228 | # <% form_for :message, @message, :url => message_path(@message), :html => {:method => :put} do |f| %> |
| 229 | # |
| 230 | # or |
| 231 | # |
| 232 | # <% form_for @message do |f| %> |
| 233 | # |
| 234 | # which takes into account whether <tt>@message</tt> is a new record or not and generates the |
| 235 | # path and method accordingly. |
| 236 | # |
| 237 | # The #resources method accepts the following options to customize the resulting routes: |
| 238 | # * <tt>:collection</tt> - add named routes for other actions that operate on the collection. |
| 239 | # Takes a hash of <tt>#{action} => #{method}</tt>, where method is <tt>:get</tt>/<tt>:post</tt>/<tt>:put</tt>/<tt>:delete</tt> |
| 240 | # or <tt>:any</tt> if the method does not matter. These routes map to a URL like /messages/rss, with a route of rss_messages_url. |
| 241 | # * <tt>:member</tt> - same as :collection, but for actions that operate on a specific member. |
| 242 | # * <tt>:new</tt> - same as :collection, but for actions that operate on the new resource action. |
| 243 | # * <tt>:controller</tt> - specify the controller name for the routes. |
| 244 | # * <tt>:singular</tt> - specify the singular name used in the member routes. |
| 245 | # * <tt>:requirements</tt> - set custom routing parameter requirements. |
| 246 | # * <tt>:conditions</tt> - specify custom routing recognition conditions. Resources sets the :method value for the method-specific routes. |
| 247 | # * <tt>:as</tt> - specify a different resource name to use in the URL path. For example: |
| 248 | # # products_path == '/productos' |
| 249 | # map.resources :products, :as => 'productos' do |product| |
| 250 | # # product_reviews_path(product) == '/productos/1234/comentarios' |
| 251 | # product.resources :product_reviews, :as => 'comentarios' |
| 252 | # end |
| 253 | # |
| 254 | # * <tt>:has_one</tt> - specify nested resources, this is a shorthand for mapping singleton resources beneath the current. |
| 255 | # * <tt>:has_many</tt> - same has :has_one, but for plural resources. |
| 256 | # |
| 257 | # You may directly specify the routing association with has_one and has_many like: |
| 258 | # |
| 259 | # map.resources :notes, :has_one => :author, :has_many => [:comments, :attachments] |
| 260 | # |
| 261 | # This is the same as: |
| 262 | # |
| 263 | # map.resources :notes do |notes| |
| 264 | # notes.resource :author |
| 265 | # notes.resources :comments |
| 266 | # notes.resources :attachments |
| 267 | # end |
| 268 | # |
| 269 | # * <tt>:path_prefix</tt> - set a prefix to the routes with required route variables. |
| 270 | # |
| 271 | # Weblog comments usually belong to a post, so you might use resources like: |
| 272 | # |
| 273 | # map.resources :articles |
| 274 | # map.resources :comments, :path_prefix => '/articles/:article_id' |
| 275 | # |
| 276 | # You can nest resources calls to set this automatically: |
| 277 | # |
| 278 | # map.resources :articles do |article| |
| 279 | # article.resources :comments |
| 280 | # end |
| 281 | # |
| 282 | # The comment resources work the same, but must now include a value for :article_id. |
| 283 | # |
| 284 | # article_comments_url(@article) |
| 285 | # article_comment_url(@article, @comment) |
| 286 | # |
| 287 | # article_comments_url(:article_id => @article) |
| 288 | # article_comment_url(:article_id => @article, :id => @comment) |
| 289 | # |
| 290 | # * <tt>:name_prefix</tt> - define a prefix for all generated routes, usually ending in an underscore. |
| 291 | # Use this if you have named routes that may clash. |
| 292 | # |
| 293 | # map.resources :tags, :path_prefix => '/books/:book_id', :name_prefix => 'book_' |
| 294 | # map.resources :tags, :path_prefix => '/toys/:toy_id', :name_prefix => 'toy_' |
| 295 | # |
| 296 | # You may also use :name_prefix to override the generic named routes in a nested resource: |
| 297 | # |
| 298 | # map.resources :articles do |article| |
| 299 | # article.resources :comments, :name_prefix => nil |
| 300 | # end |
| 301 | # |
| 302 | # This will yield named resources like so: |
| 303 | # |
| 304 | # comments_url(@article) |
| 305 | # comment_url(@article, @comment) |
| 306 | # |
| 307 | # If <tt>map.resources</tt> is called with multiple resources, they all get the same options applied. |
| 308 | # |
| 309 | # Examples: |
| 310 | # |
| 311 | # map.resources :messages, :path_prefix => "/thread/:thread_id" |
| 312 | # # --> GET /thread/7/messages/1 |
| 313 | # |
| 314 | # map.resources :messages, :collection => { :rss => :get } |
| 315 | # # --> GET /messages/rss (maps to the #rss action) |
| 316 | # # also adds a named route called "rss_messages" |
| 317 | # |
| 318 | # map.resources :messages, :member => { :mark => :post } |
| 319 | # # --> POST /messages/1/mark (maps to the #mark action) |
| 320 | # # also adds a named route called "mark_message" |
| 321 | # |
| 322 | # map.resources :messages, :new => { :preview => :post } |
| 323 | # # --> POST /messages/new/preview (maps to the #preview action) |
| 324 | # # also adds a named route called "preview_new_message" |
| 325 | # |
| 326 | # map.resources :messages, :new => { :new => :any, :preview => :post } |
| 327 | # # --> POST /messages/new/preview (maps to the #preview action) |
| 328 | # # also adds a named route called "preview_new_message" |
| 329 | # # --> /messages/new can be invoked via any request method |
| 330 | # |
| 331 | # map.resources :messages, :controller => "categories", |
| 332 | # :path_prefix => "/category/:category_id", |
| 333 | # :name_prefix => "category_" |
| 334 | # # --> GET /categories/7/messages/1 |
| 335 | # # has named route "category_message" |
| 336 | # |
| 337 | # The #resources method sets HTTP method restrictions on the routes it generates. For example, making an |
| 338 | # HTTP POST on <tt>new_message_url</tt> will raise a RoutingError exception. The default route in |
| 339 | # <tt>config/routes.rb</tt> overrides this and allows invalid HTTP methods for resource routes. |
| 340 | def resources(*entities, &block) |
| 341 | options = entities.extract_options! |
| 342 | entities.each { |entity| map_resource(entity, options.dup, &block) } |
| 343 | end |
| 344 | |
| 345 | # Creates named routes for implementing verb-oriented controllers for a singleton resource. |
| 346 | # A singleton resource is global to its current context. For unnested singleton resources, |
| 347 | # the resource is global to the current user visiting the application, such as a user's |
| 348 | # /account profile. For nested singleton resources, the resource is global to its parent |
| 349 | # resource, such as a <tt>projects</tt> resource that <tt>has_one :project_manager</tt>. |
| 350 | # The <tt>project_manager</tt> should be mapped as a singleton resource under <tt>projects</tt>: |
| 351 | # |
| 352 | # map.resources :projects do |project| |
| 353 | # project.resource :project_manager |
| 354 | # end |
| 355 | # |
| 356 | # See map.resources for general conventions. These are the main differences: |
| 357 | # * A singular name is given to map.resource. The default controller name is still taken from the plural name. |
| 358 | # * To specify a custom plural name, use the :plural option. There is no :singular option. |
| 359 | # * No default index route is created for the singleton resource controller. |
| 360 | # * When nesting singleton resources, only the singular name is used as the path prefix (example: 'account/messages/1') |
| 361 | # |
| 362 | # For example: |
| 363 | # |
| 364 | # map.resource :account |
| 365 | # |
| 366 | # maps these actions in the Accounts controller: |
| 367 | # |
| 368 | # class AccountsController < ActionController::Base |
| 369 | # # GET new_account_url |
| 370 | # def new |
| 371 | # # return an HTML form for describing the new account |
| 372 | # end |
| 373 | # |
| 374 | # # POST account_url |
| 375 | # def create |
| 376 | # # create an account |
| 377 | # end |
| 378 | # |
| 379 | # # GET account_url |
| 380 | # def show |
| 381 | # # find and return the account |
| 382 | # end |
| 383 | # |
| 384 | # # GET edit_account_url |
| 385 | # def edit |
| 386 | # # return an HTML form for editing the account |
| 387 | # end |
| 388 | # |
| 389 | # # PUT account_url |
| 390 | # def update |
| 391 | # # find and update the account |
| 392 | # end |
| 393 | # |
| 394 | # # DELETE account_url |
| 395 | # def destroy |
| 396 | # # delete the account |
| 397 | # end |
| 398 | # end |
| 399 | # |
| 400 | # Along with the routes themselves, #resource generates named routes for |
| 401 | # use in controllers and views. <tt>map.resource :account</tt> produces |
| 402 | # these named routes and helpers: |
| 403 | # |
| 404 | # Named Route Helpers |
| 405 | # ============ ============================================= |
| 406 | # account account_url, hash_for_account_url, |
| 407 | # account_path, hash_for_account_path |
| 408 | # |
| 409 | # new_account new_account_url, hash_for_new_account_url, |
| 410 | # new_account_path, hash_for_new_account_path |
| 411 | # |
| 412 | # edit_account edit_account_url, hash_for_edit_account_url, |
| 413 | # edit_account_path, hash_for_edit_account_path |
| 414 | def resource(*entities, &block) |
| 415 | options = entities.extract_options! |
| 416 | entities.each { |entity| map_singleton_resource(entity, options.dup, &block) } |
| 417 | end |
| 418 | |
| 419 | private |
| 420 | def map_resource(entities, options = {}, &block) |
| 421 | resource = Resource.new(entities, options) |
| 422 | |
| 423 | with_options :controller => resource.controller do |map| |
| 424 | map_collection_actions(map, resource) |
| 425 | map_default_collection_actions(map, resource) |
| 426 | map_new_actions(map, resource) |
| 427 | map_member_actions(map, resource) |
| 428 | |
| 429 | map_associations(resource, options) |
| 430 | |
| 431 | if block_given? |
| 432 | with_options(:path_prefix => resource.nesting_path_prefix, :name_prefix => resource.nesting_name_prefix, :namespace => options[:namespace], &block) |
| 433 | end |
| 434 | end |
| 435 | end |
| 436 | |
| 437 | def map_singleton_resource(entities, options = {}, &block) |
| 438 | resource = SingletonResource.new(entities, options) |
| 439 | |
| 440 | with_options :controller => resource.controller do |map| |
| 441 | map_collection_actions(map, resource) |
| 442 | map_default_singleton_actions(map, resource) |
| 443 | map_new_actions(map, resource) |
| 444 | map_member_actions(map, resource) |
| 445 | |
| 446 | map_associations(resource, options) |
| 447 | |
| 448 | if block_given? |
| 449 | with_options(:path_prefix => resource.nesting_path_prefix, :name_prefix => resource.nesting_name_prefix, :namespace => options[:namespace], &block) |
| 450 | end |
| 451 | end |
| 452 | end |
| 453 | |
| 454 | def map_associations(resource, options) |
| 455 | path_prefix = "#{options.delete(:path_prefix)}#{resource.nesting_path_prefix}" |
| 456 | name_prefix = "#{options.delete(:name_prefix)}#{resource.nesting_name_prefix}" |
| 457 | |
| 458 | Array(options[:has_many]).each do |association| |
| 459 | resources(association, :path_prefix => path_prefix, :name_prefix => name_prefix, :namespace => options[:namespace]) |
| 460 | end |
| 461 | |
| 462 | Array(options[:has_one]).each do |association| |
| 463 | resource(association, :path_prefix => path_prefix, :name_prefix => name_prefix, :namespace => options[:namespace]) |
| 464 | end |
| 465 | end |
| 466 | |
| 467 | def map_collection_actions(map, resource) |
| 468 | resource.collection_methods.each do |method, actions| |
| 469 | actions.each do |action| |
| 470 | action_options = action_options_for(action, resource, method) |
| 471 | map.named_route("#{action}_#{resource.name_prefix}#{resource.plural}", "#{resource.path}#{resource.action_separator}#{action}", action_options) |
| 472 | map.named_route("formatted_#{action}_#{resource.name_prefix}#{resource.plural}", "#{resource.path}#{resource.action_separator}#{action}.:format", action_options) |
| 473 | end |
| 474 | end |
| 475 | end |
| 476 | |
| 477 | def map_default_collection_actions(map, resource) |
| 478 | index_action_options = action_options_for("index", resource) |
| 479 | index_route_name = "#{resource.name_prefix}#{resource.plural}" |
| 480 | |
| 481 | if resource.uncountable? |
| 482 | index_route_name << "_index" |
| 483 | end |
| 484 | |
| 485 | map.named_route(index_route_name, resource.path, index_action_options) |
| 486 | map.named_route("formatted_#{index_route_name}", "#{resource.path}.:format", index_action_options) |
| 487 | |
| 488 | create_action_options = action_options_for("create", resource) |
| 489 | map.connect(resource.path, create_action_options) |
| 490 | map.connect("#{resource.path}.:format", create_action_options) |
| 491 | end |
| 492 | |
| 493 | def map_default_singleton_actions(map, resource) |
| 494 | create_action_options = action_options_for("create", resource) |
| 495 | map.connect(resource.path, create_action_options) |
| 496 | map.connect("#{resource.path}.:format", create_action_options) |
| 497 | end |
| 498 | |
| 499 | def map_new_actions(map, resource) |
| 500 | resource.new_methods.each do |method, actions| |
| 501 | actions.each do |action| |
| 502 | action_options = action_options_for(action, resource, method) |
| 503 | if action == :new |
| 504 | map.named_route("new_#{resource.name_prefix}#{resource.singular}", resource.new_path, action_options) |
| 505 | map.named_route("formatted_new_#{resource.name_prefix}#{resource.singular}", "#{resource.new_path}.:format", action_options) |
| 506 | else |
| 507 | map.named_route("#{action}_new_#{resource.name_prefix}#{resource.singular}", "#{resource.new_path}#{resource.action_separator}#{action}", action_options) |
| 508 | map.named_route("formatted_#{action}_new_#{resource.name_prefix}#{resource.singular}", "#{resource.new_path}#{resource.action_separator}#{action}.:format", action_options) |
| 509 | end |
| 510 | end |
| 511 | end |
| 512 | end |
| 513 | |
| 514 | def map_member_actions(map, resource) |
| 515 | resource.member_methods.each do |method, actions| |
| 516 | actions.each do |action| |
| 517 | action_options = action_options_for(action, resource, method) |
| 518 | map.named_route("#{action}_#{resource.name_prefix}#{resource.singular}", "#{resource.member_path}#{resource.action_separator}#{action}", action_options) |
| 519 | map.named_route("formatted_#{action}_#{resource.name_prefix}#{resource.singular}", "#{resource.member_path}#{resource.action_separator}#{action}.:format",action_options) |
| 520 | end |
| 521 | end |
| 522 | |
| 523 | show_action_options = action_options_for("show", resource) |
| 524 | map.named_route("#{resource.name_prefix}#{resource.singular}", resource.member_path, show_action_options) |
| 525 | map.named_route("formatted_#{resource.name_prefix}#{resource.singular}", "#{resource.member_path}.:format", show_action_options) |
| 526 | |
| 527 | update_action_options = action_options_for("update", resource) |
| 528 | map.connect(resource.member_path, update_action_options) |
| 529 | map.connect("#{resource.member_path}.:format", update_action_options) |
| 530 | |
| 531 | destroy_action_options = action_options_for("destroy", resource) |
| 532 | map.connect(resource.member_path, destroy_action_options) |
| 533 | map.connect("#{resource.member_path}.:format", destroy_action_options) |
| 534 | end |
| 535 | |
| 536 | def add_conditions_for(conditions, method) |
| 537 | returning({:conditions => conditions.dup}) do |options| |
| 538 | options[:conditions][:method] = method unless method == :any |
| 539 | end |
| 540 | end |
| 541 | |
| 542 | def action_options_for(action, resource, method = nil) |
| 543 | default_options = { :action => action.to_s } |
| 544 | require_id = !resource.kind_of?(SingletonResource) |
| 545 | case default_options[:action] |
| 546 | when "index", "new"; default_options.merge(add_conditions_for(resource.conditions, method || :get)).merge(resource.requirements) |
| 547 | when "create"; default_options.merge(add_conditions_for(resource.conditions, method || :post)).merge(resource.requirements) |
| 548 | when "show", "edit"; default_options.merge(add_conditions_for(resource.conditions, method || :get)).merge(resource.requirements(require_id)) |
| 549 | when "update"; default_options.merge(add_conditions_for(resource.conditions, method || :put)).merge(resource.requirements(require_id)) |
| 550 | when "destroy"; default_options.merge(add_conditions_for(resource.conditions, method || :delete)).merge(resource.requirements(require_id)) |
| 551 | else default_options.merge(add_conditions_for(resource.conditions, method)).merge(resource.requirements) |
| 552 | end |
| 553 | end |
| 554 | end |
| 555 | end |
| 556 | |
| 557 | class ActionController::Routing::RouteSet::Mapper |
| 558 | include ActionController::Resources |
| 559 | end |
Note: See TracBrowser for help on using the browser.