Permalink
Browse files

Add router support for resources :only and :except actions

  • Loading branch information...
1 parent 5d78759 commit d01716731bd9c68de686d6ac85e3da5251305495 @josh josh committed Jan 13, 2010
Showing with 56 additions and 16 deletions.
  1. +38 −16 actionpack/lib/action_dispatch/routing/mapper.rb
  2. +18 −0 actionpack/test/dispatch/routing_test.rb
View
54 actionpack/lib/action_dispatch/routing/mapper.rb
@@ -324,7 +324,11 @@ module Resources
CRUD_ACTIONS = [:index, :show, :new, :edit, :create, :update, :destroy]
class Resource #:nodoc:
- attr_reader :plural, :singular
+ def self.default_actions
+ [:index, :create, :new, :show, :update, :destroy, :edit]
+ end
+
+ attr_reader :plural, :singular, :options
def initialize(entities, options = {})
entities = entities.to_s
@@ -334,8 +338,22 @@ def initialize(entities, options = {})
@singular = entities.singularize
end
+ def default_actions
+ self.class.default_actions
+ end
+
+ def actions
+ if only = options[:only]
+ only.map(&:to_sym)
+ elsif except = options[:except]
+ default_actions - except.map(&:to_sym)
+ else
+ default_actions
+ end
+ end
+
def name
- @options[:as] || plural
+ options[:as] || plural
end
def controller
@@ -356,12 +374,16 @@ def id_segment
end
class SingletonResource < Resource #:nodoc:
+ def self.default_actions
+ [:show, :create, :update, :destroy, :new, :edit]
+ end
+
def initialize(entity, options = {})
super
end
def name
- @options[:as] || singular
+ options[:as] || singular
end
end
@@ -387,12 +409,12 @@ def resource(*resources, &block)
with_scope_level(:resource, resource) do
yield if block_given?
- get "(.:format)", :to => :show, :as => resource.member_name
- post "(.:format)", :to => :create
- put "(.:format)", :to => :update
- delete "(.:format)", :to => :destroy
- get "/new(.:format)", :to => :new, :as => "new_#{resource.singular}"
- get "/edit(.:format)", :to => :edit, :as => "edit_#{resource.singular}"
+ get "(.:format)", :to => :show, :as => resource.member_name if resource.actions.include?(:show)
+ post "(.:format)", :to => :create if resource.actions.include?(:create)
+ put "(.:format)", :to => :update if resource.actions.include?(:update)
+ delete "(.:format)", :to => :destroy if resource.actions.include?(:destroy)
+ get "/new(.:format)", :to => :new, :as => "new_#{resource.singular}" if resource.actions.include?(:new)
+ get "/edit(.:format)", :to => :edit, :as => "edit_#{resource.singular}" if resource.actions.include?(:edit)
end
end
@@ -422,22 +444,22 @@ def resources(*resources, &block)
yield if block_given?
with_scope_level(:collection) do
- get "(.:format)", :to => :index, :as => resource.collection_name
- post "(.:format)", :to => :create
+ get "(.:format)", :to => :index, :as => resource.collection_name if resource.actions.include?(:index)
+ post "(.:format)", :to => :create if resource.actions.include?(:create)
with_exclusive_name_prefix :new do
- get "/new(.:format)", :to => :new, :as => resource.singular
+ get "/new(.:format)", :to => :new, :as => resource.singular if resource.actions.include?(:new)
end
end
with_scope_level(:member) do
scope("/:id") do
- get "(.:format)", :to => :show, :as => resource.member_name
- put "(.:format)", :to => :update
- delete "(.:format)", :to => :destroy
+ get "(.:format)", :to => :show, :as => resource.member_name if resource.actions.include?(:show)
+ put "(.:format)", :to => :update if resource.actions.include?(:update)
+ delete "(.:format)", :to => :destroy if resource.actions.include?(:destroy)
with_exclusive_name_prefix :edit do
- get "/edit(.:format)", :to => :edit, :as => resource.singular
+ get "/edit(.:format)", :to => :edit, :as => resource.singular if resource.actions.include?(:edit)
end
end
end
View
18 actionpack/test/dispatch/routing_test.rb
@@ -93,6 +93,8 @@ def self.matches?(request)
end
end
+ resources :posts, :only => [:index, :show]
+
match 'sprockets.js' => ::TestRoutingMapper::SprocketsApp
match 'people/:id/update', :to => 'people#update', :as => :update_person
@@ -421,6 +423,22 @@ def test_projects_posts
end
end
+ def test_posts
+ with_test_routes do
+ get '/posts'
+ assert_equal 'posts#index', @response.body
+ assert_equal '/posts', posts_path
+
+ get '/posts/1'
+ assert_equal 'posts#show', @response.body
+ assert_equal '/posts/1', post_path(:id => 1)
+
+ assert_raise(ActionController::RoutingError) { post '/posts' }
+ assert_raise(ActionController::RoutingError) { put '/posts/1' }
+ assert_raise(ActionController::RoutingError) { delete '/posts/1' }
+ end
+ end
+
def test_sprockets
with_test_routes do
get '/sprockets.js'

4 comments on commit d017167

@ahlen

Very nice, I was waiting on this.

@wildchild

Would be cool to have the following syntax:

resources :posts, :only => :index # Just symbol instead of array.

@jpzwarte

wildchild: this is already possible with 2.3.5 so i'd be surprised if it wouldn't be in 3.0.

@dallas

jpzwarte: according to the code, it's just setting only as options[:only] as-is and then calls map on it—won't work for a symbol all by its lonesome.

Please sign in to comment.