<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -70,6 +70,8 @@ module Merb
       def resources(name, *args, &amp;block)
         name       = name.to_s
         options    = extract_options_from_args!(args) || {}
+        match_opts = options.except(*resource_options)
+        options    = options.only(*resource_options)
         singular   = options[:singular] ? options[:singular].to_s : Extlib::Inflection.singularize(name)
         klass_name = args.first ? args.first.to_s : Extlib::Inflection.classify(singular)
         klass      = Object.full_const_get(klass_name) rescue nil
@@ -118,45 +120,48 @@ module Merb
           end
 
           # =&gt; show
-          resource.match(&quot;/#{root_keys}(.:format)&quot;, :method =&gt; :get).to(:action =&gt; &quot;show&quot;).
+          resource.match(&quot;/#{root_keys}(.:format)&quot;, match_opts.merge(:method =&gt; :get)).to(:action =&gt; &quot;show&quot;).
             name(singular).register_resource(klass_name)
 
           # =&gt; user defined member routes
           member.each_pair do |action, method|
             action = action.to_s
-            resource.match(&quot;/#{root_keys}/#{action}(.:format)&quot;, :method =&gt; method).
+            resource.match(&quot;/#{root_keys}/#{action}(.:format)&quot;, match_opts.merge(:method =&gt; method)).
               to(:action =&gt; &quot;#{action}&quot;).name(action, singular).register_resource(klass_name, action)
           end
 
           # =&gt; update
-          resource.match(&quot;/#{root_keys}(.:format)&quot;, :method =&gt; :put).
+          resource.match(&quot;/#{root_keys}(.:format)&quot;, match_opts.merge(:method =&gt; :put)).
             to(:action =&gt; &quot;update&quot;)
             
           # =&gt; destroy
-          resource.match(&quot;/#{root_keys}(.:format)&quot;, :method =&gt; :delete).
+          resource.match(&quot;/#{root_keys}(.:format)&quot;, match_opts.merge(:method =&gt; :delete)).
             to(:action =&gt; &quot;destroy&quot;)
 
           if block_given?
             nested_keys = keys.map do |k|
               k.to_s == &quot;id&quot; ? &quot;:#{singular}_id&quot; : &quot;:#{k}&quot;
             end.join(&quot;/&quot;)
+
+            nested_match_opts = match_opts.except(:id)
+            nested_match_opts[&quot;#{singular}_id&quot;.to_sym] = match_opts[:id] if match_opts[:id]
             
             # Procs for building the extra collection/member resource routes
             placeholder = Router.resource_routes[ [@options[:resource_prefix], klass_name].flatten.compact ]
             builders    = {}
             
             builders[:collection] = lambda do |action, to, method|
-              resource.before(placeholder).match(&quot;/#{action}(.:format)&quot;, :method =&gt; method).
+              resource.before(placeholder).match(&quot;/#{action}(.:format)&quot;, match_opts.merge(:method =&gt; method)).
                 to(:action =&gt; to).name(action, name).register_resource(name, action)
             end
             
             builders[:member] = lambda do |action, to, method|
-              resource.match(&quot;/#{root_keys}/#{action}(.:format)&quot;, :method =&gt; method).
+              resource.match(&quot;/#{root_keys}/#{action}(.:format)&quot;, match_opts.merge(:method =&gt; method)).
                 to(:action =&gt; to).name(action, singular).register_resource(klass_name, action)
             end
             
             resource.options(:name_prefix =&gt; singular, :resource_prefix =&gt; klass_name).
-              match(&quot;/#{nested_keys}&quot;).resource_block(builders, &amp;block)
+              match(&quot;/#{nested_keys}&quot;, nested_match_opts).resource_block(builders, &amp;block)
           end
         end # namespace
       end # resources
@@ -226,6 +231,7 @@ module Merb
 
         self.namespace(name, options).to(params) do |resource|
           # =&gt; show
+          
           resource.match(&quot;(.:format)&quot;, :method =&gt; :get).to(:action =&gt; &quot;show&quot;).
             name(name).register_resource(name)
             
@@ -270,6 +276,11 @@ module Merb
         behavior = ResourceBehavior.new(builders, @proxy, @conditions, @params, @defaults, @identifiers, @options, @blocks)
         with_behavior_context(behavior, &amp;block)
       end
+      
+      def resource_options
+        [:singular, :keys, :key, :controller, :member, :collection, :identify,
+          :name_prefix, :resource_prefix, :controller_prefix, :namespace, :path]
+      end
 
     end # Resources
     </diff>
      <filename>lib/merb-core/dispatch/router/resources.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,93 +1,5 @@
 require File.join(File.dirname(__FILE__), &quot;..&quot;, &quot;spec_helper&quot;)
 
-def it_should_be_a_resource_collection_route(name, prefix, params = {})
-  it &quot;should provide #{name} with an 'index' route&quot; do
-    route_for(&quot;#{prefix}/#{name}&quot;).should have_route(params.merge(:action =&gt; &quot;index&quot;, :controller =&gt; &quot;#{name}&quot;))
-  end
-  
-  it &quot;should provide #{name} with an 'index' route when explicitly specified&quot; do
-    route_for(&quot;#{prefix}/#{name}/index&quot;).should have_route(params.merge(:action =&gt; &quot;index&quot;, :controller =&gt; &quot;#{name}&quot;))
-  end
-  
-  it &quot;should provide #{name} with a 'new' route&quot; do
-    route_for(&quot;#{prefix}/#{name}/new&quot;).should have_route(params.merge(:action =&gt; &quot;new&quot;, :controller =&gt; &quot;#{name}&quot;))
-  end
-  
-  it &quot;should provide #{name} with a 'create' route&quot; do
-    route_for(&quot;#{prefix}/#{name}&quot;, :method =&gt; :post).should have_route(params.merge(:action =&gt; &quot;create&quot;, :controller =&gt; &quot;#{name}&quot;))
-  end
-  
-  it &quot;should provide #{name} with a 'show' route&quot; do
-    route_for(&quot;#{prefix}/#{name}/45&quot;).should have_route(params.merge(:action =&gt; &quot;show&quot;, :controller =&gt; &quot;#{name}&quot;, :id =&gt; &quot;45&quot;))
-  end
-  
-  it &quot;should provide #{name} with an 'edit' route&quot; do
-    route_for(&quot;#{prefix}/#{name}/45/edit&quot;).should have_route(params.merge(:action =&gt; &quot;edit&quot;, :controller =&gt; &quot;#{name}&quot;, :id =&gt; &quot;45&quot;))
-  end
-  
-  it &quot;should provide #{name} with an 'update' route&quot; do
-    route_for(&quot;#{prefix}/#{name}/45&quot;, :method =&gt; :put).should have_route(params.merge(:action =&gt; &quot;update&quot;, :controller =&gt; &quot;#{name}&quot;, :id =&gt; &quot;45&quot;))
-  end
-  
-  it &quot;should provide #{name} with a 'delete' route&quot; do
-    route_for(&quot;#{prefix}/#{name}/45/delete&quot;).should have_route(params.merge(:action =&gt; &quot;delete&quot;, :controller =&gt; &quot;#{name}&quot;, :id =&gt; &quot;45&quot;))
-  end
-  
-  it &quot;should provide #{name} with a 'destroy' route&quot; do
-    route_for(&quot;#{prefix}/#{name}/45&quot;, :method =&gt; :delete).should have_route(params.merge(:action =&gt; &quot;destroy&quot;, :controller =&gt; &quot;#{name}&quot;, :id =&gt; &quot;45&quot;))
-  end
-  
-  # --- I decided that all the routes here will have the following ---
-  
-  it &quot;should provide #{name} with a 'one' collection route&quot; do
-    route_for(&quot;#{prefix}/#{name}/one&quot;).should have_route(params.merge(:action =&gt; &quot;one&quot;, :controller =&gt; &quot;#{name}&quot;))
-  end
-  
-  it &quot;should provide #{name} with a 'two' member route&quot; do
-    route_for(&quot;#{prefix}/#{name}/45/two&quot;).should have_route(params.merge(:action =&gt; &quot;two&quot;, :controller =&gt; &quot;#{name}&quot;, :id =&gt; &quot;45&quot;))
-  end
-  
-  it &quot;should provide #{name} with a 'three' collection route that maps the 'awesome' method&quot; do
-    route_for(&quot;#{prefix}/#{name}/three&quot;).should have_route(params.merge(:action =&gt; &quot;awesome&quot;, :controller =&gt; &quot;#{name}&quot;))
-  end
-  
-  it &quot;should provide #{name} with a 'four' member route that maps to the 'awesome' method&quot; do
-    route_for(&quot;#{prefix}/#{name}/45/four&quot;).should have_route(params.merge(:action =&gt; &quot;awesome&quot;, :controller =&gt; &quot;#{name}&quot;, :id =&gt; &quot;45&quot;))
-  end
-end
-
-def it_should_be_a_resource_object_route(name, prefix, params = {})
-  controller = &quot;#{name}s&quot;
-  
-  it &quot;should provide #{name} with a 'show' route&quot; do
-    route_for(&quot;#{prefix}/#{name}&quot;).should have_route(params.merge(:action =&gt; &quot;show&quot;, :controller =&gt; controller))
-  end
-  
-  it &quot;should provide #{name} with an 'edit' route&quot; do
-    route_for(&quot;#{prefix}/#{name}/edit&quot;).should have_route(params.merge(:action =&gt; &quot;edit&quot;, :controller =&gt; controller))
-  end
-  
-  it &quot;should provide #{name} with an 'update' route&quot; do
-    route_for(&quot;#{prefix}/#{name}&quot;, :method =&gt; :put).should have_route(params.merge(:action =&gt; &quot;update&quot;, :controller =&gt; controller))
-  end
-  
-  it &quot;should provide #{name} with a 'delete' route&quot; do
-    route_for(&quot;#{prefix}/#{name}/delete&quot;).should have_route(params.merge(:action =&gt; &quot;delete&quot;, :controller =&gt; controller))
-  end
-  
-  it &quot;should provide #{name} with a 'destroy' route&quot; do
-    route_for(&quot;#{prefix}/#{name}&quot;, :method =&gt; :delete).should have_route(params.merge(:action =&gt; &quot;destroy&quot;, :controller =&gt; controller))
-  end
-  
-  it &quot;should provide #{name} with a 'one' member route&quot; do
-    route_for(&quot;#{prefix}/#{name}/one&quot;).should have_route(params.merge(:action =&gt; &quot;one&quot;, :controller =&gt; controller))
-  end
-  
-  it &quot;should provide #{name} with a 'two' member route that maps to the 'awesome' method&quot; do
-    route_for(&quot;#{prefix}/#{name}/two&quot;).should have_route(params.merge(:action =&gt; &quot;awesome&quot;, :controller =&gt; controller))
-  end
-end
-
 describe &quot;Recognizing requests for nested resources routes&quot; do
   
   before(:each) do
@@ -140,4 +52,54 @@ describe &quot;Recognizing requests for nested resources routes&quot; do
   it &quot;should match a get to /domains/merbivore_com/emails to the emails controller and index action with domain =&gt; 'merbivore_com&quot; do
     route_for('/domains/merbivore_com/emails', :method =&gt; :get).should have_route(:controller =&gt; 'emails', :action =&gt; 'index', :username =&gt; nil, :domain =&gt; 'merbivore_com')
   end
+  
+end
+
+describe &quot;Recognizing requests for nested resources routes with custom matchers&quot; do
+  
+  it &quot;should convert the :id condition to :user_id&quot; do
+    Merb::Router.prepare do
+      resources :users, :id =&gt; /[a-z]+/ do
+        resources :comments
+      end
+    end
+    
+    route_for(&quot;/users/abc/comments/1&quot;).should have_route(:user_id =&gt; &quot;abc&quot;)
+    lambda { route_for('/users/123/comments/1') }.should raise_not_found
+  end
+  
+  it &quot;should leave single keys not named :id alone&quot; do
+    Merb::Router.prepare do
+      resources :users, :key =&gt; :name, :name =&gt; /[a-z]+/ do
+        resources :comments
+      end
+    end
+    
+    route_for(&quot;/users/abc/comments/1&quot;).should have_route(:name =&gt; &quot;abc&quot;)
+    lambda { route_for('/users/123/comments/1') }.should raise_not_found
+  end
+  
+  it &quot;should work with multi-key resources that have an :id as part of the identifier&quot; do
+    Merb::Router.prepare do
+      resources :users, :key =&gt; [:name, :id], :id =&gt; /[a-z]+/ do
+        resources :comments
+      end
+    end
+    
+    route_for(&quot;/users/abc/efg/comments/1&quot;).should have_route(:name =&gt; &quot;abc&quot;, :user_id =&gt; &quot;efg&quot;)
+    lambda { route_for('/users/abc/123/comments/1') }.should raise_not_found
+  end
+  
+  it &quot;should work with mult-key resources&quot; do
+    Merb::Router.prepare do
+      resources :users, :key =&gt; [:first, :last], :first =&gt; /[a-z]+/, :last =&gt; /[a-z]+\/[a-z]+/ do
+        resources :comments
+      end
+    end
+    
+    route_for(&quot;/users/abc/efg/hij/comments/1&quot;).should have_route(:first =&gt; &quot;abc&quot;, :last =&gt; &quot;efg/hij&quot;)
+    lambda { route_for('/users/abc/123/comments/1') }.should raise_not_found
+    lambda { route_for('/users/abc/efg/comments/1') }.should raise_not_found
+  end
+  
 end
\ No newline at end of file</diff>
      <filename>spec/public/router/recognition/nested_resources_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,63 +1,28 @@
 require File.join(File.dirname(__FILE__), &quot;..&quot;, &quot;spec_helper&quot;)
 
 describe &quot;When recognizing requests,&quot; do
-
-  describe &quot;a basic resource collection route&quot; do
   
+  describe &quot;a basic resource collection route&quot; do
+    
     before :each do
       Merb::Router.prepare do
         resources :blogposts
       end
     end
-  
-    it &quot;should have an index action with an optional :format&quot; do
-      route_for('/blogposts').should           have_route(:controller =&gt; 'blogposts', :action =&gt; 'index', :id =&gt; nil, :format =&gt; nil)
-      route_for('/blogposts/index').should     have_route(:controller =&gt; 'blogposts', :action =&gt; 'index', :id =&gt; nil, :format =&gt; nil)
-      route_for('/blogposts.js').should        have_route(:controller =&gt; 'blogposts', :action =&gt; 'index', :id =&gt; nil, :format =&gt; &quot;js&quot;)
-      route_for('/blogposts/index.xml').should have_route(:controller =&gt; 'blogposts', :action =&gt; 'index', :id =&gt; nil, :format =&gt; &quot;xml&quot;)
-    end
-  
-    it &quot;should have a create action with an optional :format&quot; do
-      route_for('/blogposts',    :method =&gt; :post).should have_route(:controller =&gt; 'blogposts', :action =&gt; 'create', :id =&gt; nil, :format =&gt; nil)
-      route_for('/blogposts.js', :method =&gt; :post).should have_route(:controller =&gt; 'blogposts', :action =&gt; 'create', :id =&gt; nil, :format =&gt; &quot;js&quot;)
-    end
-
+    
+    it_should_be_a_resource_collection_route :blogposts, { :extra =&gt; false }, { }
+    
     it &quot;should not match put or delete on the collection&quot; do
       [:put, :delete].each do |method|
         lambda { route_for('/blogposts',    :method =&gt; method) }.should raise_not_found
         lambda { route_for('/blogposts.js', :method =&gt; method) }.should raise_not_found
       end
     end
-  
-    it &quot;should have a new action with an optional :format&quot; do
-      route_for('/blogposts/new',    :method =&gt; :get).should have_route(:controller =&gt; 'blogposts', :action =&gt; 'new', :id =&gt; nil, :format =&gt; nil)
-      route_for('/blogposts/new.js', :method =&gt; :get).should have_route(:controller =&gt; 'blogposts', :action =&gt; 'new', :id =&gt; nil, :format =&gt; &quot;js&quot;)
-    end
     
     it &quot;should not match post on the new action&quot; do
       lambda { route_for('/blogposts/new',     :method =&gt; :post) }.should raise_not_found
       lambda { route_for('/blogposts/new.xml', :method =&gt; :post) }.should raise_not_found
     end
-  
-    it &quot;should have a show action with an optional :format&quot; do
-      route_for('/blogposts/1',     :method =&gt; :get).should have_route(:controller =&gt; 'blogposts', :action =&gt; 'show', :id =&gt; &quot;1&quot;, :format =&gt; nil)
-      route_for('/blogposts/1.css', :method =&gt; :get).should have_route(:controller =&gt; 'blogposts', :action =&gt; 'show', :id =&gt; &quot;1&quot;, :format =&gt; &quot;css&quot;)
-    end
-  
-    it &quot;should have an update action with an optional :format&quot; do
-      route_for('/blogposts/1',     :method =&gt; :put).should have_route(:controller =&gt; 'blogposts', :action =&gt; 'update', :id =&gt; &quot;1&quot;, :format =&gt; nil)
-      route_for('/blogposts/1.csv', :method =&gt; :put).should have_route(:controller =&gt; 'blogposts', :action =&gt; 'update', :id =&gt; &quot;1&quot;, :format =&gt; &quot;csv&quot;)
-    end
-  
-    it &quot;should have a destroy action with an optional :format&quot; do
-      route_for('/blogposts/1',     :method =&gt; :delete).should have_route(:controller =&gt; 'blogposts', :action =&gt; 'destroy', :id =&gt; &quot;1&quot;, :format =&gt; nil)
-      route_for('/blogposts/1.xxl', :method =&gt; :delete).should have_route(:controller =&gt; 'blogposts', :action =&gt; 'destroy', :id =&gt; &quot;1&quot;, :format =&gt; 'xxl')
-    end
-
-    it &quot;should have an edit action with an optional :format&quot; do
-      route_for('/blogposts/1/edit',     :method =&gt; :get).should have_route(:controller =&gt; 'blogposts', :action =&gt; 'edit', :id =&gt; &quot;1&quot;, :format =&gt; nil)
-      route_for('/blogposts/1/edit.rss', :method =&gt; :get).should have_route(:controller =&gt; 'blogposts', :action =&gt; 'edit', :id =&gt; &quot;1&quot;, :format =&gt; &quot;rss&quot;)
-    end
     
     it &quot;should not match post, put, or delete on the edit action&quot; do
       [:put, :post, :delete].each do |method|
@@ -65,11 +30,6 @@ describe &quot;When recognizing requests,&quot; do
         lambda { route_for('/blogposts/edit.hi', :method =&gt; :post) }.should raise_not_found
       end
     end
-  
-    it &quot;should should have a delete action with an optional :format&quot; do
-      route_for('/blogposts/1/delete',     :method =&gt; :get).should have_route(:controller =&gt; 'blogposts', :action =&gt; 'delete', :id =&gt; &quot;1&quot;, :format =&gt; nil)
-      route_for('/blogposts/1/delete.mp3', :method =&gt; :get).should have_route(:controller =&gt; 'blogposts', :action =&gt; 'delete', :id =&gt; &quot;1&quot;, :format =&gt; &quot;mp3&quot;)
-    end
     
     it &quot;should not match post, put, or delete on the delete action&quot; do
       [:put, :post, :delete].each do |method|
@@ -77,6 +37,27 @@ describe &quot;When recognizing requests,&quot; do
         lambda { route_for('/blogposts/delete.flv', :method =&gt; :post) }.should raise_not_found
       end
     end
+    
+  end
+  
+  describe &quot;a basic resource collection with custom &quot; do
+    
+    before :each do
+      Merb::Router.prepare do
+        resources :blogposts, :id =&gt; %r([a-z]+/\d+)
+      end
+    end
+    
+    it_should_be_a_resource_collection_route :blogposts, { :extra =&gt; false, :id =&gt; &quot;abc/123&quot; }, { }
+    
+    it &quot;should not match a numeric ID for the routes&quot; do
+      lambda { route_for(&quot;/blogposts/10&quot;) }.should                     raise_not_found
+      lambda { route_for(&quot;/blogposts/10&quot;, :method =&gt; :put) }.should    raise_not_found
+      lambda { route_for(&quot;/blogposts/10&quot;, :method =&gt; :delete) }.should raise_not_found
+      lambda { route_for(&quot;/blogposts/10/edit&quot;) }.should                raise_not_found
+      lambda { route_for(&quot;/blogposts/10/delete&quot;) }.should              raise_not_found
+    end
+    
   end
   
   describe &quot;a customized resource collection route&quot; do
@@ -267,6 +248,28 @@ describe &quot;When recognizing requests,&quot; do
     it &quot;should match a get to /emails/bidule/merbivore_com/delete to the emails controller and the delete action with username =&gt; 'bidule', domain =&gt; 'merbivore_com'&quot; do
       route_for('/emails/bidule/merbivore_com/delete', :method =&gt; :get).should have_route(:controller =&gt; 'emails', :action =&gt; 'delete', :username =&gt; &quot;bidule&quot;, :domain =&gt; &quot;merbivore_com&quot;)
     end
+    
+    it &quot;should be able to set matches on each key&quot; do
+      Merb::Router.prepare do
+        resources :emails, :keys =&gt; [&quot;username&quot;, &quot;domain&quot;], :username =&gt; /[a-z]+/, :domain =&gt; /[a-z]+\.com/
+      end
+      
+      route_for(&quot;/emails/abc/abc.com&quot;).should have_route(:username =&gt; &quot;abc&quot;, :domain =&gt; &quot;abc.com&quot;)
+      lambda { route_for(&quot;/emails/123/456&quot;)     }.should raise_not_found
+      lambda { route_for(&quot;/emails/abc/123&quot;)     }.should raise_not_found
+      lambda { route_for(&quot;/emails/123/abc.com&quot;) }.should raise_not_found
+    end
+    
+    it &quot;should be able to set matches on a single key&quot; do
+      Merb::Router.prepare do
+        resources :emails, :keys =&gt; [&quot;username&quot;, &quot;domain&quot;], :username =&gt; /[a-z]+/
+      end
+      
+      route_for(&quot;/emails/abc/123&quot;).should have_route(:username =&gt; &quot;abc&quot;, :domain =&gt; &quot;123&quot;)
+      route_for(&quot;/emails/abc/abc&quot;).should have_route(:username =&gt; &quot;abc&quot;, :domain =&gt; &quot;abc&quot;)
+      lambda { route_for(&quot;/emails/123/456&quot;) }.should raise_not_found
+      lambda { route_for(&quot;/emails/123/abc&quot;) }.should raise_not_found
+    end
  
   end
   </diff>
      <filename>spec/public/router/recognition/resources_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -157,6 +157,123 @@ module Spec
   end
 end
 
+def it_should_be_a_resource_collection_route(name, *args)
+  params = extract_options_from_args!(args) || {}
+  prefix = args.first.is_a?(String) ? args.shift : &quot;&quot;
+  opts   = args.first.is_a?(Hash)   ? args.shift : {}
+  
+  id = opts[:id] || &quot;45&quot;
+  
+  it &quot;should provide #{name} with an 'index' route&quot; do
+    route_for(&quot;#{prefix}/#{name}&quot;).should          have_route({:action =&gt; &quot;index&quot;, :controller =&gt; &quot;#{name}&quot;,  :id =&gt; nil, :format =&gt; nil }.merge(params))
+    route_for(&quot;#{prefix}/#{name}/index&quot;).should    have_route({:action =&gt; &quot;index&quot;, :controller =&gt; &quot;#{name}&quot;,  :id =&gt; nil, :format =&gt; nil }.merge(params))
+    route_for(&quot;#{prefix}/#{name}.js&quot;).should       have_route({:action =&gt; &quot;index&quot;, :controller =&gt; &quot;#{name}&quot;,  :id =&gt; nil, :format =&gt; &quot;js&quot;}.merge(params))
+    route_for(&quot;#{prefix}/#{name}/index.js&quot;).should have_route({:action =&gt; &quot;index&quot;, :controller =&gt; &quot;#{name}&quot;,  :id =&gt; nil, :format =&gt; &quot;js&quot;}.merge(params))
+  end
+
+  it &quot;should provide #{name} with a 'new' route&quot; do
+    route_for(&quot;#{prefix}/#{name}/new&quot;).should    have_route({:action =&gt; &quot;new&quot;, :controller =&gt; &quot;#{name}&quot;, :id =&gt; nil, :format =&gt; nil }.merge(params))
+    route_for(&quot;#{prefix}/#{name}/new.js&quot;).should have_route({:action =&gt; &quot;new&quot;, :controller =&gt; &quot;#{name}&quot;, :id =&gt; nil, :format =&gt; &quot;js&quot;}.merge(params))
+  end
+
+  it &quot;should provide #{name} with a 'create' route&quot; do
+    route_for(&quot;#{prefix}/#{name}&quot;,    :method =&gt; :post).should have_route({:action =&gt; &quot;create&quot;, :controller =&gt; &quot;#{name}&quot;, :id =&gt; nil, :format =&gt; nil }.merge(params))
+    route_for(&quot;#{prefix}/#{name}.js&quot;, :method =&gt; :post).should have_route({:action =&gt; &quot;create&quot;, :controller =&gt; &quot;#{name}&quot;, :id =&gt; nil, :format =&gt; &quot;js&quot;}.merge(params))
+  end
+
+  it &quot;should provide #{name} with a 'show' route&quot; do
+    route_for(&quot;#{prefix}/#{name}/#{id}&quot;).should    have_route({:action =&gt; &quot;show&quot;, :controller =&gt; &quot;#{name}&quot;, :id =&gt; id, :format =&gt; nil }.merge(params))
+    route_for(&quot;#{prefix}/#{name}/#{id}.js&quot;).should have_route({:action =&gt; &quot;show&quot;, :controller =&gt; &quot;#{name}&quot;, :id =&gt; id, :format =&gt; &quot;js&quot;}.merge(params))
+  end
+
+  it &quot;should provide #{name} with an 'edit' route&quot; do
+    route_for(&quot;#{prefix}/#{name}/#{id}/edit&quot;).should    have_route({:action =&gt; &quot;edit&quot;, :controller =&gt; &quot;#{name}&quot;, :id =&gt; id, :format =&gt; nil }.merge(params))
+    route_for(&quot;#{prefix}/#{name}/#{id}/edit.js&quot;).should have_route({:action =&gt; &quot;edit&quot;, :controller =&gt; &quot;#{name}&quot;, :id =&gt; id, :format =&gt; &quot;js&quot;}.merge(params))
+  end
+
+  it &quot;should provide #{name} with an 'update' route&quot; do
+    route_for(&quot;#{prefix}/#{name}/#{id}&quot;,    :method =&gt; :put).should have_route({:action =&gt; &quot;update&quot;, :controller =&gt; &quot;#{name}&quot;, :id =&gt; id, :format =&gt; nil }.merge(params))
+    route_for(&quot;#{prefix}/#{name}/#{id}.js&quot;, :method =&gt; :put).should have_route({:action =&gt; &quot;update&quot;, :controller =&gt; &quot;#{name}&quot;, :id =&gt; id, :format =&gt; &quot;js&quot;}.merge(params))
+  end
+
+  it &quot;should provide #{name} with a 'delete' route&quot; do
+    route_for(&quot;#{prefix}/#{name}/#{id}/delete&quot;).should    have_route({:action =&gt; &quot;delete&quot;, :controller =&gt; &quot;#{name}&quot;, :id =&gt; id, :format =&gt; nil }.merge(params))
+    route_for(&quot;#{prefix}/#{name}/#{id}/delete.js&quot;).should have_route({:action =&gt; &quot;delete&quot;, :controller =&gt; &quot;#{name}&quot;, :id =&gt; id, :format =&gt; &quot;js&quot;}.merge(params))
+  end
+
+  it &quot;should provide #{name} with a 'destroy' route&quot; do
+    route_for(&quot;#{prefix}/#{name}/#{id}&quot;,    :method =&gt; :delete).should have_route({:action =&gt; &quot;destroy&quot;, :controller =&gt; &quot;#{name}&quot;, :id =&gt; id, :format =&gt; nil }.merge(params))
+    route_for(&quot;#{prefix}/#{name}/#{id}.js&quot;, :method =&gt; :delete).should have_route({:action =&gt; &quot;destroy&quot;, :controller =&gt; &quot;#{name}&quot;, :id =&gt; id, :format =&gt; &quot;js&quot;}.merge(params))
+  end
+
+  # --- I decided that all the routes here will have the following ---
+  
+  if !opts.has_key?(:extra) || opts[:extra]
+    
+    it &quot;should provide #{name} with a 'one' collection route&quot; do
+      route_for(&quot;#{prefix}/#{name}/one&quot;).should    have_route({:action =&gt; &quot;one&quot;, :controller =&gt; &quot;#{name}&quot;, :format =&gt; nil }.merge(params))
+      route_for(&quot;#{prefix}/#{name}/one.js&quot;).should have_route({:action =&gt; &quot;one&quot;, :controller =&gt; &quot;#{name}&quot;, :format =&gt; &quot;js&quot;}.merge(params))
+    end
+
+    it &quot;should provide #{name} with a 'two' member route&quot; do
+      route_for(&quot;#{prefix}/#{name}/#{id}/two&quot;).should    have_route({:action =&gt; &quot;two&quot;, :controller =&gt; &quot;#{name}&quot;, :id =&gt; id, :format =&gt; nil }.merge(params))
+      route_for(&quot;#{prefix}/#{name}/#{id}/two.js&quot;).should have_route({:action =&gt; &quot;two&quot;, :controller =&gt; &quot;#{name}&quot;, :id =&gt; id, :format =&gt; &quot;js&quot;}.merge(params))
+    end
+
+    it &quot;should provide #{name} with a 'three' collection route that maps the 'awesome' method&quot; do
+      route_for(&quot;#{prefix}/#{name}/three&quot;).should    have_route({:action =&gt; &quot;awesome&quot;, :controller =&gt; &quot;#{name}&quot;, :format =&gt; nil }.merge(params))
+      route_for(&quot;#{prefix}/#{name}/three.js&quot;).should have_route({:action =&gt; &quot;awesome&quot;, :controller =&gt; &quot;#{name}&quot;, :format =&gt; &quot;js&quot;}.merge(params))
+    end
+
+    it &quot;should provide #{name} with a 'four' member route that maps to the 'awesome' method&quot; do
+      route_for(&quot;#{prefix}/#{name}/#{id}/four&quot;).should    have_route({:action =&gt; &quot;awesome&quot;, :controller =&gt; &quot;#{name}&quot;, :id =&gt; id, :format =&gt; nil }.merge(params))
+      route_for(&quot;#{prefix}/#{name}/#{id}/four.js&quot;).should have_route({:action =&gt; &quot;awesome&quot;, :controller =&gt; &quot;#{name}&quot;, :id =&gt; id, :format =&gt; &quot;js&quot;}.merge(params))
+    end
+  end
+end
+
+def it_should_be_a_resource_object_route(name, *args)
+  controller = &quot;#{name}s&quot;
+  params     = extract_options_from_args!(args) || {}
+  prefix     = args.first.is_a?(String) ? args.shift : &quot;&quot;
+  opts       = args.first.is_a?(Hash)   ? args.shift : {}
+
+  it &quot;should provide #{name} with a 'show' route&quot; do
+    route_for(&quot;#{prefix}/#{name}&quot;).should    have_route({:action =&gt; &quot;show&quot;, :controller =&gt; controller, :format =&gt; nil }.merge(params))
+    route_for(&quot;#{prefix}/#{name}.js&quot;).should have_route({:action =&gt; &quot;show&quot;, :controller =&gt; controller, :format =&gt; &quot;js&quot;}.merge(params))
+  end
+
+  it &quot;should provide #{name} with an 'edit' route&quot; do
+    route_for(&quot;#{prefix}/#{name}/edit&quot;).should    have_route({:action =&gt; &quot;edit&quot;, :controller =&gt; controller, :format =&gt; nil }.merge(params))
+    route_for(&quot;#{prefix}/#{name}/edit.js&quot;).should have_route({:action =&gt; &quot;edit&quot;, :controller =&gt; controller, :format =&gt; &quot;js&quot;}.merge(params))
+  end
+
+  it &quot;should provide #{name} with an 'update' route&quot; do
+    route_for(&quot;#{prefix}/#{name}&quot;,    :method =&gt; :put).should have_route({:action =&gt; &quot;update&quot;, :controller =&gt; controller, :format =&gt; nil }.merge(params))
+    route_for(&quot;#{prefix}/#{name}.js&quot;, :method =&gt; :put).should have_route({:action =&gt; &quot;update&quot;, :controller =&gt; controller, :format =&gt; &quot;js&quot;}.merge(params))
+  end
+
+  it &quot;should provide #{name} with a 'delete' route&quot; do
+    route_for(&quot;#{prefix}/#{name}/delete&quot;).should    have_route({:action =&gt; &quot;delete&quot;, :controller =&gt; controller, :format =&gt; nil }.merge(params))
+    route_for(&quot;#{prefix}/#{name}/delete.js&quot;).should have_route({:action =&gt; &quot;delete&quot;, :controller =&gt; controller, :format =&gt; &quot;js&quot;}.merge(params))
+  end
+
+  it &quot;should provide #{name} with a 'destroy' route&quot; do
+    route_for(&quot;#{prefix}/#{name}&quot;,    :method =&gt; :delete).should have_route({:action =&gt; &quot;destroy&quot;, :controller =&gt; controller, :format =&gt; nil}.merge(params))
+    route_for(&quot;#{prefix}/#{name}.js&quot;, :method =&gt; :delete).should have_route({:action =&gt; &quot;destroy&quot;, :controller =&gt; controller, :format =&gt; &quot;js&quot;}.merge(params))
+  end
+
+  it &quot;should provide #{name} with a 'one' member route&quot; do
+    route_for(&quot;#{prefix}/#{name}/one&quot;).should    have_route({:action =&gt; &quot;one&quot;, :controller =&gt; controller, :format =&gt; nil}.merge(params))
+    route_for(&quot;#{prefix}/#{name}/one.js&quot;).should have_route({:action =&gt; &quot;one&quot;, :controller =&gt; controller, :format =&gt; &quot;js&quot;}.merge(params))
+  end
+
+  it &quot;should provide #{name} with a 'two' member route that maps to the 'awesome' method&quot; do
+    route_for(&quot;#{prefix}/#{name}/two&quot;).should    have_route({:action =&gt; &quot;awesome&quot;, :controller =&gt; controller, :format =&gt; nil }.merge(params))
+    route_for(&quot;#{prefix}/#{name}/two.js&quot;).should have_route({:action =&gt; &quot;awesome&quot;, :controller =&gt; controller, :format =&gt; &quot;js&quot;}.merge(params))
+  end
+end
+
 Spec::Runner.configure do |config|
   config.include(Spec::Helpers)
   config.include(Spec::Matchers)</diff>
      <filename>spec/public/router/spec_helper.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>e3ec4814766fc1dfbbdbf2f1b7bff1f13b08ecc8</id>
    </parent>
  </parents>
  <author>
    <name>Carl Lerche</name>
    <email>carllerche@mac.com</email>
  </author>
  <url>http://github.com/wycats/merb-core/commit/3c1d2dcfc2fd64957ff0f9b65ca11bb8b52d11fd</url>
  <id>3c1d2dcfc2fd64957ff0f9b65ca11bb8b52d11fd</id>
  <committed-date>2008-10-12T10:50:08-07:00</committed-date>
  <authored-date>2008-10-11T17:22:14-07:00</authored-date>
  <message>Adding the ability to set conditions on resource keys

When defining resource routes, conditions for the keys
can now be set by simply passing those conditions along
as extra keys of the options hash.

For example:

Merb::Router.prepare do
  resources :users, :id =&gt; /[a-z]+/
end

This will also work with Array keys, such as.

Merb::Router.prepare do
  resources :users, :keys =&gt; [:name, :age],
    :name =&gt; /[a-z]+/, :age =&gt; /\d+/
end</message>
  <tree>2eaa101dcea098db8e0bedd94171c47aaac72515</tree>
  <committer>
    <name>Carl Lerche</name>
    <email>carllerche@mac.com</email>
  </committer>
</commit>
