From e494b0a441aab6d85a7b1cdc2c3b0d03196ada21 Mon Sep 17 00:00:00 2001 From: Nicholas Seckar Date: Fri, 30 Jun 2006 02:36:17 +0000 Subject: Add route_name_path method to generate only the path for a named routes. For example, map.person will add person_path. git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@4518 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- actionpack/CHANGELOG | 2 + actionpack/lib/action_controller/routing.rb | 80 +++++++++++++----------- actionpack/lib/action_controller/url_rewriter.rb | 2 +- actionpack/test/controller/routing_test.rb | 13 +++- 4 files changed, 58 insertions(+), 39 deletions(-) diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index dfae63ee79..4a63ba47d7 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* Add route_name_path method to generate only the path for a named routes. For example, map.person will add person_path. [Nicholas Seckar] + * Avoid naming collision among compiled view methods. [Jeremy Kemper] * Fix CGI extensions when they expect string but get nil in Windows. Closes #5276 [mislav@nippur.irb.hr] diff --git a/actionpack/lib/action_controller/routing.rb b/actionpack/lib/action_controller/routing.rb index d53becd2a9..f374fff02f 100644 --- a/actionpack/lib/action_controller/routing.rb +++ b/actionpack/lib/action_controller/routing.rb @@ -120,7 +120,7 @@ module ActionController class Route attr_accessor :segments, :requirements, :conditions - + def initialize @segments = [] @requirements = {} @@ -137,7 +137,7 @@ module ActionController args = "options, hash, expire_on = {}" # Nest the body inside of a def block, and then compile it. - method_decl = "def generate_raw(#{args})\npath = begin\n#{body}\nend\n[path, hash]\nend" + raw_method = method_decl = "def generate_raw(#{args})\npath = begin\n#{body}\nend\n[path, hash]\nend" # puts "\n======================" # puts # p self @@ -157,6 +157,7 @@ module ActionController method_decl = "def generate_extras(#{args})\npath, hash = generate_raw(options, hash, expire_on)\n[path, extra_keys(hash, expire_on)]\nend" instance_eval method_decl, "generated code (#{__FILE__}:#{__LINE__})" + raw_method end # Build several lines of code that extract values from the options hash. If any @@ -219,7 +220,7 @@ module ActionController end wrap ? ("\\A" + pattern + "\\Z") : pattern end - + # Write the code to extract the parameters from a matched route. def recognition_extraction next_capture = 1 @@ -344,10 +345,10 @@ module ActionController def to_s @to_s ||= begin - segs = segments.inject("") { |str,s| str << s.to_s } - "%-6s %-40s %s" % [(conditions[:method] || :any).to_s.upcase, segs, requirements.inspect] - end - end + segs = segments.inject("") { |str,s| str << s.to_s } + "%-6s %-40s %s" % [(conditions[:method] || :any).to_s.upcase, segs, requirements.inspect] + end + end protected @@ -806,8 +807,7 @@ module ActionController def add(name, route) routes[name.to_sym] = route - define_hash_access_method(name, route) - define_url_helper_method(name, route) + define_named_route_methods(name, route) end def get(name) @@ -840,31 +840,41 @@ module ActionController private - def url_helper_name(name) - :"#{name}_url" + def url_helper_name(name, kind = :url) + :"#{name}_#{kind}" end - def hash_access_name(name) - :"hash_for_#{name}_url" + def hash_access_name(name, kind = :url) + :"hash_for_#{name}_#{kind}" end - def define_hash_access_method(name, route) - method_name = hash_access_name(name) - - @module.send(:define_method, method_name) do |*args| - hash = route.defaults.merge(:use_route => name) - args.first ? hash.merge(args.first) : hash + def define_named_route_methods(name, route) + {:url => {}, :path => {:only_path => true}}.each do |kind, opts| + hash = route.defaults.merge(:use_route => name).merge(opts) + define_hash_access route, name, kind, hash + define_url_helper route, name, kind, hash end - - @module.send(:protected, method_name) - helpers << method_name end - - def define_url_helper_method(name, route) - hash_access_method = hash_access_name(name) - method_name = url_helper_name(name) - - @module.send(:define_method, method_name) do |*args| + + def define_hash_access(route, name, kind, options) + selector = hash_access_name(name, kind) + @module.send(:define_method, selector) do |*args| + args.first ? options.merge(args.first) : options + end + @module.send(:protected, selector) + helpers << selector + end + + def define_url_helper(route, name, kind, options) + selector = url_helper_name(name, kind) + + # The segment keys used for positional paramters + segment_keys = route.segments.collect do |segment| + segment.key if segment.respond_to? :key + end.compact + hash_access_method = hash_access_name(name, kind) + + @module.send(:define_method, selector) do |*args| opts = if args.empty? || Hash === args.first args.first || {} else @@ -876,20 +886,18 @@ module ActionController # instead of # # foo_url(:bar => bar, :baz => baz, :bang => bang) - route.segments.inject({}) do |opts, seg| - next opts unless seg.respond_to?(:key) && seg.key - opts[seg.key] = args.shift - break opts if args.empty? - opts + args.zip(segment_keys).inject({}) do |h, (v, k)| + h[k] = v + h end end url_for(send(hash_access_method, opts)) end - - @module.send(:protected, method_name) - helpers << method_name + @module.send(:protected, selector) + helpers << selector end + end attr_accessor :routes, :named_routes diff --git a/actionpack/lib/action_controller/url_rewriter.rb b/actionpack/lib/action_controller/url_rewriter.rb index 4aa0576976..d0615bc023 100644 --- a/actionpack/lib/action_controller/url_rewriter.rb +++ b/actionpack/lib/action_controller/url_rewriter.rb @@ -7,7 +7,7 @@ module ActionController @request, @parameters = request, parameters end - def rewrite(options = {}) + def rewrite(options = {}) rewrite_url(rewrite_path(options), options) end diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index e6d42c823f..56070fe6f3 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -1108,8 +1108,9 @@ class RouteSetTest < Test::Unit::TestCase end def url_for(options) + only_path = options.delete(:only_path) path = routes.generate(options) - "http://named.route.test#{path}" + only_path ? path : "http://named.route.test#{path}" end end @@ -1193,13 +1194,21 @@ class RouteSetTest < Test::Unit::TestCase assert_equal( { :controller => 'people', :action => 'index', :use_route => :index }, controller.send(:hash_for_index_url)) + + assert_equal( + { :controller => 'people', :action => 'show', :id => 5, :use_route => :show, :only_path => true }, + controller.send(:hash_for_show_path, :id => 5) + ) end def test_named_route_url_method controller = setup_named_route_test - + assert_equal "http://named.route.test/people/5", controller.send(:show_url, :id => 5) + assert_equal "/people/5", controller.send(:show_path, :id => 5) + assert_equal "http://named.route.test/people", controller.send(:index_url) + assert_equal "/people", controller.send(:index_path) end def test_namd_route_url_method_with_ordered_parameters -- cgit v1.2.3