Skip to content

Commit

Permalink
Add constraints to resources in new routing DSL
Browse files Browse the repository at this point in the history
Signed-off-by: Rizwan Reza <rizwanreza@gmail.com>
  • Loading branch information
pixeltrix authored and rizwanreza committed Mar 28, 2010
1 parent 5c05829 commit e1a70fa
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 14 deletions.
61 changes: 47 additions & 14 deletions actionpack/lib/action_dispatch/routing/mapper.rb
Expand Up @@ -259,6 +259,7 @@ def initialize(*args)

def scope(*args)
options = args.extract_options!
options = options.dup

case args.first
when String
Expand Down Expand Up @@ -440,6 +441,32 @@ def name_for_action(action)
def id_segment
":#{singular}_id"
end

def constraints
options[:constraints] || {}
end

def id_constraint?
options[:id] && options[:id].is_a?(Regexp) || constraints[:id] && constraints[:id].is_a?(Regexp)
end

def id_constraint
options[:id] || constraints[:id]
end

def collection_options
(options || {}).dup.tap do |options|
options.delete(:id)
options[:constraints] = options[:constraints].dup if options[:constraints]
options[:constraints].delete(:id) if options[:constraints].is_a?(Hash)
end
end

def nested_options
options = { :name_prefix => member_name }
options["#{singular}_id".to_sym] = id_constraint if id_constraint?
options
end
end

class SingletonResource < Resource #:nodoc:
Expand Down Expand Up @@ -484,12 +511,14 @@ def resource(*resources, &block)
yield if block_given?
end

get :show if resource.actions.include?(:show)
post :create if resource.actions.include?(:create)
put :update if resource.actions.include?(:update)
delete :destroy if resource.actions.include?(:destroy)
get :new, :as => resource.name if resource.actions.include?(:new)
get :edit, :as => resource.name if resource.actions.include?(:edit)
scope(resource.options) do
get :show if resource.actions.include?(:show)
post :create if resource.actions.include?(:create)
put :update if resource.actions.include?(:update)
delete :destroy if resource.actions.include?(:destroy)
get :new, :as => resource.name if resource.actions.include?(:new)
get :edit, :as => resource.name if resource.actions.include?(:edit)
end
end
end

Expand All @@ -510,17 +539,21 @@ def resources(*resources, &block)
yield if block_given?

with_scope_level(:collection) do
get :index if resource.actions.include?(:index)
post :create if resource.actions.include?(:create)
get :new, :as => resource.singular if resource.actions.include?(:new)
scope(resource.collection_options) do
get :index if resource.actions.include?(:index)
post :create if resource.actions.include?(:create)
get :new, :as => resource.singular if resource.actions.include?(:new)
end
end

with_scope_level(:member) do
scope(':id') do
get :show if resource.actions.include?(:show)
put :update if resource.actions.include?(:update)
delete :destroy if resource.actions.include?(:destroy)
get :edit, :as => resource.singular if resource.actions.include?(:edit)
scope(resource.options) do
get :show if resource.actions.include?(:show)
put :update if resource.actions.include?(:update)
delete :destroy if resource.actions.include?(:destroy)
get :edit, :as => resource.singular if resource.actions.include?(:edit)
end
end
end
end
Expand Down Expand Up @@ -559,7 +592,7 @@ def nested
end

with_scope_level(:nested) do
scope(parent_resource.id_segment, :name_prefix => parent_resource.member_name) do
scope(parent_resource.id_segment, parent_resource.nested_options) do
yield
end
end
Expand Down
26 changes: 26 additions & 0 deletions actionpack/test/dispatch/routing_test.rb
Expand Up @@ -171,6 +171,12 @@ def self.matches?(request)
resources :descriptions
root :to => 'projects#index'
end

resources :products, :constraints => { :id => /\d{4}/ } do
resources :images
end

resource :dashboard, :constraints => { :ip => /192\.168\.1\.\d{1,3}/ }
end
end

Expand Down Expand Up @@ -794,6 +800,26 @@ def test_default_params
end
end

def test_resource_constraints
with_test_routes do
assert_raise(ActionController::RoutingError) { get '/products/1' }
get '/products'
assert_equal 'products#index', @response.body
get '/products/0001'
assert_equal 'products#show', @response.body

assert_raise(ActionController::RoutingError) { get '/products/1/images' }
get '/products/0001/images'
assert_equal 'images#index', @response.body
get '/products/0001/images/1'
assert_equal 'images#show', @response.body

assert_raise(ActionController::RoutingError) { get '/dashboard', {}, {'REMOTE_ADDR' => '10.0.0.100'} }
get '/dashboard', {}, {'REMOTE_ADDR' => '192.168.1.100'}
assert_equal 'dashboards#show', @response.body
end
end

private
def with_test_routes
yield
Expand Down

3 comments on commit e1a70fa

@fxn
Copy link
Member

@fxn fxn commented on e1a70fa Mar 28, 2010

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit has no rdoc?

@pixeltrix
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't add any documentation since constraints are already documented, however looking at the documentation in ActionDispatch::Routing I can see there's no documentation at all on resources so we certainly do with some documentation on resource routing in the new DSL. Currently there's no rdoc attached to any of the new routing methods so should the resource docs go with the rest of the docs in ActionDispatch::Routing or is the intention to add docs to each of the methods? Also I'm guessing that any doc commits should go to docrails?

@fxn
Copy link
Member

@fxn fxn commented on e1a70fa Mar 28, 2010

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah some more docs would be good indeed. Would you like to contribute them? If so please just write them and ping me, I'll apply.

Regarding docrails, the idea is that a patch should always have proper test and rdoc coverage to be accepted. The docrails branch is only a shortcut to fix docs bypassing LH (and it does guides as well). But rdoc is still something contributed together with code and tests.

Please sign in to comment.