<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>spec/specs/load_enclosing_resources_spec.rb</filename>
    </added>
    <added>
      <filename>spec/specs/route_enclosing_names_spec.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,3 +1,21 @@
+* - :polymorphic =&gt; true is back:
+      resources_controller_for :tags
+      nested_in :taggable, :polymorphic =&gt; true
+
+    This will load the enclosing resource (which can be a mapped resource) as
+    @taggable as well as its default name
+  
+    The following syntax is equivalent to the above two lines:
+      resources_controller_for :tags, :in =&gt; '?taggable'
+  
+    And you can specify a single wildcard '?' as well as expanding wildcards '*':
+      resources_controller_for :images, :in =&gt; '?', :load_enclosing =&gt; false
+      # this will work for routes like /users/1/images, /forums/2/images, /featured/images
+  
+  - test coverage is up
+  
+  - moved some of the 'friend' functionality out of Specification, as it smelt bad
+
 * added specs for when you want to find_by_(something other than id) (users,
   addresses, interests)
   </diff>
      <filename>CHANGELOG</filename>
    </modified>
    <modified>
      <diff>@@ -30,7 +30,7 @@ namespace :spec do
   namespace :rcov do
     desc &quot;Verify RCov threshold for #{plugin_name}&quot;
     RCov::VerifyTask.new(:verify =&gt; &quot;spec:rcov&quot;) do |t|
-      t.threshold = 94.1
+      t.threshold = 98.5
       t.index_html = File.join(File.dirname(__FILE__), 'doc/coverage/index.html')
     end
   end</diff>
      <filename>Rakefile</filename>
    </modified>
    <modified>
      <diff>@@ -7,6 +7,7 @@ AccountController#resource_service
 - .new should call :new on User
 - .find should call :current_user
 - .find should call whatever is in resource_specification @find
+- .find should raise CantFindSingleton when no custom finder (and no enclosing resource)
 
 Routing shortcuts for Admin::Forums should map
 - resources_path to /admin/forums
@@ -35,7 +36,7 @@ Routing shortcuts for Admin::Forums should map
 - edit_resource_interest_path(5) to /admin/forums/2/interests/5/edit
 - edit_resource_interest_path(9,5) to /admin/forums/9/interests/5/edit
 - respond_to?(:edit_resource_interest_path) should == true
-- resource_users_path should raise informative NoMethodError
+- resource_users_path should raise informative CantMapRoute
 - enclosing_resource_path should raise informative NoMethodError
 - any_old_missing_method should raise NoMethodError
 - respond_to?(:resource_users_path) should == false
@@ -272,6 +273,11 @@ Routing shortcuts for ForumPosts (forums/2/posts/1) should map
 - enclosing_resource_tag_path(9) to /forums/2/tags/9
 - enclosing_resource_tag_path(8,9) to /forums/8/tags/9
 
+ForumPostsController errors
+- should raise ResourceMismatch for /posts
+- should raise MissingSegment, when route does not contain the resource segment
+- should raise NoRecognizedRoute when no route is recognized
+
 resource_service in ForumPostsController
 - should build new post with @forum foreign key with new
 - should find @post with find(@post.id)
@@ -523,6 +529,7 @@ Requesting /forums/2/owner using POST
 - should build a new owner
 - should set the flash notice
 - should redirect to the new owner
+- should render new when post unsuccesful
 
 Requesting /forums/2/owner using PUT
 - should find the owner from forum.owner
@@ -743,6 +750,7 @@ ActionView with resources_controller Helper
 - should forward #resource to controller
 - should forward #resources to controller
 - should forward #enclosing_resource to controller
+- should forward #enclosing_resource_name to controller
 - should not forward unknown url helper to controller
 
 Helper#form_for_resource (when resource is new record)
@@ -754,10 +762,51 @@ Helper#form_for_resource (when resource is existing record)
 Helper#remote_form_for_resource (when resource is existing record)
 - should call remote_form_for with update form options
 
+#load_enclosing_resources for resources_controller_for :tags (when route_enclosing_names is [['users', false]])
+- should call load_wildcard once
+- should call Specification.new('user', :singleton =&gt; false)
+
+#load_enclosing_resources for resources_controller_for :tags, with :account mapping (when route_enclosing_names is [['account', true]])
+- should call load_wildcard once
+- should call load_enclosing_resource_from_specification with account specification
+- should not call Specification.new
+
+#load_enclosing_resources for resources_controller_for :tags (when route_enclosing_names is [['users', false], ['forums', false]])
+- should call load_wildcard twice
+- should call Specification.new with ('user', :singleton =&gt; false), then ('forum', :singleton =&gt; false)
+
+#load_enclosing_resources for resources_controller_for :tags, :in =&gt; ['*', :comment] (when route_enclosing_names is [['comments', false]])
+- should not call load_wildcard
+- should not call Specification.new
+
+#load_enclosing_resources for resources_controller_for :tags, :in =&gt; ['*', :comment] (when route_enclosing_names is [['users', false], ['forums', false], ['comments', false]])
+- should call load_wildcard twice
+- should call Specification.new with ('user', :singleton =&gt; false), then ('forum', :singleton =&gt; false)
+
+#load_enclosing_resources for resources_controller_for :tags, :in =&gt; ['*', :comment] (when route_enclosing_names is [['users', false], ['forums', false], ['special', true], ['comments', false]])
+- should call load_wildcard three times
+- should call Specification.new with ('user', :singleton =&gt; false), ('forum', :singleton =&gt; false), then ('special', :singleton =&gt; true)
+
+#load_enclosing_resources for resources_controller_for :tags, :in =&gt; ['*', '?commentable', :comment] (when route_enclosing_names is [['users', false], ['comments', false]])
+- should call load_wildcard once with 'commentable'
+- should call Specification.new with ('user', :singleton =&gt; false)
+
+#load_enclosing_resources for resources_controller_for :tags, :in =&gt; ['*', '?commentable', :comment] (when route_enclosing_names is [['users', false], ['forums', false], ['comments', false]])
+- should call load_wildcard once, then once with 'commentable'
+- should call Specification.new with ('user', :singleton =&gt; false), ('forum', :singleton =&gt; false)
+
+#load_enclosing_resources for resources_controller_for :tags, :in =&gt; ['*', '?commentable', :comment] (when route_enclosing_names is [['users', false], ['forums', false], ['posts', false], ['comments', false]])
+- should call load_wildcard twice, then once with 'commentable'
+- should call Specification.new with ('user', :singleton =&gt; false), ('forum', :singleton =&gt; false), then ('post', :singleton =&gt; false)
+
+#load_enclosing_resources for resources_controller_for :tags, :in =&gt; ['user', '*', '?taggable'] (when route_enclosing_names is [['users', false], ['comments', false]])
+- should call load_enclosing_resource_from_specification with user spec, then load_wildcard once with 'taggable'
+- should call Specification.new with ('comment', :singleton =&gt; false)
+
 A controller's resource_service
 - may be explicitly set with #resource_service=
 
-ResourcesController#route_resource_names (route_name:tag, :singleton:false)
+#route_enclosing_names (route_name:tag, :singleton:false) for named_route:
 - :tags should be []
 - :new_tag should be []
 - :edit_tag should be []
@@ -768,6 +817,6 @@ ResourcesController#route_resource_names (route_name:tag, :singleton:false)
 - :account_info_tags should be [[&quot;account&quot;, true], [&quot;info&quot;, true]]
 - :new_account_info_tag should be [[&quot;account&quot;, true], [&quot;info&quot;, true]]
 
-Finished in 4.40074 seconds
+Finished in 5.243358 seconds
 
-539 examples, 0 failures
+566 examples, 0 failures</diff>
      <filename>SPECDOC</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,5 @@
+* allow option to override namespace name_prefix, or add arbitrary name_prefix
+  and path_prefix
+* enclosing_resource_service for easier creating of custom enclosing resources
 * end-to-end tests
-* re-introduce :polymorphic option (it can be simulated now - but it's a common use-case for many people)
-* add '?' wildcard (which can be used to implement the :polymorphic option)
-* write some docs on how RC could be improved by having the resources passed to the controller
-* rationalise test suite - make a better app
 * stories
-* when :in specified, then don't add the load_enclosing wildcard?</diff>
      <filename>TODO</filename>
    </modified>
    <modified>
      <diff>@@ -425,6 +425,7 @@ module Ardes#:nodoc:
       before_filter :load_enclosing_resources unless find_filter(:load_enclosing_resources)
       
       write_inheritable_attribute(:specifications, [])
+      specifications &lt;&lt; '*' unless options.delete(:load_enclosing) == false
       
       if actions = options.delete(:actions)
         include actions
@@ -436,19 +437,16 @@ module Ardes#:nodoc:
       name = options[:singleton] ? name.to_s : name.to_s.singularize
       write_inheritable_attribute :route_name, options[:singleton] ? route : route.singularize
       
-      specifications &lt;&lt; '*' unless options.delete(:load_enclosing) == false
-      if nested = options.delete(:in)
-        nested_in(*nested)
-      end
+      nested_in(*options.delete(:in)) if options[:in]
       
-      write_inheritable_attribute(:resource_specification, Specification.new(name, options, &amp;block).freeze)
+      write_inheritable_attribute(:resource_specification, Specification.new(name, options, &amp;block))
     end
     
     def deprecated_resources_controller_for(options)
-      options[:class] ||= options[:class_name] &amp;&amp; options[:class_name].constantize
-      options[:source] ||= options[:collection_name]
-      options[:actions] = options[:actions_include] if options[:actions].nil?
-      options[:route] ||= options[:route_name]
+      options[:class_name]      and options[:class] ||= options[:class_name].constantize
+      options[:collection_name] and options[:source] ||= options[:collection_name] 
+      options[:actions_include] and options[:actions] = options[:actions_include] if options[:actions].nil?
+      options[:route_name]      and options[:route] ||= options[:route_name]
       [:class_name, :collection_name, :actions_include, :route_name].each do |k|
         if options.key?(k)
           ActiveSupport::Deprecation.warn(&quot;option :#{k} has been deprecated for resources_controller_for and will be removed soon&quot;)
@@ -477,16 +475,27 @@ module Ardes#:nodoc:
         options = names.last.is_a?(Hash) ? names.pop : {}
         raise ArgumentError, &quot;when giving more than one nesting, you may not specify options or a block&quot; if names.length &gt; 1 and (block_given? or options.length &gt; 0)
         deprecated_nested_in(options)
+        
+        # convert :polymorphic option to '?'
+        if options.delete(:polymorphic)
+          raise ArgumentError, &quot;when specifying :polymorphic =&gt; true, no block or other options may be given&quot; if block_given? or options.length &gt; 0
+          names = [&quot;?#{names.first}&quot;] 
+        end
+
+        # ignore first '*' if it has already been specified by :load_enclosing == true
+        names.shift if specifications == ['*'] &amp;&amp; names.first == '*'
+        
         names.each do |name|
-          specifications &lt;&lt; (name.to_s == '*' ? '*' : Specification.new(name, options, &amp;block))
+          ensure_sane_wildcard if name == '*'
+          specifications &lt;&lt; (name.to_s =~ /^(\*|\?(.*))$/ ? name.to_s : Specification.new(name, options, &amp;block))
         end
       end
       
       def deprecated_nested_in(options)
-        options[:class] ||= options[:class_name] &amp;&amp; options[:class_name].constantize
-        options[:source] ||= options[:collection_name]
-        options[:key] ||= options[:foreign_key]
-        [:class_name, :collection_name, :load_enclosing, :polymorphic, :foreign_key].each do |k|
+        options[:class_name]      and options[:class]  ||= options[:class_name].constantize
+        options[:collection_name] and options[:source] ||= options[:collection_name]
+        options[:foreign_key]     and options[:key]    ||= options[:foreign_key]
+        [:class_name, :collection_name, :load_enclosing, :anonymous, :foreign_key].each do |k|
           if options.key?(k)
             ActiveSupport::Deprecation.warn(&quot;option :#{k} has been deprecated for nested_in and will be removed soon&quot;)
             options.delete(k)
@@ -498,6 +507,20 @@ module Ardes#:nodoc:
       def resource_specification
         read_inheritable_attribute(:resource_specification)
       end
+      
+    private
+      # ensure that specifications array is determinate w.r.t route matching
+      def ensure_sane_wildcard
+        idx = specifications.length
+        while (idx -= 1) &gt;= 0
+          if specifications[idx] == '*'
+            raise ArgumentError, &quot;Can only specify one wildcard '*' in between resource specifications&quot;
+          elsif specifications[idx].is_a?(Specification)
+            break
+          end
+        end
+        true
+      end
     end
     
     module InstanceMethods
@@ -578,31 +601,28 @@ module Ardes#:nodoc:
       
       # returns the name of the immediately enclosing resource
       def enclosing_resource_name
-        enclosing_resource &amp;&amp; @enclosing_resource_name ||= enclosing_resource.class.name.underscore
+        enclosing_resource.class.name.underscore
       end
       
       # returns the resource service for the controller - this will be lazilly created
-      # to a ResourceService, or a SingletonResourceService (if :singelton =&gt; true)
+      # to a ResourceService, or a SingletonResourceService (if :singleton =&gt; true)
       def resource_service
         @resource_service ||= resource_specification.singleton? ? SingletonResourceService.new(self) : ResourceService.new(self)
       end
       
       # returns the instance resource_specification
       def resource_specification
-        @resource_specification ||= returning self.class.resource_specification.dup do |specification|
-          specification.controller = self
-        end
+        self.class.resource_specification
       end
       
-    protected
       # returns an array of the controller's enclosing (nested in) resources
       def enclosing_resources
         @enclosing_resources ||= []
       end
   
-      # returns an array of the non singleton enclosing resources, this is used for generating routes.
-      def non_singleton_resources
-        @non_singleton_resources ||= []
+      # returns an array of the collection (non singleton) enclosing resources, this is used for generating routes.
+      def enclosing_collection_resources
+        @enclosing_collection_resources ||= []
       end
       
     private
@@ -615,21 +635,8 @@ module Ardes#:nodoc:
       
       # returns the all route segments except for the ones corresponding to the current resource and action.
       # Also remove any route segments from the front which correspond to modules (namespaces)
-      def enclosing_route_segments
-        segments = recognized_route.segments.dup
-        
-        # shift namespaces from segments, update the name_prefix accordingly for outgoing routes. 
-        namespaces = self.class.name.underscore.split('/') - [controller_name]
-        
-        while namespaces.size &gt; 0
-          if segments[0].is_a?(ActionController::Routing::DividerSegment) &amp;&amp; segments[1].is_a?(ActionController::Routing::StaticSegment) &amp;&amp; segments[1].value == namespaces.first
-            segments.shift; segments.shift # remove the '/' &amp; 'namespace' segments from the front
-            update_name_prefix(&quot;#{namespaces.shift}_&quot;)
-          else
-            break
-          end
-        end
-        
+      def enclosing_segments
+        segments = remove_namespaces_from_segments(recognized_route.segments.dup)
         if segments.select{|s| s.is_a?(ActionController::Routing::DynamicSegment)}.collect(&amp;:key) == [:controller, :action, :id]
           logger.warn &quot;WARNING: resources_controller: #{controller_name} has recognized the default route: #{recognized_route}&quot;
         end
@@ -637,16 +644,30 @@ module Ardes#:nodoc:
           segment = segments.pop
           return segments if segment.is_a?(::ActionController::Routing::StaticSegment) &amp;&amp; segment.value == resource_specification.segment
         end
-        ResourcesController.raise_missing_route_segment(self)
+        ResourcesController.raise_missing_segment(self)
+      end
+      
+      # shift namespaces from segments, update the name_prefix accordingly for outgoing routes. 
+      def remove_namespaces_from_segments(segments)
+        namespaces = controller_path.sub(controller_name,'').sub(/\/$/,'').split('/')
+        while namespaces.size &gt; 0
+          if segments[0].is_a?(ActionController::Routing::DividerSegment) &amp;&amp; segments[1].is_a?(ActionController::Routing::StaticSegment) &amp;&amp; segments[1].value == namespaces.first
+            segments.shift; segments.shift # shift the '/' &amp; 'namespace' segments
+            update_name_prefix(&quot;#{namespaces.shift}_&quot;)
+          else
+            break
+          end
+        end
+        segments
       end
       
       # Returns an array of pairs [&lt;name&gt;, &lt;singleton?&gt;] e.g. [[users, false], [blog, true], [posts, false]]
-      # corresponding to the enclosing resources.
+      # corresponding to the enclosing resource route segments
       #
       # This is used to map resources and automatically load resources.
-      def route_resource_names
-        @route_resource_names ||= returning(Array.new) do |req|
-          enclosing_route_segments.each do |segment|
+      def route_enclosing_names
+        @route_enclosing_names ||= returning(Array.new) do |req|
+          enclosing_segments.each do |segment|
             unless segment.is_optional or segment.is_a?(::ActionController::Routing::DividerSegment)
               req &lt;&lt; [segment.value, true] if segment.is_a?(::ActionController::Routing::StaticSegment)
               req.last[1] = false if segment.is_a?(::ActionController::Routing::DynamicSegment)
@@ -655,33 +676,60 @@ module Ardes#:nodoc:
         end
       end
       
-      # this is the before_filter that 
-      # * loads all specified and wilcard resources
-      # * sets the controller instance to the current resource specification
+      # this is the before_filter that loads all specified and wildcard resources
       def load_enclosing_resources
         specifications.each_with_index do |spec, idx|
-          spec == '*' ? load_wildcards(specifications[idx+1]) : spec.load_into(self)
-        end
-      end
-    
-      # loads resoources from the route segments, using the segment names to either
-      # * map to a specification, or
-      # * create a specification using the segment name
-      def load_wildcards(to_spec)
-        return if to_spec == '*'
-        route_resource_names.slice(enclosing_resources.size..-1).each do |segment, singleton|
-          return if to_spec &amp;&amp; to_spec.segment == segment
-          if resource_specification_map[segment]
-            resource_specification_map[segment].load_into(self)
-          else
-            name = singleton ? segment : segment.singularize
-            Specification.new(name, :singleton =&gt; singleton).load_into(self)
+          case spec
+            when '*' then load_wildcards_from(idx)
+            when /^\?(.*)/ then load_wildcard($1)
+            else load_enclosing_resource_from_specification(spec)
           end
         end
       end
       
-      # The name prefix is used for forwarding urls.  This is different dependning on
-      # which route the controller was invoked by.  The resource spcifications build
+      # load a wildcard resource by either
+      # * matching the segment to mapped resource specification, or
+      # * creating one using the segment name
+      # Optionally takes a variable name to set the instance variable as (for polymorphic use)
+      def load_wildcard(as = nil)
+        route_enclosing_names[enclosing_resources.size] or ResourcesController.raise_resource_mismatch(self)
+        segment, singleton = *route_enclosing_names[enclosing_resources.size]
+        spec = resource_specification_map[segment] || Specification.new(singleton ? segment : segment.singularize, :singleton =&gt; singleton)
+        load_enclosing_resource_from_specification(spec, as)
+      end
+      
+      # loads a series of wildcard resources, from the specified specification idx
+      #
+      # To do this, we need to figure out where the next specified resource is
+      # and how many single wildcards are prior to that.  What is left over from
+      # the current route enclosing names will be the number of wildcards we need to load
+      def load_wildcards_from(start)
+        specs = specifications.slice(start..-1)
+        encls = route_enclosing_names.slice(enclosing_resources.size..-1)
+        
+        if spec = specs.find {|s| s.is_a?(Specification)}
+          spec_seg = encls.index([spec.segment, spec.singleton?]) or ResourcesController.raise_resource_mismatch(self)
+          number_of_wildcards = spec_seg - (specs.index(spec) -1)
+        else
+          number_of_wildcards = encls.length - (specs.length - 1)
+        end        
+
+        number_of_wildcards.times { load_wildcard }
+      end
+         
+      def load_enclosing_resource_from_specification(spec, as = nil)
+        spec.segment == route_enclosing_names[enclosing_resources.size].first or ResourcesController.raise_resource_mismatch(self)
+        returning spec.find_from(self) do |resource|
+          update_name_prefix(spec.name_prefix)
+          enclosing_resources &lt;&lt; resource
+          enclosing_collection_resources &lt;&lt; resource unless spec.singleton?
+          instance_variable_set(&quot;@#{spec.name}&quot;, resource)
+          instance_variable_set(&quot;@#{as}&quot;, resource) if as
+        end
+      end
+        
+      # The name prefix is used for forwarding urls and will be different depending on
+      # which route the controller was invoked by.  The resource specifications build
       # up the name prefix as the resources are loaded.
       def update_name_prefix(name_prefix)
         @name_prefix = &quot;#{@name_prefix}#{name_prefix}&quot;
@@ -703,7 +751,7 @@ module Ardes#:nodoc:
       end
       
       def find(*args, &amp;block)
-        resource_specification.find ? resource_specification.find_custom : super
+        resource_specification.find ? resource_specification.find_custom(controller) : super
       end
       
       def respond_to?(method)
@@ -718,7 +766,7 @@ module Ardes#:nodoc:
     class SingletonResourceService &lt; ResourceService
       def find(*args)
         if resource_specification.find
-          resource_specification.find_custom
+          resource_specification.find_custom(controller)
         elsif enclosing_resource
           enclosing_resource.send(resource_specification.source)
         else
@@ -739,11 +787,14 @@ module Ardes#:nodoc:
     class CantFindSingleton &lt; RuntimeError #:nodoc:
     end
 
-    class MissingRouteSegment &lt; RuntimeError #:nodoc:
+    class MissingSegment &lt; RuntimeError #:nodoc:
     end
 
     class NoRecognizedRoute &lt; RuntimeError #:nodoc:
     end
+    
+    class ResourceMismatch &lt; RuntimeError #:nodoc:
+    end
 
     class &lt;&lt; self
       def raise_cant_find_singleton(name, klass) #:nodoc:
@@ -768,8 +819,8 @@ help.  Do this by mapping the route segment to a resource in the controller, or
 end_str
       end
 
-      def raise_missing_route_segment(controller) #:nodoc:
-        raise MissingRouteSegment, &lt;&lt;-end_str
+      def raise_missing_segment(controller) #:nodoc:
+        raise MissingSegment, &lt;&lt;-end_str
 Could not recognize segment '#{controller.resource_specification.segment}' in route:
   #{controller.send(:recognized_route)}
 
@@ -795,7 +846,16 @@ Possible reasons for this:
 - the test can't figure out which route corresponds to the params, in this 
   case you may need to stub the recognized_route. (rspec example:)
   @controller.stub!(:recognized_route).and_return(ActionController::Routing::Routes.named_routes[:the_route])
+        end_str
+      end
+      
+      def raise_resource_mismatch(controller) #:nodoc:
+        raise ResourceMismatch, &lt;&lt;-end_str
+resources_controller can't match the route to the resource specification
+  route:         #{controller.send(:recognized_route)}
+  specification: enclosing: [#{controller.specifications.collect{|s| s.is_a?(Specification) ? &quot;:#{s.segment}&quot; : s}.join(', ')}], resource :#{controller.resource_specification.segment}
   
+the successfully loaded enclosing resources are: #{controller.enclosing_resources.join(', ')}
         end_str
       end
     end</diff>
      <filename>lib/ardes/resources_controller.rb</filename>
    </modified>
    <modified>
      <diff>@@ -127,7 +127,7 @@ Currently:
           self.class.send :module_eval, &lt;&lt;-end_eval, __FILE__, __LINE__
             def #{method}(*args)
               options = args.last.is_a?(Hash) ? args.pop : {}
-              args = args.size &lt; #{required_args} ? non_singleton_resources + args : non_singleton_resources - [enclosing_resource] + args
+              args = args.size &lt; #{required_args} ? enclosing_collection_resources + args : enclosing_collection_resources - [enclosing_resource] + args
               args = args + [options] if options.size &gt; 0
               send :#{route_method}, *args
             end
@@ -140,9 +140,9 @@ Currently:
           self.class.send :module_eval, &lt;&lt;-end_eval, __FILE__, __LINE__
             def #{method}(*args)
               options = args.last.is_a?(Hash) ? args.pop : {}
-              #{&quot;args = [resource] + args if non_singleton_resources.size + args.size &lt; #{required_args}&quot; if required_args &gt; 0}
+              #{&quot;args = [resource] + args if enclosing_collection_resources.size + args.size &lt; #{required_args}&quot; if required_args &gt; 0}
               args = args + [options] if options.size &gt; 0
-              send :#{route_method}, *(non_singleton_resources + args)
+              send :#{route_method}, *(enclosing_collection_resources + args)
             end
           end_eval
         end</diff>
      <filename>lib/ardes/resources_controller/named_route_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,16 +3,17 @@ module Ardes#:nodoc:
     # This class holds all the info that is required to find a resource, or determine a name prefix, based on a route segment
     # or segment pair (e.g. /blog or /users/3).
     #
-    # You don't need to instatiate this class directly - it is created by ResourcesController::ClassMethods#nested_in,
-    # ResourcesController#map_resource (and ResourcesController::InstanceMethods#load_wildcards)
+    # You don't need to instantiate this class directly - it is created by ResourcesController::ClassMethods#nested_in,
+    # ResourcesController#map_resource (and ResourcesController::InstanceMethods#load_wildcard)
+    #
+    # This is primarily a container class.  A summary of its behaviour:
+    # 1. setting defaults for its own variables on initialize, and
+    # 2. finding an enclosing resource, given a controller object
     #
-    # This class is 'friendly' with controller, see load_into 
     class Specification
       attr_reader :name, :source, :klass, :key, :name_prefix, :segment, :find
-      attr_accessor :controller
-      delegate :enclosing_resource, :to =&gt; :controller
-
-      # acts as a factory for Specification and SingletonSpecification
+      
+      # factory for Specification and SingletonSpecification
       #
       # you can call Specification.new 'name', :singleton =&gt; true
       def self.new(name, options = {}, &amp;block)
@@ -54,29 +55,21 @@ module Ardes#:nodoc:
       def singleton?
         false
       end
-      
-      # This method loads the resource into the passed controller, accessing some of the controller's
-      # internals to do so.
-      #
-      # This is the 'friend' functionality
-      def load_into(controller)
-        self.controller = controller
-        resource = find ? find_custom : find_resource
-        controller.send(:update_name_prefix, name_prefix)
-        controller.send(:enclosing_resources) &lt;&lt; resource
-        controller.send(:non_singleton_resources) &lt;&lt; resource unless singleton?
-        controller.send(:instance_variable_set, &quot;@#{name}&quot;, resource)
-      end
 
+      # given a controller object, returns the resource according to this specification
+      def find_from(controller)
+        find ? find_custom(controller) : find_resource(controller)
+      end
+      
       # finds the resource using the custom :find Proc or symbol
-      def find_custom
+      def find_custom(controller)
         raise &quot;This specification has no custom :find attribute&quot; unless find
         find.is_a?(Proc) ? controller.instance_eval(&amp;find) : controller.send(find)
       end
       
-      # finds the resource using enclosing resources or resource class
-      def find_resource
-        (enclosing_resource ? enclosing_resource.send(source) : klass).find controller.params[key]
+      # finds the resource on a controller using enclosing resources or resource class
+      def find_resource(controller)
+        (controller.enclosing_resource ? controller.enclosing_resource.send(source) : klass).find controller.params[key]
       end
     end
   
@@ -100,9 +93,9 @@ module Ardes#:nodoc:
       end
     
       # finds the resource from the enclosing resource.  Raise CantFindSingleton if there is no enclosing resource
-      def find_resource
-        ResourcesController.raise_cant_find_singleton(name, klass) unless enclosing_resource
-        enclosing_resource.send(source)
+      def find_resource(controller)
+        ResourcesController.raise_cant_find_singleton(name, klass) unless controller.enclosing_resource
+        controller.enclosing_resource.send(source)
       end
     end
   end</diff>
      <filename>lib/ardes/resources_controller/specification.rb</filename>
    </modified>
    <modified>
      <diff>@@ -45,6 +45,12 @@ ActionController::Routing::Routes.draw do |map|
   
   map.resources :tags
   
+  # the following routes are for testing errors
+  map.resources :posts, :controller =&gt; 'forum_posts'
+  map.resources :foos do |foo|
+    foo.resources :bars, :controller =&gt; 'forum_posts'
+  end
+  
   map.connect ':controller/:action/:id.:format'
   map.connect ':controller/:action/:id'
 end
@@ -248,8 +254,9 @@ class ForumPostsController &lt; PostsController
   # for testing filter load order
   before_filter {|controller| controller.filter_trace ||= []; controller.filter_trace &lt;&lt; :forum_posts}
 
-  # test inherited resources_controller_for use
+  # test override resources_controller_for use
   resources_controller_for :posts
+  
   # example of providing a custom finder for the nesting resource
   nested_in :forum do
     Forum.find(params[:forum_id])
@@ -257,14 +264,13 @@ class ForumPostsController &lt; PostsController
 end
 
 class CommentsController &lt; ApplicationController
-  resources_controller_for :comments, :in =&gt; [:forum, :post]
+  resources_controller_for :comments, :in =&gt; [:forum, :post], :load_enclosing =&gt; false
 end
 
 class InterestsController &lt; ApplicationController
   resources_controller_for :interests
-  before_filter :set_interested_in
+  nested_in :interested_in, :polymorphic =&gt; true
   
-  def set_interested_in
-    @interested_in = enclosing_resource
-  end
+  # the above two lines are the same as:
+  #   resources_controller_for :interests, :in =&gt; '?interested_in'
 end
\ No newline at end of file</diff>
      <filename>spec/app.rb</filename>
    </modified>
    <modified>
      <diff>@@ -26,7 +26,7 @@ describe &quot;Routing shortcuts for Account should map&quot; do
    
   it &quot;resource_info_tags_path to /account/info/tags&quot; do
     controller.resource_info_tags_path.should == &quot;/account/info/tags&quot;
-  end
+  end    
 end
 
 describe AccountController, &quot;#resource_service&quot; do
@@ -52,7 +52,12 @@ describe AccountController, &quot;#resource_service&quot; do
   
   it &quot;.find should call whatever is in resource_specification @find&quot; do
     @controller.should_receive(:lambda_called).once.and_return(@current_user)
-    @controller.send(:resource_specification).instance_variable_set &quot;@find&quot;, lambda { lambda_called }
+    @controller.send(:resource_specification).stub!(:find).and_return(lambda { lambda_called })
     @resource_service.find
   end
+  
+  it &quot;.find should raise CantFindSingleton when no custom finder (and no enclosing resource)&quot; do
+    @controller.send(:resource_specification).stub!(:find).and_return nil
+    lambda{ @resource_service.find }.should raise_error(Ardes::ResourcesController::CantFindSingleton)
+  end
 end
\ No newline at end of file</diff>
      <filename>spec/controllers/account_controller_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -115,7 +115,7 @@ describe &quot;Routing shortcuts for Admin::Forums should map&quot; do
     controller.should respond_to(:edit_resource_interest_path)
   end
 
-  it &quot;resource_users_path should raise informative NoMethodError&quot; do
+  it &quot;resource_users_path should raise informative CantMapRoute&quot; do
     lambda{ controller.resource_users_path }.should raise_error(Ardes::ResourcesController::CantMapRoute, &lt;&lt;-end_str
 Tried to map :resource_users_path to :admin_forum_users_path,
 which doesn't exist. You may not have defined the route in config/routes.rb.</diff>
      <filename>spec/controllers/admin_forums_controller_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -94,6 +94,23 @@ describe &quot;Routing shortcuts for ForumPosts (forums/2/posts/1) should map&quot; do
   end
 end
 
+describe ForumPostsController, &quot; errors&quot; do
+  controller_name :forum_posts
+  
+  it &quot;should raise ResourceMismatch for /posts&quot; do
+    lambda{ get :index }.should raise_error(Ardes::ResourcesController::ResourceMismatch)
+  end
+
+  it &quot;should raise MissingSegment, when route does not contain the resource segment&quot; do
+    lambda{ get :index, :foo_id =&gt; 1}.should raise_error(Ardes::ResourcesController::MissingSegment)
+  end
+  
+  it &quot;should raise NoRecognizedRoute when no route is recognized&quot; do
+    ::ActionController::Routing::Routes.stub!(:routes_for_controller_and_action).and_return([])
+    lambda{ get :index }.should raise_error(Ardes::ResourcesController::NoRecognizedRoute)
+  end
+end
+
 describe &quot;resource_service in ForumPostsController&quot; do
   controller_name :forum_posts
   </diff>
      <filename>spec/controllers/forum_posts_controller_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -211,6 +211,12 @@ describe &quot;Requesting /forums/2/owner using POST&quot; do
     response.should be_redirect
     response.redirect_url.should == &quot;http://test.host/forums/2/owner&quot;
   end
+  
+  it &quot;should render new when post unsuccesful&quot; do
+    @owner.stub!(:save).and_return(false)
+    do_post
+    response.should render_template('new')
+  end
 end
 
 </diff>
      <filename>spec/controllers/owner_controller_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -24,6 +24,7 @@ describe &quot;ActionView with resources_controller Helper&quot; do
   it_should_forward_to_controller :resource
   it_should_forward_to_controller :resources
   it_should_forward_to_controller :enclosing_resource
+  it_should_forward_to_controller :enclosing_resource_name
   
   it 'should not forward unknown url helper to controller' do
     @controller.stub!(:resource_named_route_helper_method?).and_return(false)</diff>
      <filename>spec/specs/action_view_helper_spec.rb</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>spec/specs/resources_controller_spec.rb</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>e8fc191094b3a333c9b5fd501cb7b2e81078a2bc</id>
    </parent>
  </parents>
  <author>
    <name>ian</name>
    <email>ian@845bbffb-5c18-0410-91b3-f25c072b94c1</email>
  </author>
  <url>http://github.com/ianwhite/resources_controller/commit/44316d0a6734bb3953abf1349f401d6f6bce51df</url>
  <id>44316d0a6734bb3953abf1349f401d6f6bce51df</id>
  <committed-date>2007-10-24T08:14:37-07:00</committed-date>
  <authored-date>2007-10-24T08:14:37-07:00</authored-date>
  <message>resources_controller: - :polymorphic =&gt; true is back:
      resources_controller_for :tags
      nested_in :taggable, :polymorphic =&gt; true

    This will load the enclosing resource (which can be a mapped resource) as
    @taggable as well as its default name
  
    The following syntax is equivalent to the above two lines:
      resources_controller_for :tags, :in =&gt; '?taggable'
  
    And you can specify a single wildcard '?' as well as expanding wildcards '*':
      resources_controller_for :images, :in =&gt; '?', :load_enclosing =&gt; false
      # this will work for routes like /users/1/images, /forums/2/images, /featured/images
  
  - test coverage is up
  
  - moved some of the 'friend' functionality out of Specification, as it smelt bad

git-svn-id: https://svn.ardes.com/rails_plugins/resources_controller@464 845bbffb-5c18-0410-91b3-f25c072b94c1</message>
  <tree>79858f0841e8d70e62e87f6f3919418f6a77e49b</tree>
  <committer>
    <name>ian</name>
    <email>ian@845bbffb-5c18-0410-91b3-f25c072b94c1</email>
  </committer>
</commit>
