From f7af75976a9117aa1cb294114af4f99a1d28f1cd Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 23 Jun 2010 02:38:44 +0200 Subject: require 'active_support/dependencies' in action_dispatch/middleware/stack --- actionpack/lib/action_dispatch/middleware/stack.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/middleware/stack.rb b/actionpack/lib/action_dispatch/middleware/stack.rb index 5a029a60d1..6f243574e4 100644 --- a/actionpack/lib/action_dispatch/middleware/stack.rb +++ b/actionpack/lib/action_dispatch/middleware/stack.rb @@ -1,4 +1,5 @@ require "active_support/inflector/methods" +require "active_support/dependencies" module ActionDispatch class MiddlewareStack < Array -- cgit v1.2.3 From 28016d33b0f2e668ca59a912c7fb2d777e3cf0a3 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 1 Jul 2010 09:04:30 +0200 Subject: Use env['action_dispatch.routes'] to determine if we should generate prefix or not. This technique is here to allow using routes from Engine in Application and vice versa. When using Engine routes inside Application it should generate prefix based on mount point. When using Engine routes inside Engine it should use env['SCRIPT_NAME']. In any other case it should generate prefix as env should not be even available. --- actionpack/lib/action_dispatch/routing/mapper.rb | 27 ++++++ .../lib/action_dispatch/routing/route_set.rb | 20 ++-- actionpack/lib/action_dispatch/routing/url_for.rb | 8 +- actionpack/test/controller/routing_test.rb | 2 +- actionpack/test/dispatch/prefix_generation_test.rb | 102 +++++++++++++++++++++ 5 files changed, 151 insertions(+), 8 deletions(-) create mode 100644 actionpack/test/dispatch/prefix_generation_test.rb (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index a2570cb877..f3aa09f4a7 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -261,7 +261,11 @@ module ActionDispatch raise "A rack application must be specified" unless path + options[:as] ||= app_name(app) + match(path, options.merge(:to => app, :anchor => false, :format => false)) + + define_generate_prefix(app, options[:as]) self end @@ -269,6 +273,29 @@ module ActionDispatch @set.default_url_options = options end alias_method :default_url_options, :default_url_options= + + private + def app_name(app) + return unless app.respond_to?(:routes) + class_name = app.class.is_a?(Class) ? app.name : app.class.name + ActiveSupport::Inflector.underscore(class_name).gsub("/", "_") + end + + def define_generate_prefix(app, name) + return unless app.respond_to?(:routes) + + _route = @set.named_routes.routes[name.to_sym] + _router = @set + app.routes.class_eval do + define_method :_generate_prefix do |options| + keys = _route.segment_keys + ActionDispatch::Routing::RouteSet::RESERVED_OPTIONS + prefix_options = options.reject { |k, v| !(keys).include?(k) } + # we must actually delete prefix segment keys to avoid passing them to next url_for + _route.segment_keys.each { |k| options.delete(k) } + _router.url_helpers.send("#{name}_path", prefix_options) + end + end + end end module HttpHelpers diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index b531cc1a8e..cb0373951f 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -303,10 +303,9 @@ module ActionDispatch end class Generator #:nodoc: - attr_reader :options, :recall, :set, :script_name, :named_route + attr_reader :options, :recall, :set, :named_route def initialize(options, recall, set, extras = false) - @script_name = options.delete(:script_name) @named_route = options.delete(:use_route) @options = options.dup @recall = recall.dup @@ -401,7 +400,7 @@ module ActionDispatch return [path, params.keys] if @extras path << "?#{params.to_query}" if params.any? - "#{script_name}#{path}" + path rescue Rack::Mount::RoutingError raise_routing_error end @@ -453,7 +452,11 @@ module ActionDispatch Generator.new(options, recall, self, extras).generate end - RESERVED_OPTIONS = [:anchor, :params, :only_path, :host, :protocol, :port, :trailing_slash] + RESERVED_OPTIONS = [:anchor, :params, :only_path, :host, :protocol, :port, :trailing_slash, :script_name, :skip_prefix, :routes] + + def _generate_prefix(options = {}) + nil + end def url_for(options) finalize! @@ -464,7 +467,6 @@ module ActionDispatch rewritten_url = "" path_segments = options.delete(:_path_segments) - unless options[:only_path] rewritten_url << (options[:protocol] || "http") rewritten_url << "://" unless rewritten_url.match("://") @@ -476,9 +478,15 @@ module ActionDispatch rewritten_url << ":#{options.delete(:port)}" if options.key?(:port) end + path = [options.delete(:script_name)] + if !options.delete(:skip_prefix) + path << _generate_prefix(options) + end + path_options = options.except(*RESERVED_OPTIONS) path_options = yield(path_options) if block_given? - path = generate(path_options, path_segments || {}) + path << generate(path_options, path_segments || {}) + path = path.compact.join '' # ROUTES TODO: This can be called directly, so script_name should probably be set in the routes rewritten_url << (options[:trailing_slash] ? path.sub(/\?|\z/) { "/" + $& } : path) diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index 28ec830fe8..f73067688c 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -128,7 +128,13 @@ module ActionDispatch when String options when nil, Hash - _routes.url_for((options || {}).reverse_merge!(url_options).symbolize_keys) + routes = (options ? options.delete(:routes) : nil) || _routes + + if respond_to?(:env) && env && routes.equal?(env["action_dispatch.routes"]) + options[:skip_prefix] = true + end + + routes.url_for((options || {}).reverse_merge!(url_options).symbolize_keys) else polymorphic_url(options) end diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index a8c74a6064..1f14607c31 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -251,7 +251,7 @@ class LegacyRouteSetTests < Test::Unit::TestCase map.pages 'pages', :controller => 'content', :action => 'show_page', :host => 'foo.com' end x = setup_for_named_route - x.expects(:url_for).with(:host => 'foo.com', :only_path => false, :controller => 'content', :action => 'show_page', :use_route => :pages).once + x.expects(:url_for).with(:host => 'foo.com', :only_path => false, :controller => 'content', :action => 'show_page', :use_route => :pages, :router => rs).once x.send(:pages_url) end diff --git a/actionpack/test/dispatch/prefix_generation_test.rb b/actionpack/test/dispatch/prefix_generation_test.rb new file mode 100644 index 0000000000..95d5c1c366 --- /dev/null +++ b/actionpack/test/dispatch/prefix_generation_test.rb @@ -0,0 +1,102 @@ +require 'abstract_unit' + +module TestGenerationPrefix + class WithMountedEngine < ActionDispatch::IntegrationTest + class BlogEngine + def self.routes + @routes ||= begin + routes = ActionDispatch::Routing::RouteSet.new + routes.draw do + match "/posts/:id", :to => "inside_engine_generating#index", :as => :post + end + + routes + end + end + + def self.call(env) + env['action_dispatch.routes'] = routes + routes.call(env) + end + end + + class RailsApplication + def self.routes + @routes ||= begin + routes = ActionDispatch::Routing::RouteSet.new + routes.draw do + scope "/:omg", :omg => "awesome" do + mount BlogEngine => "/blog" + end + match "/generate", :to => "outside_engine_generating#index" + end + + routes + end + end + + def self.call(env) + env['action_dispatch.routes'] = routes + routes.call(env) + end + end + + class ::InsideEngineGeneratingController < ActionController::Base + include BlogEngine.routes.url_helpers + def index + render :text => post_path(:id => params[:id]) + end + end + + class ::OutsideEngineGeneratingController < ActionController::Base + include BlogEngine.routes.url_helpers + def index + render :text => post_path(:id => 1) + end + end + + class Foo + include ActionDispatch::Routing::UrlFor + include BlogEngine.routes.url_helpers + + def foo + post_path(42) + end + end + + + RailsApplication.routes # force draw + include BlogEngine.routes.url_helpers + + test "generating URL with prefix" do + assert_equal "/awesome/blog/posts/1", post_path(:id => 1) + end + + test "use SCRIPT_NAME inside the engine" do + env = Rack::MockRequest.env_for("/posts/1") + env["SCRIPT_NAME"] = "/pure-awesomness/blog" + response = ActionDispatch::Response.new(*BlogEngine.call(env)) + assert_equal "/pure-awesomness/blog/posts/1", response.body + end + + test "prepend prefix outside the engine" do + env = Rack::MockRequest.env_for("/generate") + env["SCRIPT_NAME"] = "/something" # it could be set by passenger + response = ActionDispatch::Response.new(*RailsApplication.call(env)) + assert_equal "/something/awesome/blog/posts/1", response.body + end + + test "generating urls with options for both prefix and named_route" do + assert_equal "/pure-awesomness/blog/posts/3", post_path(:id => 3, :omg => "pure-awesomness") + end + + test "generating urls with url_for should prepend the prefix" do + path = BlogEngine.routes.url_for(:omg => 'omg', :controller => "inside_engine_generating", :action => "index", :id => 1, :only_path => true) + assert_equal "/omg/blog/posts/1", path + end + + test "generating urls from a regular class" do + assert_equal "/awesome/blog/posts/42", Foo.new.foo + end + end +end -- cgit v1.2.3 From 451c9942bb493190d5673c1b55be7506056db13b Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 7 Jul 2010 11:26:03 +0200 Subject: Allow to generate Application routes inside Engine This requires knowledge about original SCRIPT_NAME and the parent router. It should be pass through the env as ORIGIAL_SCRIPT_NAME and action_dispatch.parent_routes --- actionpack/lib/action_dispatch/routing/mapper.rb | 2 +- actionpack/lib/action_dispatch/routing/url_for.rb | 6 +++--- actionpack/test/dispatch/prefix_generation_test.rb | 25 +++++++++++++++++++--- 3 files changed, 26 insertions(+), 7 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index f3aa09f4a7..0e138524cd 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -289,7 +289,7 @@ module ActionDispatch app.routes.class_eval do define_method :_generate_prefix do |options| keys = _route.segment_keys + ActionDispatch::Routing::RouteSet::RESERVED_OPTIONS - prefix_options = options.reject { |k, v| !(keys).include?(k) } + prefix_options = options.slice(*keys) # we must actually delete prefix segment keys to avoid passing them to next url_for _route.segment_keys.each { |k| options.delete(k) } _router.url_helpers.send("#{name}_path", prefix_options) diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index f73067688c..deaf1cdf03 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -129,9 +129,9 @@ module ActionDispatch options when nil, Hash routes = (options ? options.delete(:routes) : nil) || _routes - - if respond_to?(:env) && env && routes.equal?(env["action_dispatch.routes"]) - options[:skip_prefix] = true + if respond_to?(:env) && env + options[:skip_prefix] = true if routes.equal?(env["action_dispatch.routes"]) + options[:script_name] = env["ORIGINAL_SCRIPT_NAME"] if routes.equal?(env["action_dispatch.parent_routes"]) end routes.url_for((options || {}).reverse_merge!(url_options).symbolize_keys) diff --git a/actionpack/test/dispatch/prefix_generation_test.rb b/actionpack/test/dispatch/prefix_generation_test.rb index 95d5c1c366..efc56c067b 100644 --- a/actionpack/test/dispatch/prefix_generation_test.rb +++ b/actionpack/test/dispatch/prefix_generation_test.rb @@ -8,6 +8,7 @@ module TestGenerationPrefix routes = ActionDispatch::Routing::RouteSet.new routes.draw do match "/posts/:id", :to => "inside_engine_generating#index", :as => :post + match "/bare_url_for", :to => "inside_engine_generating#bare_url_for", :as => :bare_url_for end routes @@ -37,6 +38,10 @@ module TestGenerationPrefix def self.call(env) env['action_dispatch.routes'] = routes + + # the next to values should be set only in application + env['ORIGINAL_SCRIPT_NAME'] = env['SCRIPT_NAME'] + env['action_dispatch.parent_routes'] = routes routes.call(env) end end @@ -46,6 +51,14 @@ module TestGenerationPrefix def index render :text => post_path(:id => params[:id]) end + + def bare_url_for + path = url_for( :routes => RailsApplication.routes, + :controller => "outside_engine_generating", + :action => "index", + :only_path => true) + render :text => path + end end class ::OutsideEngineGeneratingController < ActionController::Base @@ -73,9 +86,8 @@ module TestGenerationPrefix end test "use SCRIPT_NAME inside the engine" do - env = Rack::MockRequest.env_for("/posts/1") - env["SCRIPT_NAME"] = "/pure-awesomness/blog" - response = ActionDispatch::Response.new(*BlogEngine.call(env)) + env = Rack::MockRequest.env_for("/pure-awesomness/blog/posts/1") + response = ActionDispatch::Response.new(*RailsApplication.call(env)) assert_equal "/pure-awesomness/blog/posts/1", response.body end @@ -98,5 +110,12 @@ module TestGenerationPrefix test "generating urls from a regular class" do assert_equal "/awesome/blog/posts/42", Foo.new.foo end + + test "passing :routes to url_for to change current routes" do + env = Rack::MockRequest.env_for("/pure-awesomness/blog/bare_url_for") + env["SCRIPT_NAME"] = "/something" + response = ActionDispatch::Response.new(*RailsApplication.call(env)) + assert_equal "/something/generate", response.body + end end end -- cgit v1.2.3 From eedbf87d15b99a7cae38b0d8894fc39f1e70a81e Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 8 Jul 2010 15:42:40 +0200 Subject: New way of generating urls for Application from Engine. It's based specifying application's script_name with: Rails.application.default_url_options = {:script_name => "/foo"} default_url_options method is delegated to routes. If router used to generate url differs from the router passed via env it always overwrites :script_name with this value. --- actionpack/lib/action_controller/metal/url_for.rb | 13 +++++++++++-- actionpack/lib/action_dispatch/routing/route_set.rb | 4 ++-- actionpack/lib/action_dispatch/routing/url_for.rb | 15 ++++++++++----- actionpack/test/controller/routing_test.rb | 2 +- actionpack/test/dispatch/prefix_generation_test.rb | 1 + 5 files changed, 25 insertions(+), 10 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/metal/url_for.rb b/actionpack/lib/action_controller/metal/url_for.rb index a51fc5b8e4..ca91e1f362 100644 --- a/actionpack/lib/action_controller/metal/url_for.rb +++ b/actionpack/lib/action_controller/metal/url_for.rb @@ -5,11 +5,20 @@ module ActionController include ActionDispatch::Routing::UrlFor def url_options - super.reverse_merge( + options = {} + if respond_to?(:env) && env + if _routes.equal?(env["action_dispatch.routes"]) + options[:skip_prefix] = true + elsif env["action_dispatch.routes"] + options[:script_name] = _routes.default_url_options[:script_name] + end + end + + super.merge(options).reverse_merge( :host => request.host_with_port, :protocol => request.protocol, :_path_segments => request.symbolized_path_parameters - ).merge(:script_name => request.script_name) + ).reverse_merge(:script_name => request.script_name) end def _routes diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index cb0373951f..7519d74183 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -280,10 +280,10 @@ module ActionDispatch # Yes plz - JP included do routes.install_helpers(self) - singleton_class.send(:define_method, :_routes) { routes } + singleton_class.send(:define_method, :_routes) { @_routes || routes } end - define_method(:_routes) { routes } + define_method(:_routes) { @_routes || routes } end helpers diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index deaf1cdf03..5da41df485 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -129,16 +129,21 @@ module ActionDispatch options when nil, Hash routes = (options ? options.delete(:routes) : nil) || _routes - if respond_to?(:env) && env - options[:skip_prefix] = true if routes.equal?(env["action_dispatch.routes"]) - options[:script_name] = env["ORIGINAL_SCRIPT_NAME"] if routes.equal?(env["action_dispatch.parent_routes"]) - end - routes.url_for((options || {}).reverse_merge!(url_options).symbolize_keys) + _with_routes(routes) do + routes.url_for((options || {}).reverse_merge!(url_options).symbolize_keys) + end else polymorphic_url(options) end end + + def _with_routes(routes) + old_routes, @_routes = @_routes, routes + yield + ensure + @_routes = old_routes + end end end end diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index 1f14607c31..a8c74a6064 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -251,7 +251,7 @@ class LegacyRouteSetTests < Test::Unit::TestCase map.pages 'pages', :controller => 'content', :action => 'show_page', :host => 'foo.com' end x = setup_for_named_route - x.expects(:url_for).with(:host => 'foo.com', :only_path => false, :controller => 'content', :action => 'show_page', :use_route => :pages, :router => rs).once + x.expects(:url_for).with(:host => 'foo.com', :only_path => false, :controller => 'content', :action => 'show_page', :use_route => :pages).once x.send(:pages_url) end diff --git a/actionpack/test/dispatch/prefix_generation_test.rb b/actionpack/test/dispatch/prefix_generation_test.rb index efc56c067b..49c5c82ad6 100644 --- a/actionpack/test/dispatch/prefix_generation_test.rb +++ b/actionpack/test/dispatch/prefix_generation_test.rb @@ -114,6 +114,7 @@ module TestGenerationPrefix test "passing :routes to url_for to change current routes" do env = Rack::MockRequest.env_for("/pure-awesomness/blog/bare_url_for") env["SCRIPT_NAME"] = "/something" + RailsApplication.routes.default_url_options = {:script_name => "/something"} response = ActionDispatch::Response.new(*RailsApplication.call(env)) assert_equal "/something/generate", response.body end -- cgit v1.2.3 From b1e5e233fabe8f75ebd06e7e08c15f0eeddbae79 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 8 Jul 2010 23:27:49 +0200 Subject: Refactored tests for prefix generation and added test for url generation in regular class with default_url_options[:script_name] set --- actionpack/test/dispatch/prefix_generation_test.rb | 43 ++++++++++++++++------ 1 file changed, 32 insertions(+), 11 deletions(-) (limited to 'actionpack') diff --git a/actionpack/test/dispatch/prefix_generation_test.rb b/actionpack/test/dispatch/prefix_generation_test.rb index 49c5c82ad6..6ceb07a4f1 100644 --- a/actionpack/test/dispatch/prefix_generation_test.rb +++ b/actionpack/test/dispatch/prefix_generation_test.rb @@ -2,6 +2,9 @@ require 'abstract_unit' module TestGenerationPrefix class WithMountedEngine < ActionDispatch::IntegrationTest + require 'rack/test' + include Rack::Test::Methods + class BlogEngine def self.routes @routes ||= begin @@ -30,6 +33,7 @@ module TestGenerationPrefix mount BlogEngine => "/blog" end match "/generate", :to => "outside_engine_generating#index" + root :to => "outside_engine_generating#index" end routes @@ -77,25 +81,39 @@ module TestGenerationPrefix end end + class Bar + include ActionDispatch::Routing::UrlFor + include RailsApplication.routes.url_helpers + + def bar + root_path + end + end RailsApplication.routes # force draw include BlogEngine.routes.url_helpers + def app + RailsApplication + end + + def setup + RailsApplication.routes.default_url_options = {} + end + test "generating URL with prefix" do assert_equal "/awesome/blog/posts/1", post_path(:id => 1) end test "use SCRIPT_NAME inside the engine" do - env = Rack::MockRequest.env_for("/pure-awesomness/blog/posts/1") - response = ActionDispatch::Response.new(*RailsApplication.call(env)) - assert_equal "/pure-awesomness/blog/posts/1", response.body + get "/pure-awesomness/blog/posts/1" + assert_equal "/pure-awesomness/blog/posts/1", last_response.body end test "prepend prefix outside the engine" do - env = Rack::MockRequest.env_for("/generate") - env["SCRIPT_NAME"] = "/something" # it could be set by passenger - response = ActionDispatch::Response.new(*RailsApplication.call(env)) - assert_equal "/something/awesome/blog/posts/1", response.body + RailsApplication.routes.default_url_options = {:script_name => "/something"} + get "/generate", {}, 'SCRIPT_NAME' => "/something" + assert_equal "/something/awesome/blog/posts/1", last_response.body end test "generating urls with options for both prefix and named_route" do @@ -112,11 +130,14 @@ module TestGenerationPrefix end test "passing :routes to url_for to change current routes" do - env = Rack::MockRequest.env_for("/pure-awesomness/blog/bare_url_for") - env["SCRIPT_NAME"] = "/something" RailsApplication.routes.default_url_options = {:script_name => "/something"} - response = ActionDispatch::Response.new(*RailsApplication.call(env)) - assert_equal "/something/generate", response.body + get "/pure-awesomness/blog/bare_url_for", {}, 'SCRIPT_NAME' => "/something" + assert_equal "/something/generate", last_response.body + end + + test "using default_url_options[:script_name] in regular classes" do + RailsApplication.routes.default_url_options = {:script_name => "/something"} + assert_equal "/something/", Bar.new.bar end end end -- cgit v1.2.3 From 8a077089d9b7aa89cb56ef754b4540f411453375 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 9 Jul 2010 01:22:18 +0200 Subject: Get rid of :skip_prefix options in routes --- actionpack/lib/action_controller/metal/url_for.rb | 12 ++++-------- actionpack/lib/action_dispatch/routing/route_set.rb | 9 +++------ actionpack/test/dispatch/url_generation_test.rb | 2 +- 3 files changed, 8 insertions(+), 15 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/metal/url_for.rb b/actionpack/lib/action_controller/metal/url_for.rb index ca91e1f362..ae628df81c 100644 --- a/actionpack/lib/action_controller/metal/url_for.rb +++ b/actionpack/lib/action_controller/metal/url_for.rb @@ -5,20 +5,16 @@ module ActionController include ActionDispatch::Routing::UrlFor def url_options - options = {} - if respond_to?(:env) && env - if _routes.equal?(env["action_dispatch.routes"]) - options[:skip_prefix] = true - elsif env["action_dispatch.routes"] - options[:script_name] = _routes.default_url_options[:script_name] + options = {} + if respond_to?(:env) && env && _routes.equal?(env["action_dispatch.routes"]) + options[:script_name] = request.script_name end - end super.merge(options).reverse_merge( :host => request.host_with_port, :protocol => request.protocol, :_path_segments => request.symbolized_path_parameters - ).reverse_merge(:script_name => request.script_name) + ) end def _routes diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 7519d74183..6f182ae652 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -452,7 +452,7 @@ module ActionDispatch Generator.new(options, recall, self, extras).generate end - RESERVED_OPTIONS = [:anchor, :params, :only_path, :host, :protocol, :port, :trailing_slash, :script_name, :skip_prefix, :routes] + RESERVED_OPTIONS = [:anchor, :params, :only_path, :host, :protocol, :port, :trailing_slash, :script_name, :routes] def _generate_prefix(options = {}) nil @@ -478,15 +478,12 @@ module ActionDispatch rewritten_url << ":#{options.delete(:port)}" if options.key?(:port) end - path = [options.delete(:script_name)] - if !options.delete(:skip_prefix) - path << _generate_prefix(options) - end + script_name = options.delete(:script_name) + path = (script_name.blank? ? _generate_prefix(options) : script_name).to_s path_options = options.except(*RESERVED_OPTIONS) path_options = yield(path_options) if block_given? path << generate(path_options, path_segments || {}) - path = path.compact.join '' # ROUTES TODO: This can be called directly, so script_name should probably be set in the routes rewritten_url << (options[:trailing_slash] ? path.sub(/\?|\z/) { "/" + $& } : path) diff --git a/actionpack/test/dispatch/url_generation_test.rb b/actionpack/test/dispatch/url_generation_test.rb index f83651d583..d491be2f11 100644 --- a/actionpack/test/dispatch/url_generation_test.rb +++ b/actionpack/test/dispatch/url_generation_test.rb @@ -31,7 +31,7 @@ module TestUrlGeneration end test "the request's SCRIPT_NAME takes precedence over the routes'" do - get "/foo", {}, 'SCRIPT_NAME' => "/new" + get "/foo", {}, 'SCRIPT_NAME' => "/new", 'action_dispatch.routes' => Routes assert_equal "/new/foo", response.body end -- cgit v1.2.3 From b697ba9fd72ac8701747863b42082e59f13ba678 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 9 Jul 2010 10:25:10 +0200 Subject: Added some more tests for url generation between Engine and Application --- actionpack/lib/action_controller/metal/url_for.rb | 8 ++--- actionpack/test/dispatch/prefix_generation_test.rb | 38 ++++++++++++++++------ 2 files changed, 32 insertions(+), 14 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/metal/url_for.rb b/actionpack/lib/action_controller/metal/url_for.rb index ae628df81c..c1f1be3bef 100644 --- a/actionpack/lib/action_controller/metal/url_for.rb +++ b/actionpack/lib/action_controller/metal/url_for.rb @@ -5,10 +5,10 @@ module ActionController include ActionDispatch::Routing::UrlFor def url_options - options = {} - if respond_to?(:env) && env && _routes.equal?(env["action_dispatch.routes"]) - options[:script_name] = request.script_name - end + options = {} + if respond_to?(:env) && env && _routes.equal?(env["action_dispatch.routes"]) + options[:script_name] = request.script_name + end super.merge(options).reverse_merge( :host => request.host_with_port, diff --git a/actionpack/test/dispatch/prefix_generation_test.rb b/actionpack/test/dispatch/prefix_generation_test.rb index 6ceb07a4f1..af83ced5e9 100644 --- a/actionpack/test/dispatch/prefix_generation_test.rb +++ b/actionpack/test/dispatch/prefix_generation_test.rb @@ -11,7 +11,7 @@ module TestGenerationPrefix routes = ActionDispatch::Routing::RouteSet.new routes.draw do match "/posts/:id", :to => "inside_engine_generating#index", :as => :post - match "/bare_url_for", :to => "inside_engine_generating#bare_url_for", :as => :bare_url_for + match "/url_to_application", :to => "inside_engine_generating#url_to_application" end routes @@ -42,10 +42,6 @@ module TestGenerationPrefix def self.call(env) env['action_dispatch.routes'] = routes - - # the next to values should be set only in application - env['ORIGINAL_SCRIPT_NAME'] = env['SCRIPT_NAME'] - env['action_dispatch.parent_routes'] = routes routes.call(env) end end @@ -56,7 +52,7 @@ module TestGenerationPrefix render :text => post_path(:id => params[:id]) end - def bare_url_for + def url_to_application path = url_for( :routes => RailsApplication.routes, :controller => "outside_engine_generating", :action => "index", @@ -111,12 +107,23 @@ module TestGenerationPrefix end test "prepend prefix outside the engine" do + get "/generate" + assert_equal "/awesome/blog/posts/1", last_response.body + end + + test "prepend prefix outside the engine and use default_url_options[:script_name]" do + RailsApplication.routes.default_url_options = {:script_name => "/something"} + get "/generate" + assert_equal "/something/awesome/blog/posts/1", last_response.body + end + + test "give higher priority to default_url_options[:script_name]" do RailsApplication.routes.default_url_options = {:script_name => "/something"} - get "/generate", {}, 'SCRIPT_NAME' => "/something" + get "/generate", {}, 'SCRIPT_NAME' => "/foo" assert_equal "/something/awesome/blog/posts/1", last_response.body end - test "generating urls with options for both prefix and named_route" do + test "generating urls with options for prefix and named_route" do assert_equal "/pure-awesomness/blog/posts/3", post_path(:id => 3, :omg => "pure-awesomness") end @@ -129,9 +136,20 @@ module TestGenerationPrefix assert_equal "/awesome/blog/posts/42", Foo.new.foo end - test "passing :routes to url_for to change current routes" do + test "generating application's url from engine" do + get "/pure-awesomness/blog/url_to_application" + assert_equal "/generate", last_response.body + end + + test "generating application's url from engine with default_url_options[:script_name]" do + RailsApplication.routes.default_url_options = {:script_name => "/something"} + get "/pure-awesomness/blog/url_to_application" + assert_equal "/something/generate", last_response.body + end + + test "generating application's url from engine should give higher priority to default_url_options[:script_name]" do RailsApplication.routes.default_url_options = {:script_name => "/something"} - get "/pure-awesomness/blog/bare_url_for", {}, 'SCRIPT_NAME' => "/something" + get "/pure-awesomness/blog/url_to_application", {}, 'SCRIPT_NAME' => '/foo' assert_equal "/something/generate", last_response.body end -- cgit v1.2.3 From b53efd21059b9d829a6617fb5b2dd86754684c60 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 14 Jul 2010 00:46:42 +0200 Subject: Extended url_for to handle specifying which router should be used. A few examples: url_for Blog::Engine, :posts_path url_for Blog::Engine, @post url_for Blog::Engine, :action => "main", :controller => "index" --- .../action_dispatch/routing/polymorphic_routes.rb | 2 +- .../lib/action_dispatch/routing/route_set.rb | 24 +++--- actionpack/lib/action_dispatch/routing/url_for.rb | 45 +++++++---- actionpack/test/dispatch/url_for_test.rb | 52 +++++++++++++ actionpack/test/dispatch/url_generation_test.rb | 1 + actionpack/test/template/form_helper_test.rb | 90 ++++++++++------------ actionpack/test/template/test_test.rb | 2 +- 7 files changed, 136 insertions(+), 80 deletions(-) create mode 100644 actionpack/test/dispatch/url_for_test.rb (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb index fb2118a8d7..15ee7c8051 100644 --- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb +++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb @@ -111,7 +111,7 @@ module ActionDispatch args.last.kind_of?(Hash) ? args.last.merge!(url_options) : args << url_options end - send(named_route, *args) + url_for _routes.url_helpers.__send__("hash_for_#{named_route}", *args) end # Returns the path component of a URL for the given record. It uses diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 6f182ae652..c94b00257b 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -158,10 +158,17 @@ module ActionDispatch # We use module_eval to avoid leaks @module.module_eval <<-END_EVAL, __FILE__, __LINE__ + 1 - def #{selector}(options = nil) # def hash_for_users_url(options = nil) - options ? #{options.inspect}.merge(options) : #{options.inspect} # options ? {:only_path=>false}.merge(options) : {:only_path=>false} - end # end - protected :#{selector} # protected :hash_for_users_url + def #{selector}(*args) + options = args.extract_options! + + if args.any? + options[:_positional_args] = args + options[:_positional_keys] = #{route.segment_keys.inspect} + end + + options ? #{options.inspect}.merge(options) : #{options.inspect} + end + protected :#{selector} END_EVAL helpers << selector end @@ -185,14 +192,7 @@ module ActionDispatch @module.module_eval <<-END_EVAL, __FILE__, __LINE__ + 1 def #{selector}(*args) - options = #{hash_access_method}(args.extract_options!) - - if args.any? - options[:_positional_args] = args - options[:_positional_keys] = #{route.segment_keys.inspect} - end - - url_for(options) + url_for(#{hash_access_method}(*args)) end END_EVAL helpers << selector diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index 5da41df485..edcb7f9cbe 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -123,27 +123,40 @@ module ActionDispatch # url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :anchor => 'ok', :only_path => true # => '/tasks/testing#ok' # url_for :controller => 'tasks', :action => 'testing', :trailing_slash=>true # => 'http://somehost.org/tasks/testing/' # url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :number => '33' # => 'http://somehost.org/tasks/testing?number=33' - def url_for(options = nil) - case options - when String - options - when nil, Hash - routes = (options ? options.delete(:routes) : nil) || _routes - - _with_routes(routes) do - routes.url_for((options || {}).reverse_merge!(url_options).symbolize_keys) + def url_for(*args) + if args.first.respond_to?(:routes) + app = args.shift + _with_routes(app.routes) do + if args.first.is_a? Symbol + named_route = args.shift + url_for _routes.url_helpers.__send__("hash_for_#{named_route}", *args) + else + url_for(*args) + end end else - polymorphic_url(options) + options = args.first + case options + when String + options + when nil, Hash + routes = (options ? options.delete(:routes) : nil) || _routes + _with_routes(routes) do + routes.url_for((options || {}).reverse_merge!(url_options).symbolize_keys) + end + else + polymorphic_url(options) + end end end - def _with_routes(routes) - old_routes, @_routes = @_routes, routes - yield - ensure - @_routes = old_routes - end + protected + def _with_routes(routes) + old_routes, @_routes = @_routes, routes + yield + ensure + @_routes = old_routes + end end end end diff --git a/actionpack/test/dispatch/url_for_test.rb b/actionpack/test/dispatch/url_for_test.rb new file mode 100644 index 0000000000..3dc96d27d7 --- /dev/null +++ b/actionpack/test/dispatch/url_for_test.rb @@ -0,0 +1,52 @@ +require 'abstract_unit' + +module UrlForGeneration + class UrlForTest < ActionDispatch::IntegrationTest + + Routes = ActionDispatch::Routing::RouteSet.new + Routes.draw { match "/foo", :to => "my_route_generating#index", :as => :foo } + + class BlogEngine + def self.routes + @routes ||= begin + routes = ActionDispatch::Routing::RouteSet.new + routes.draw do + resources :posts + end + routes + end + end + end + + class Post + extend ActiveModel::Naming + + def to_param + "1" + end + + def self.model_name + klass = "Post" + def klass.name; self end + + ActiveModel::Name.new(klass) + end + end + + include Routes.url_helpers + + test "url_for with named url helpers" do + assert_equal "/posts", url_for(BlogEngine, :posts_path) + end + + test "url_for with polymorphic routes" do + assert_equal "http://www.example.com/posts/1", url_for(BlogEngine, Post.new) + end + + test "url_for with named url helper with arguments" do + assert_equal "/posts/1", url_for(BlogEngine, :post_path, 1) + assert_equal "/posts/1", url_for(BlogEngine, :post_path, :id => 1) + assert_equal "/posts/1.json", url_for(BlogEngine, :post_path, :id => 1, :format => :json) + end + end +end diff --git a/actionpack/test/dispatch/url_generation_test.rb b/actionpack/test/dispatch/url_generation_test.rb index d491be2f11..2b54bc62b0 100644 --- a/actionpack/test/dispatch/url_generation_test.rb +++ b/actionpack/test/dispatch/url_generation_test.rb @@ -41,3 +41,4 @@ module TestUrlGeneration end end end + diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb index 9a1fe01872..ec57b6a2ab 100644 --- a/actionpack/test/template/form_helper_test.rb +++ b/actionpack/test/template/form_helper_test.rb @@ -77,13 +77,35 @@ class FormHelperTest < ActionView::TestCase @post.written_on = Date.new(2004, 6, 15) end + Routes = ActionDispatch::Routing::RouteSet.new + Routes.draw do + resources :posts do + resources :comments + end + + namespace :admin do + resources :posts do + resources :comments + end + end + + match "/foo", :to => "controller#action" + root :to => "main#index" + end + + def _routes + Routes + end + + include Routes.url_helpers + def url_for(object) @url_for_options = object - if object.is_a?(Hash) - "http://www.example.com" - else - super + if object.is_a?(Hash) && object[:use_route].blank? && object[:controller].blank? + object.merge!(:controller => "main", :action => "index") end + object + super end def test_label @@ -628,7 +650,7 @@ class FormHelperTest < ActionView::TestCase end expected = - "
" + + "" + snowman + "" + "" + @@ -683,7 +705,7 @@ class FormHelperTest < ActionView::TestCase end end - expected = whole_form("http://www.example.com", "create-post", nil, "put") do + expected = whole_form("/", "create-post", nil, "put") do "" + "" + "" + @@ -702,7 +724,7 @@ class FormHelperTest < ActionView::TestCase end end - expected = whole_form("http://www.example.com", "create-post", nil, :method => "put", :remote => true) do + expected = whole_form("/", "create-post", nil, :method => "put", :remote => true) do "" + "" + "" + @@ -721,7 +743,7 @@ class FormHelperTest < ActionView::TestCase end end - expected = whole_form("http://www.example.com", nil, nil, :remote => true) do + expected = whole_form("/", nil, nil, :remote => true) do "" + "" + "" + @@ -738,7 +760,7 @@ class FormHelperTest < ActionView::TestCase concat f.check_box(:secret) end - expected = whole_form("http://www.example.com", "create-post") do + expected = whole_form("/", "create-post") do "" + "" + "" + @@ -1478,7 +1500,7 @@ class FormHelperTest < ActionView::TestCase end expected = - "" + + "" + snowman + "" + "" + @@ -1502,7 +1524,7 @@ class FormHelperTest < ActionView::TestCase end expected = - whole_form("http://www.example.com", "create-post") do + whole_form("/", "create-post") do "" + "" + "" @@ -1546,7 +1568,7 @@ class FormHelperTest < ActionView::TestCase txt << %{} end - def form_text(action = "http://www.example.com", id = nil, html_class = nil, remote = nil) + def form_text(action = "/", id = nil, html_class = nil, remote = nil) txt = %{} end - def whole_form(action = "http://www.example.com", id = nil, html_class = nil, options = nil) + def whole_form(action = "/", id = nil, html_class = nil, options = nil) contents = block_given? ? yield : "" if options.is_a?(Hash) @@ -1655,7 +1677,7 @@ class FormHelperTest < ActionView::TestCase assert_deprecated do form_for(:post, @post, :html => {:id => 'some_form', :class => 'some_class'}) do |f| end end - expected = whole_form("http://www.example.com", "some_form", "some_class") + expected = whole_form("/", "some_form", "some_class") assert_dom_equal expected, output_buffer end @@ -1710,14 +1732,14 @@ class FormHelperTest < ActionView::TestCase @comment.save form_for([@post, @comment]) {} - expected = whole_form(comment_path(@post, @comment), "edit_comment_1", "edit_comment", "put") + expected = whole_form(post_comment_path(@post, @comment), "edit_comment_1", "edit_comment", "put") assert_dom_equal expected, output_buffer end def test_form_for_with_new_object_in_list form_for([@post, @comment]) {} - expected = whole_form(comments_path(@post), "new_comment", "new_comment") + expected = whole_form(post_comments_path(@post), "new_comment", "new_comment") assert_dom_equal expected, output_buffer end @@ -1725,14 +1747,14 @@ class FormHelperTest < ActionView::TestCase @comment.save form_for([:admin, @post, @comment]) {} - expected = whole_form(admin_comment_path(@post, @comment), "edit_comment_1", "edit_comment", "put") + expected = whole_form(admin_post_comment_path(@post, @comment), "edit_comment_1", "edit_comment", "put") assert_dom_equal expected, output_buffer end def test_form_for_with_new_object_and_namespace_in_list form_for([:admin, @post, @comment]) {} - expected = whole_form(admin_comments_path(@post), "new_comment", "new_comment") + expected = whole_form(admin_post_comments_path(@post), "new_comment", "new_comment") assert_dom_equal expected, output_buffer end @@ -1749,38 +1771,6 @@ class FormHelperTest < ActionView::TestCase end protected - def comments_path(post) - "/posts/#{post.id}/comments" - end - alias_method :post_comments_path, :comments_path - - def comment_path(post, comment) - "/posts/#{post.id}/comments/#{comment.id}" - end - alias_method :post_comment_path, :comment_path - - def admin_comments_path(post) - "/admin/posts/#{post.id}/comments" - end - alias_method :admin_post_comments_path, :admin_comments_path - - def admin_comment_path(post, comment) - "/admin/posts/#{post.id}/comments/#{comment.id}" - end - alias_method :admin_post_comment_path, :admin_comment_path - - def posts_path - "/posts" - end - - def post_path(post, options = {}) - if options[:format] - "/posts/#{post.id}.#{options[:format]}" - else - "/posts/#{post.id}" - end - end - def protect_against_forgery? false end diff --git a/actionpack/test/template/test_test.rb b/actionpack/test/template/test_test.rb index 68e790cf46..20c96824d6 100644 --- a/actionpack/test/template/test_test.rb +++ b/actionpack/test/template/test_test.rb @@ -39,7 +39,7 @@ class PeopleHelperTest < ActionView::TestCase with_test_route_set do person = mock(:name => "David") person.class.extend ActiveModel::Naming - expects(:mocha_mock_path).with(person).returns("/people/1") + _routes.url_helpers.expects(:hash_for_mocha_mock_path).with(person).returns("/people/1") assert_equal 'David', link_to_person(person) end end -- cgit v1.2.3 From 233be6572c96087192885924c6658a15d01a2a1b Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 14 Jul 2010 09:17:24 +0200 Subject: Ensure that env is always available in controllers --- actionpack/lib/action_controller/metal.rb | 6 +++++- actionpack/lib/action_controller/metal/url_for.rb | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb index 96ac138ba3..def28a0054 100644 --- a/actionpack/lib/action_controller/metal.rb +++ b/actionpack/lib/action_controller/metal.rb @@ -52,7 +52,11 @@ module ActionController class Metal < AbstractController::Base abstract! - attr_internal :env + attr_internal_writer :env + + def env + @_env ||= {} + end # Returns the last part of the controller's name, underscored, without the ending # Controller. For instance, PostsController returns posts. diff --git a/actionpack/lib/action_controller/metal/url_for.rb b/actionpack/lib/action_controller/metal/url_for.rb index c1f1be3bef..e7eb7485c4 100644 --- a/actionpack/lib/action_controller/metal/url_for.rb +++ b/actionpack/lib/action_controller/metal/url_for.rb @@ -6,7 +6,7 @@ module ActionController def url_options options = {} - if respond_to?(:env) && env && _routes.equal?(env["action_dispatch.routes"]) + if _routes.equal?(env["action_dispatch.routes"]) options[:script_name] = request.script_name end -- cgit v1.2.3 From 229a868264a1dd5f4441f4b82ccf2a51cf83511d Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 14 Jul 2010 10:20:30 +0200 Subject: Use new url_for API instead of including routes.url_helpers --- actionpack/test/dispatch/prefix_generation_test.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'actionpack') diff --git a/actionpack/test/dispatch/prefix_generation_test.rb b/actionpack/test/dispatch/prefix_generation_test.rb index af83ced5e9..c681642eda 100644 --- a/actionpack/test/dispatch/prefix_generation_test.rb +++ b/actionpack/test/dispatch/prefix_generation_test.rb @@ -47,9 +47,8 @@ module TestGenerationPrefix end class ::InsideEngineGeneratingController < ActionController::Base - include BlogEngine.routes.url_helpers def index - render :text => post_path(:id => params[:id]) + render :text => url_for(BlogEngine, :post_path, :id => params[:id]) end def url_to_application @@ -64,7 +63,7 @@ module TestGenerationPrefix class ::OutsideEngineGeneratingController < ActionController::Base include BlogEngine.routes.url_helpers def index - render :text => post_path(:id => 1) + render :text => url_for(BlogEngine, :post_path, :id => 1) end end -- cgit v1.2.3 From e9791bec823e42372eca095b946c93c1712a0613 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 15 Jul 2010 01:18:02 +0200 Subject: Routes refactoring: * added more tests for prefix generation * fixed bug with generating host for both prefix and url * refactored url_for method * organized tests for prefix generation --- actionpack/lib/action_dispatch/routing/mapper.rb | 3 +- .../lib/action_dispatch/routing/route_set.rb | 2 +- actionpack/lib/action_dispatch/routing/url_for.rb | 10 +- actionpack/test/dispatch/prefix_generation_test.rb | 117 +++++++++++++-------- 4 files changed, 77 insertions(+), 55 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 0e138524cd..88152ac290 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -288,8 +288,7 @@ module ActionDispatch _router = @set app.routes.class_eval do define_method :_generate_prefix do |options| - keys = _route.segment_keys + ActionDispatch::Routing::RouteSet::RESERVED_OPTIONS - prefix_options = options.slice(*keys) + prefix_options = options.slice(*_route.segment_keys) # we must actually delete prefix segment keys to avoid passing them to next url_for _route.segment_keys.each { |k| options.delete(k) } _router.url_helpers.send("#{name}_path", prefix_options) diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index c94b00257b..b3945a4963 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -452,7 +452,7 @@ module ActionDispatch Generator.new(options, recall, self, extras).generate end - RESERVED_OPTIONS = [:anchor, :params, :only_path, :host, :protocol, :port, :trailing_slash, :script_name, :routes] + RESERVED_OPTIONS = [:anchor, :params, :only_path, :host, :protocol, :port, :trailing_slash, :script_name] def _generate_prefix(options = {}) nil diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index edcb7f9cbe..30b456f3df 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -123,19 +123,17 @@ module ActionDispatch # url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :anchor => 'ok', :only_path => true # => '/tasks/testing#ok' # url_for :controller => 'tasks', :action => 'testing', :trailing_slash=>true # => 'http://somehost.org/tasks/testing/' # url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :number => '33' # => 'http://somehost.org/tasks/testing?number=33' - def url_for(*args) - if args.first.respond_to?(:routes) - app = args.shift - _with_routes(app.routes) do + def url_for(options = nil, *args) + if options.respond_to?(:routes) + _with_routes(options.routes) do if args.first.is_a? Symbol named_route = args.shift - url_for _routes.url_helpers.__send__("hash_for_#{named_route}", *args) + url_for _routes.url_helpers.send("hash_for_#{named_route}", *args) else url_for(*args) end end else - options = args.first case options when String options diff --git a/actionpack/test/dispatch/prefix_generation_test.rb b/actionpack/test/dispatch/prefix_generation_test.rb index c681642eda..2eb592c8d0 100644 --- a/actionpack/test/dispatch/prefix_generation_test.rb +++ b/actionpack/test/dispatch/prefix_generation_test.rb @@ -10,7 +10,8 @@ module TestGenerationPrefix @routes ||= begin routes = ActionDispatch::Routing::RouteSet.new routes.draw do - match "/posts/:id", :to => "inside_engine_generating#index", :as => :post + match "/posts/:id", :to => "inside_engine_generating#show", :as => :post + match "/posts", :to => "inside_engine_generating#index", :as => :posts match "/url_to_application", :to => "inside_engine_generating#url_to_application" end @@ -47,13 +48,19 @@ module TestGenerationPrefix end class ::InsideEngineGeneratingController < ActionController::Base + include BlogEngine.routes.url_helpers + def index - render :text => url_for(BlogEngine, :post_path, :id => params[:id]) + render :text => posts_path + end + + def show + render :text => post_path(:id => params[:id]) end def url_to_application - path = url_for( :routes => RailsApplication.routes, - :controller => "outside_engine_generating", + path = url_for( RailsApplication, + :controller => "outside_engine_generating", :action => "index", :only_path => true) render :text => path @@ -61,100 +68,118 @@ module TestGenerationPrefix end class ::OutsideEngineGeneratingController < ActionController::Base - include BlogEngine.routes.url_helpers def index render :text => url_for(BlogEngine, :post_path, :id => 1) end end - class Foo + class EngineObject include ActionDispatch::Routing::UrlFor include BlogEngine.routes.url_helpers - - def foo - post_path(42) - end end - class Bar + class AppObject include ActionDispatch::Routing::UrlFor include RailsApplication.routes.url_helpers - - def bar - root_path - end end - RailsApplication.routes # force draw - include BlogEngine.routes.url_helpers + # force draw + RailsApplication.routes def app RailsApplication end + def engine_object + @engine_object ||= EngineObject.new + end + + def app_object + @app_object ||= AppObject.new + end + def setup RailsApplication.routes.default_url_options = {} end - test "generating URL with prefix" do - assert_equal "/awesome/blog/posts/1", post_path(:id => 1) + # Inside Engine + test "[ENGINE] generating engine's url use SCRIPT_NAME from request" do + get "/pure-awesomeness/blog/posts/1" + assert_equal "/pure-awesomeness/blog/posts/1", last_response.body end - test "use SCRIPT_NAME inside the engine" do - get "/pure-awesomness/blog/posts/1" - assert_equal "/pure-awesomness/blog/posts/1", last_response.body + test "[ENGINE] generating application's url never uses SCRIPT_NAME from request" do + get "/pure-awesomeness/blog/url_to_application" + assert_equal "/generate", last_response.body end - test "prepend prefix outside the engine" do + test "[ENGINE] generating application's url includes default_url_options[:script_name]" do + RailsApplication.routes.default_url_options = {:script_name => "/something"} + get "/pure-awesomeness/blog/url_to_application" + assert_equal "/something/generate", last_response.body + end + + test "[ENGINE] generating application's url should give higher priority to default_url_options[:script_name]" do + RailsApplication.routes.default_url_options = {:script_name => "/something"} + get "/pure-awesomeness/blog/url_to_application", {}, 'SCRIPT_NAME' => '/foo' + assert_equal "/something/generate", last_response.body + end + + # Inside Application + test "[APP] generating engine's route includes prefix" do get "/generate" assert_equal "/awesome/blog/posts/1", last_response.body end - test "prepend prefix outside the engine and use default_url_options[:script_name]" do + test "[APP] generating engine's route includes default_url_options[:script_name]" do RailsApplication.routes.default_url_options = {:script_name => "/something"} get "/generate" assert_equal "/something/awesome/blog/posts/1", last_response.body end - test "give higher priority to default_url_options[:script_name]" do + test "[APP] generating engine's route should give higher priority to default_url_options[:script_name]" do RailsApplication.routes.default_url_options = {:script_name => "/something"} get "/generate", {}, 'SCRIPT_NAME' => "/foo" assert_equal "/something/awesome/blog/posts/1", last_response.body end - test "generating urls with options for prefix and named_route" do - assert_equal "/pure-awesomness/blog/posts/3", post_path(:id => 3, :omg => "pure-awesomness") + # Inside any Object + test "[OBJECT] generating engine's route includes prefix" do + assert_equal "/awesome/blog/posts/1", engine_object.post_path(:id => 1) end - test "generating urls with url_for should prepend the prefix" do - path = BlogEngine.routes.url_for(:omg => 'omg', :controller => "inside_engine_generating", :action => "index", :id => 1, :only_path => true) - assert_equal "/omg/blog/posts/1", path + test "[OBJECT] generating engine's route includes dynamic prefix" do + assert_equal "/pure-awesomeness/blog/posts/3", engine_object.post_path(:id => 3, :omg => "pure-awesomeness") end - test "generating urls from a regular class" do - assert_equal "/awesome/blog/posts/42", Foo.new.foo + test "[OBJECT] generating engine's route includes default_url_options[:script_name]" do + RailsApplication.routes.default_url_options = {:script_name => "/something"} + assert_equal "/something/pure-awesomeness/blog/posts/3", engine_object.post_path(:id => 3, :omg => "pure-awesomeness") end - test "generating application's url from engine" do - get "/pure-awesomness/blog/url_to_application" - assert_equal "/generate", last_response.body + test "[OBJECT] generating application's route" do + assert_equal "/", app_object.root_path end - test "generating application's url from engine with default_url_options[:script_name]" do + test "[OBJECT] generating application's route includes default_url_options[:script_name]" do RailsApplication.routes.default_url_options = {:script_name => "/something"} - get "/pure-awesomness/blog/url_to_application" - assert_equal "/something/generate", last_response.body + assert_equal "/something/", app_object.root_path end - test "generating application's url from engine should give higher priority to default_url_options[:script_name]" do - RailsApplication.routes.default_url_options = {:script_name => "/something"} - get "/pure-awesomness/blog/url_to_application", {}, 'SCRIPT_NAME' => '/foo' - assert_equal "/something/generate", last_response.body - end + test "[OBJECT] generating engine's route with url_for" do + path = engine_object.url_for(BlogEngine, + :controller => "inside_engine_generating", + :action => "show", + :only_path => true, + :omg => "omg", + :id => 1) + assert_equal "/omg/blog/posts/1", path - test "using default_url_options[:script_name] in regular classes" do - RailsApplication.routes.default_url_options = {:script_name => "/something"} - assert_equal "/something/", Bar.new.bar + path = engine_object.url_for(BlogEngine, :posts_path) + assert_equal "/awesome/blog/posts", path + + path = engine_object.url_for(BlogEngine, :posts_url, :host => "example.com") + assert_equal "http://example.com/awesome/blog/posts", path end end end -- cgit v1.2.3 From 6c95e0f879aafa5921cd7898d5951b9a926d3c9a Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sun, 18 Jul 2010 19:49:51 +0200 Subject: Add mounted_helpers to routes mounted_helpers are a bit similar to url_helpers. They're automatically included in controllers for Rails.application and each of mounted Engines. Mounted helper allows to call url_for and named helpers for given application. Given Blog::Engine mounted as blog_engine, there are 2 helpers defined: app and blog_engine. You can call routes for app and engine using those helpers: app.root_url app.url_for(:controller => "foo") blog_engine.posts_path blog_engine.url_for(@post) --- actionpack/lib/abstract_controller/rendering.rb | 1 + actionpack/lib/action_controller/railtie.rb | 3 +- .../lib/action_controller/railties/url_helpers.rb | 26 +++++++ actionpack/lib/action_dispatch/routing/mapper.rb | 5 +- .../lib/action_dispatch/routing/route_set.rb | 59 +++++++++++++++ actionpack/lib/action_dispatch/routing/url_for.rb | 28 ++------ actionpack/test/dispatch/prefix_generation_test.rb | 84 ++++++++++++++++++---- actionpack/test/dispatch/url_for_test.rb | 52 -------------- 8 files changed, 168 insertions(+), 90 deletions(-) create mode 100644 actionpack/lib/action_controller/railties/url_helpers.rb delete mode 100644 actionpack/test/dispatch/url_for_test.rb (limited to 'actionpack') diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb index b81d5954eb..5d9b35d297 100644 --- a/actionpack/lib/abstract_controller/rendering.rb +++ b/actionpack/lib/abstract_controller/rendering.rb @@ -52,6 +52,7 @@ module AbstractController if controller.respond_to?(:_routes) include controller._routes.url_helpers + include controller._routes.mounted_helpers end # TODO: Fix RJS to not require this diff --git a/actionpack/lib/action_controller/railtie.rb b/actionpack/lib/action_controller/railtie.rb index cd2dfafbe6..7496dd57b2 100644 --- a/actionpack/lib/action_controller/railtie.rb +++ b/actionpack/lib/action_controller/railtie.rb @@ -51,6 +51,7 @@ module ActionController ActiveSupport.on_load(:action_controller) do include app.routes.url_helpers + include app.routes.mounted_helpers(:app) options.each { |k,v| send("#{k}=", v) } end end @@ -63,4 +64,4 @@ module ActionController ActionController::Routing::Routes = proxy end end -end \ No newline at end of file +end diff --git a/actionpack/lib/action_controller/railties/url_helpers.rb b/actionpack/lib/action_controller/railties/url_helpers.rb new file mode 100644 index 0000000000..3e6f211cda --- /dev/null +++ b/actionpack/lib/action_controller/railties/url_helpers.rb @@ -0,0 +1,26 @@ +module ActionController + module Railties + + module UrlHelpers + def self.with(routes) + Module.new do + define_method(:inherited) do |klass| + super(klass) + klass.send(:include, routes.url_helpers) + end + end + end + end + + module MountedHelpers + def self.with(routes, name = nil) + Module.new do + define_method(:inherited) do |klass| + super(klass) + klass.send(:include, routes.mounted_helpers(name)) + end + end + end + end + end +end diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 88152ac290..ef1bee106a 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -285,13 +285,14 @@ module ActionDispatch return unless app.respond_to?(:routes) _route = @set.named_routes.routes[name.to_sym] - _router = @set + _routes = @set + app.routes.define_mounted_helper(name) app.routes.class_eval do define_method :_generate_prefix do |options| prefix_options = options.slice(*_route.segment_keys) # we must actually delete prefix segment keys to avoid passing them to next url_for _route.segment_keys.each { |k| options.delete(k) } - _router.url_helpers.send("#{name}_path", prefix_options) + _routes.url_helpers.send("#{name}_path", prefix_options) end end end diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index b3945a4963..0f8bb5c504 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -261,6 +261,65 @@ module ActionDispatch named_routes.install(destinations, regenerate_code) end + class RoutesProxy + include ActionDispatch::Routing::UrlFor + + %w(url_options polymorphic_url polymorphic_path).each do |method| + self.class_eval <<-RUBY, __FILE__, __LINE__ +1 + def #{method}(*args) + scope.send(:_with_routes, routes) do + scope.#{method}(*args) + end + end + RUBY + end + + attr_accessor :scope, :routes + alias :_routes :routes + + def initialize(routes, scope) + @routes, @scope = routes, scope + end + + def method_missing(method, *args) + if routes.url_helpers.respond_to?(method) + self.class.class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{method}(*args) + options = args.extract_options! + args << url_options.merge((options || {}).symbolize_keys) + routes.url_helpers.#{method}(*args) + end + RUBY + send(method, *args) + else + super + end + end + end + + module MountedHelpers + end + + def mounted_helpers(name = nil) + define_mounted_helper(name) if name + MountedHelpers + end + + def define_mounted_helper(name, helpers = nil) + routes = self + MountedHelpers.class_eval do + define_method "_#{name}" do + RoutesProxy.new(routes, self) + end + end + + MountedHelpers.class_eval <<-RUBY + def #{name} + @#{name} ||= _#{name} + end + RUBY + end + def url_helpers @url_helpers ||= begin routes = self diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index 30b456f3df..19db730b6a 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -123,28 +123,14 @@ module ActionDispatch # url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :anchor => 'ok', :only_path => true # => '/tasks/testing#ok' # url_for :controller => 'tasks', :action => 'testing', :trailing_slash=>true # => 'http://somehost.org/tasks/testing/' # url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :number => '33' # => 'http://somehost.org/tasks/testing?number=33' - def url_for(options = nil, *args) - if options.respond_to?(:routes) - _with_routes(options.routes) do - if args.first.is_a? Symbol - named_route = args.shift - url_for _routes.url_helpers.send("hash_for_#{named_route}", *args) - else - url_for(*args) - end - end + def url_for(options = nil) + case options + when String + options + when nil, Hash + _routes.url_for((options || {}).reverse_merge!(url_options).symbolize_keys) else - case options - when String - options - when nil, Hash - routes = (options ? options.delete(:routes) : nil) || _routes - _with_routes(routes) do - routes.url_for((options || {}).reverse_merge!(url_options).symbolize_keys) - end - else - polymorphic_url(options) - end + polymorphic_url(options) end end diff --git a/actionpack/test/dispatch/prefix_generation_test.rb b/actionpack/test/dispatch/prefix_generation_test.rb index 2eb592c8d0..7fe11447b8 100644 --- a/actionpack/test/dispatch/prefix_generation_test.rb +++ b/actionpack/test/dispatch/prefix_generation_test.rb @@ -13,6 +13,7 @@ module TestGenerationPrefix match "/posts/:id", :to => "inside_engine_generating#show", :as => :post match "/posts", :to => "inside_engine_generating#index", :as => :posts match "/url_to_application", :to => "inside_engine_generating#url_to_application" + match "/polymorphic_path_for_engine", :to => "inside_engine_generating#polymorphic_path_for_engine" end routes @@ -31,9 +32,11 @@ module TestGenerationPrefix routes = ActionDispatch::Routing::RouteSet.new routes.draw do scope "/:omg", :omg => "awesome" do - mount BlogEngine => "/blog" + mount BlogEngine => "/blog", :as => "blog_engine" end match "/generate", :to => "outside_engine_generating#index" + match "/polymorphic_path_for_engine", :to => "outside_engine_generating#polymorphic_path_for_engine" + match "/polymorphic_with_url_for", :to => "outside_engine_generating#polymorphic_with_url_for" root :to => "outside_engine_generating#index" end @@ -47,8 +50,27 @@ module TestGenerationPrefix end end + # force draw + RailsApplication.routes + + class Post + extend ActiveModel::Naming + + def to_param + "1" + end + + def self.model_name + klass = "Post" + def klass.name; self end + + ActiveModel::Name.new(klass) + end + end + class ::InsideEngineGeneratingController < ActionController::Base include BlogEngine.routes.url_helpers + include RailsApplication.routes.mounted_helpers(:app) def index render :text => posts_path @@ -59,17 +81,30 @@ module TestGenerationPrefix end def url_to_application - path = url_for( RailsApplication, - :controller => "outside_engine_generating", - :action => "index", - :only_path => true) + path = app.url_for( :controller => "outside_engine_generating", + :action => "index", + :only_path => true) render :text => path end + + def polymorphic_path_for_engine + render :text => polymorphic_path(Post.new) + end end class ::OutsideEngineGeneratingController < ActionController::Base + include BlogEngine.routes.mounted_helpers + def index - render :text => url_for(BlogEngine, :post_path, :id => 1) + render :text => blog_engine.post_path(:id => 1) + end + + def polymorphic_path_for_engine + render :text => blog_engine.polymorphic_path(Post.new) + end + + def polymorphic_with_url_for + render :text => blog_engine.url_for(Post.new) end end @@ -83,9 +118,6 @@ module TestGenerationPrefix include RailsApplication.routes.url_helpers end - # force draw - RailsApplication.routes - def app RailsApplication end @@ -124,7 +156,12 @@ module TestGenerationPrefix get "/pure-awesomeness/blog/url_to_application", {}, 'SCRIPT_NAME' => '/foo' assert_equal "/something/generate", last_response.body end - + + test "[ENGINE] generating engine's url with polymorphic path" do + get "/pure-awesomeness/blog/polymorphic_path_for_engine" + assert_equal "/pure-awesomeness/blog/posts/1", last_response.body + end + # Inside Application test "[APP] generating engine's route includes prefix" do get "/generate" @@ -143,6 +180,16 @@ module TestGenerationPrefix assert_equal "/something/awesome/blog/posts/1", last_response.body end + test "[APP] generating engine's url with polymorphic path" do + get "/polymorphic_path_for_engine" + assert_equal "/awesome/blog/posts/1", last_response.body + end + + test "[APP] generating engine's url with url_for(@post)" do + get "/polymorphic_with_url_for" + assert_equal "http://example.org/awesome/blog/posts/1", last_response.body + end + # Inside any Object test "[OBJECT] generating engine's route includes prefix" do assert_equal "/awesome/blog/posts/1", engine_object.post_path(:id => 1) @@ -167,19 +214,28 @@ module TestGenerationPrefix end test "[OBJECT] generating engine's route with url_for" do - path = engine_object.url_for(BlogEngine, - :controller => "inside_engine_generating", + path = engine_object.url_for(:controller => "inside_engine_generating", :action => "show", :only_path => true, :omg => "omg", :id => 1) assert_equal "/omg/blog/posts/1", path + end - path = engine_object.url_for(BlogEngine, :posts_path) + test "[OBJECT] generating engine's route with named helpers" do + path = engine_object.posts_path assert_equal "/awesome/blog/posts", path - path = engine_object.url_for(BlogEngine, :posts_url, :host => "example.com") + path = engine_object.posts_url(:host => "example.com") assert_equal "http://example.com/awesome/blog/posts", path end + + test "[OBJECT] generating engine's route with polymorphic_url" do + path = engine_object.polymorphic_path(Post.new) + assert_equal "/awesome/blog/posts/1", path + + path = engine_object.polymorphic_url(Post.new, :host => "www.example.com") + assert_equal "http://www.example.com/awesome/blog/posts/1", path + end end end diff --git a/actionpack/test/dispatch/url_for_test.rb b/actionpack/test/dispatch/url_for_test.rb deleted file mode 100644 index 3dc96d27d7..0000000000 --- a/actionpack/test/dispatch/url_for_test.rb +++ /dev/null @@ -1,52 +0,0 @@ -require 'abstract_unit' - -module UrlForGeneration - class UrlForTest < ActionDispatch::IntegrationTest - - Routes = ActionDispatch::Routing::RouteSet.new - Routes.draw { match "/foo", :to => "my_route_generating#index", :as => :foo } - - class BlogEngine - def self.routes - @routes ||= begin - routes = ActionDispatch::Routing::RouteSet.new - routes.draw do - resources :posts - end - routes - end - end - end - - class Post - extend ActiveModel::Naming - - def to_param - "1" - end - - def self.model_name - klass = "Post" - def klass.name; self end - - ActiveModel::Name.new(klass) - end - end - - include Routes.url_helpers - - test "url_for with named url helpers" do - assert_equal "/posts", url_for(BlogEngine, :posts_path) - end - - test "url_for with polymorphic routes" do - assert_equal "http://www.example.com/posts/1", url_for(BlogEngine, Post.new) - end - - test "url_for with named url helper with arguments" do - assert_equal "/posts/1", url_for(BlogEngine, :post_path, 1) - assert_equal "/posts/1", url_for(BlogEngine, :post_path, :id => 1) - assert_equal "/posts/1.json", url_for(BlogEngine, :post_path, :id => 1, :format => :json) - end - end -end -- cgit v1.2.3 From 1e6612ef80b019e602231e6833c934817cccb858 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Mon, 19 Jul 2010 13:32:34 +0200 Subject: Ensure that url_helpers included after application's ones have higher priority --- actionpack/test/dispatch/prefix_generation_test.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'actionpack') diff --git a/actionpack/test/dispatch/prefix_generation_test.rb b/actionpack/test/dispatch/prefix_generation_test.rb index 7fe11447b8..3b47a1b72d 100644 --- a/actionpack/test/dispatch/prefix_generation_test.rb +++ b/actionpack/test/dispatch/prefix_generation_test.rb @@ -14,6 +14,7 @@ module TestGenerationPrefix match "/posts", :to => "inside_engine_generating#index", :as => :posts match "/url_to_application", :to => "inside_engine_generating#url_to_application" match "/polymorphic_path_for_engine", :to => "inside_engine_generating#polymorphic_path_for_engine" + match "/conflicting_url", :to => "inside_engine_generating#conflicting" end routes @@ -37,6 +38,7 @@ module TestGenerationPrefix match "/generate", :to => "outside_engine_generating#index" match "/polymorphic_path_for_engine", :to => "outside_engine_generating#polymorphic_path_for_engine" match "/polymorphic_with_url_for", :to => "outside_engine_generating#polymorphic_with_url_for" + match "/conflicting_url", :to => "outside_engine_generating#conflicting" root :to => "outside_engine_generating#index" end @@ -90,6 +92,10 @@ module TestGenerationPrefix def polymorphic_path_for_engine render :text => polymorphic_path(Post.new) end + + def conflicting + render :text => "engine" + end end class ::OutsideEngineGeneratingController < ActionController::Base @@ -106,6 +112,10 @@ module TestGenerationPrefix def polymorphic_with_url_for render :text => blog_engine.url_for(Post.new) end + + def conflicting + render :text => "application" + end end class EngineObject @@ -162,6 +172,11 @@ module TestGenerationPrefix assert_equal "/pure-awesomeness/blog/posts/1", last_response.body end + test "[ENGINE] url_helpers from engine have higher priotity than application's url_helpers" do + get "/awesome/blog/conflicting_url" + assert_equal "engine", last_response.body + end + # Inside Application test "[APP] generating engine's route includes prefix" do get "/generate" -- cgit v1.2.3 From a132229d7b4382d9ffe8847fa58f469cb8f2ecfc Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 22 Jul 2010 22:11:32 +0200 Subject: Added ability to set asset_path for engines --- .../lib/action_dispatch/testing/test_request.rb | 2 +- .../lib/action_view/helpers/asset_tag_helper.rb | 3 +++ actionpack/test/template/asset_tag_helper_test.rb | 23 ++++++++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/testing/test_request.rb b/actionpack/lib/action_dispatch/testing/test_request.rb index b3e67f6e36..c587a36930 100644 --- a/actionpack/lib/action_dispatch/testing/test_request.rb +++ b/actionpack/lib/action_dispatch/testing/test_request.rb @@ -10,7 +10,7 @@ module ActionDispatch end def initialize(env = {}) - env = Rails.application.env_defaults.merge(env) if defined?(Rails.application) + env = Rails.application.env_config.merge(env) if defined?(Rails.application) super(DEFAULT_ENV.merge(env)) self.host = 'test.host' diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb index a3c43d3e93..3329a8b368 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb @@ -727,6 +727,9 @@ module ActionView source += ".#{ext}" if rewrite_extension?(source, dir, ext) source = "/#{dir}/#{source}" unless source[0] == ?/ + if controller.respond_to?(:env) && controller.env["action_dispatch.asset_path"] + source = rewrite_asset_path(source, controller.env["action_dispatch.asset_path"]) + end source = rewrite_asset_path(source, config.asset_path) has_request = controller.respond_to?(:request) diff --git a/actionpack/test/template/asset_tag_helper_test.rb b/actionpack/test/template/asset_tag_helper_test.rb index 6d5e4893c4..2b83cfe1a9 100644 --- a/actionpack/test/template/asset_tag_helper_test.rb +++ b/actionpack/test/template/asset_tag_helper_test.rb @@ -387,6 +387,15 @@ class AssetTagHelperTest < ActionView::TestCase assert_equal %(Rails), image_tag("rails.png") end + def test_env_asset_path + @controller.config.asset_path = "/assets%s" + def @controller.env; @_env ||= {} end + @controller.env["action_dispatch.asset_path"] = "/omg%s" + + expected_path = "/assets/omg/images/rails.png" + assert_equal %(Rails), image_tag("rails.png") + end + def test_proc_asset_id @controller.config.asset_path = Proc.new do |asset_path| "/assets.v12345#{asset_path}" @@ -396,6 +405,20 @@ class AssetTagHelperTest < ActionView::TestCase assert_equal %(Rails), image_tag("rails.png") end + def test_env_proc_asset_path + @controller.config.asset_path = Proc.new do |asset_path| + "/assets.v12345#{asset_path}" + end + + def @controller.env; @_env ||= {} end + @controller.env["action_dispatch.asset_path"] = Proc.new do |asset_path| + "/omg#{asset_path}" + end + + expected_path = "/assets.v12345/omg/images/rails.png" + assert_equal %(Rails), image_tag("rails.png") + end + def test_image_tag_interpreting_email_cid_correctly # An inline image has no need for an alt tag to be automatically generated from the cid: assert_equal '', image_tag("cid:thi%25%25sis@acontentid") -- cgit v1.2.3 From 4cd6f7752658f0ec13d082fa2ee2a6f766410645 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sat, 24 Jul 2010 17:43:33 +0200 Subject: We don't need delegating polymorphic_url and polymorphic_path anymore --- actionpack/lib/action_dispatch/routing/route_set.rb | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 0f8bb5c504..121e7c2c75 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -264,16 +264,6 @@ module ActionDispatch class RoutesProxy include ActionDispatch::Routing::UrlFor - %w(url_options polymorphic_url polymorphic_path).each do |method| - self.class_eval <<-RUBY, __FILE__, __LINE__ +1 - def #{method}(*args) - scope.send(:_with_routes, routes) do - scope.#{method}(*args) - end - end - RUBY - end - attr_accessor :scope, :routes alias :_routes :routes @@ -281,6 +271,12 @@ module ActionDispatch @routes, @scope = routes, scope end + def url_options + scope.send(:_with_routes, routes) do + scope.url_options + end + end + def method_missing(method, *args) if routes.url_helpers.respond_to?(method) self.class.class_eval <<-RUBY, __FILE__, __LINE__ + 1 -- cgit v1.2.3 From 0c1cd15470b6f953e1af8f47d072270b55474c31 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sat, 24 Jul 2010 17:43:50 +0200 Subject: to_param shoul return a string --- actionpack/test/lib/controller/fake_models.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/test/lib/controller/fake_models.rb b/actionpack/test/lib/controller/fake_models.rb index bf3e175f1f..37b200d57a 100644 --- a/actionpack/test/lib/controller/fake_models.rb +++ b/actionpack/test/lib/controller/fake_models.rb @@ -83,7 +83,7 @@ class Comment def to_key; id ? [id] : nil end def save; @id = 1; @post_id = 1 end def persisted?; @id.present? end - def to_param; @id; end + def to_param; @id.to_s; end def name @id.nil? ? "new #{self.class.name.downcase}" : "#{self.class.name.downcase} ##{@id}" end -- cgit v1.2.3 From bfccbc6df91a3c24bbf99262383c6f1e9069e1dd Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Mon, 26 Jul 2010 17:05:04 +0200 Subject: Add Rails::Railtie.railtie_name method to allow setting custom name for railtie --- actionpack/lib/action_dispatch/routing/mapper.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index ef1bee106a..b437d7a17d 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -277,8 +277,13 @@ module ActionDispatch private def app_name(app) return unless app.respond_to?(:routes) - class_name = app.class.is_a?(Class) ? app.name : app.class.name - ActiveSupport::Inflector.underscore(class_name).gsub("/", "_") + + if app.respond_to?(:railtie_name) + app.railtie_name + else + class_name = app.class.is_a?(Class) ? app.name : app.class.name + ActiveSupport::Inflector.underscore(class_name).gsub("/", "_") + end end def define_generate_prefix(app, name) -- cgit v1.2.3 From 401cd97923fb52c8f8c458b8cb276b338e0b20f3 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 29 Jul 2010 14:12:25 +0200 Subject: Modified ActionDispatch::Static to allow passing multiple roots --- .../lib/action_dispatch/middleware/static.rb | 60 +++++++++++++++++---- actionpack/test/dispatch/static_test.rb | 61 ++++++++++++++++++---- actionpack/test/fixtures/blog_public/.gitignore | 1 + actionpack/test/fixtures/blog_public/blog.html | 1 + actionpack/test/fixtures/blog_public/index.html | 1 + .../test/fixtures/blog_public/subdir/index.html | 1 + 6 files changed, 104 insertions(+), 21 deletions(-) create mode 100644 actionpack/test/fixtures/blog_public/.gitignore create mode 100644 actionpack/test/fixtures/blog_public/blog.html create mode 100644 actionpack/test/fixtures/blog_public/index.html create mode 100644 actionpack/test/fixtures/blog_public/subdir/index.html (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/middleware/static.rb b/actionpack/lib/action_dispatch/middleware/static.rb index d7e88a54e4..c2d686f514 100644 --- a/actionpack/lib/action_dispatch/middleware/static.rb +++ b/actionpack/lib/action_dispatch/middleware/static.rb @@ -2,11 +2,43 @@ require 'rack/utils' module ActionDispatch class Static + class FileHandler + def initialize(at, root) + @at = at.chomp("/") + @file_server = ::Rack::File.new(root) + end + + def file_exist?(path) + (path = full_readable_path(path)) && File.file?(path) + end + + def directory_exist?(path) + (path = full_readable_path(path)) && File.directory?(path) + end + + def call(env) + env["PATH_INFO"].gsub!(/^#{@at}/, "") + @file_server.call(env) + end + + private + def includes_path?(path) + @at == "" || path =~ /^#{@at}/ + end + + def full_readable_path(path) + return unless includes_path?(path) + path = path.gsub(/^#{@at}/, "") + File.join(@file_server.root, ::Rack::Utils.unescape(path)) + end + end + FILE_METHODS = %w(GET HEAD).freeze - def initialize(app, root) + def initialize(app, roots) @app = app - @file_server = ::Rack::File.new(root) + roots = normalize_roots(roots) + @file_handlers = file_handlers(roots) end def call(env) @@ -14,15 +46,15 @@ module ActionDispatch method = env['REQUEST_METHOD'] if FILE_METHODS.include?(method) - if file_exist?(path) - return @file_server.call(env) + if file_handler = file_exist?(path) + return file_handler.call(env) else cached_path = directory_exist?(path) ? "#{path}/index" : path cached_path += ::ActionController::Base.page_cache_extension - if file_exist?(cached_path) + if file_handler = file_exist?(cached_path) env['PATH_INFO'] = cached_path - return @file_server.call(env) + return file_handler.call(env) end end end @@ -32,13 +64,21 @@ module ActionDispatch private def file_exist?(path) - full_path = File.join(@file_server.root, ::Rack::Utils.unescape(path)) - File.file?(full_path) && File.readable?(full_path) + @file_handlers.detect { |f| f.file_exist?(path) } end def directory_exist?(path) - full_path = File.join(@file_server.root, ::Rack::Utils.unescape(path)) - File.directory?(full_path) && File.readable?(full_path) + @file_handlers.detect { |f| f.directory_exist?(path) } + end + + def normalize_roots(roots) + roots.is_a?(Hash) ? roots : { "/" => roots.chomp("/") } + end + + def file_handlers(roots) + roots.map do |at, root| + FileHandler.new(at, root) + end end end end diff --git a/actionpack/test/dispatch/static_test.rb b/actionpack/test/dispatch/static_test.rb index e6957bb0ea..2eb82fc5d8 100644 --- a/actionpack/test/dispatch/static_test.rb +++ b/actionpack/test/dispatch/static_test.rb @@ -1,28 +1,23 @@ require 'abstract_unit' -class StaticTest < ActiveSupport::TestCase - DummyApp = lambda { |env| - [200, {"Content-Type" => "text/plain"}, ["Hello, World!"]] - } - App = ActionDispatch::Static.new(DummyApp, "#{FIXTURE_LOAD_PATH}/public") - - test "serves dynamic content" do +module StaticTests + def test_serves_dynamic_content assert_equal "Hello, World!", get("/nofile") end - test "serves static index at root" do + def test_serves_static_index_at_root assert_equal "/index.html", get("/index.html") assert_equal "/index.html", get("/index") assert_equal "/index.html", get("/") end - test "serves static file in directory" do + def test_serves_static_file_in_directory assert_equal "/foo/bar.html", get("/foo/bar.html") assert_equal "/foo/bar.html", get("/foo/bar/") assert_equal "/foo/bar.html", get("/foo/bar") end - test "serves static index file in directory" do + def test_serves_static_index_file_in_directory assert_equal "/foo/index.html", get("/foo/index.html") assert_equal "/foo/index.html", get("/foo/") assert_equal "/foo/index.html", get("/foo") @@ -30,6 +25,50 @@ class StaticTest < ActiveSupport::TestCase private def get(path) - Rack::MockRequest.new(App).request("GET", path).body + Rack::MockRequest.new(@app).request("GET", path).body end end + +class StaticTest < ActiveSupport::TestCase + DummyApp = lambda { |env| + [200, {"Content-Type" => "text/plain"}, ["Hello, World!"]] + } + App = ActionDispatch::Static.new(DummyApp, "#{FIXTURE_LOAD_PATH}/public") + + def setup + @app = App + end + + include StaticTests +end + +class MultipleDirectorisStaticTest < ActiveSupport::TestCase + DummyApp = lambda { |env| + [200, {"Content-Type" => "text/plain"}, ["Hello, World!"]] + } + App = ActionDispatch::Static.new(DummyApp, + { "/" => "#{FIXTURE_LOAD_PATH}/public", + "/blog" => "#{FIXTURE_LOAD_PATH}/blog_public", + "/foo" => "#{FIXTURE_LOAD_PATH}/non_existing_dir" + }) + + def setup + @app = App + end + + include StaticTests + + test "serves files from other mounted directories" do + assert_equal "/blog/index.html", get("/blog/index.html") + assert_equal "/blog/index.html", get("/blog/index") + assert_equal "/blog/index.html", get("/blog/") + + assert_equal "/blog/blog.html", get("/blog/blog/") + assert_equal "/blog/blog.html", get("/blog/blog.html") + assert_equal "/blog/blog.html", get("/blog/blog") + + assert_equal "/blog/subdir/index.html", get("/blog/subdir/index.html") + assert_equal "/blog/subdir/index.html", get("/blog/subdir/") + assert_equal "/blog/subdir/index.html", get("/blog/subdir") + end +end diff --git a/actionpack/test/fixtures/blog_public/.gitignore b/actionpack/test/fixtures/blog_public/.gitignore new file mode 100644 index 0000000000..312e635ee6 --- /dev/null +++ b/actionpack/test/fixtures/blog_public/.gitignore @@ -0,0 +1 @@ +absolute/* diff --git a/actionpack/test/fixtures/blog_public/blog.html b/actionpack/test/fixtures/blog_public/blog.html new file mode 100644 index 0000000000..79ad44c010 --- /dev/null +++ b/actionpack/test/fixtures/blog_public/blog.html @@ -0,0 +1 @@ +/blog/blog.html \ No newline at end of file diff --git a/actionpack/test/fixtures/blog_public/index.html b/actionpack/test/fixtures/blog_public/index.html new file mode 100644 index 0000000000..2de3825481 --- /dev/null +++ b/actionpack/test/fixtures/blog_public/index.html @@ -0,0 +1 @@ +/blog/index.html \ No newline at end of file diff --git a/actionpack/test/fixtures/blog_public/subdir/index.html b/actionpack/test/fixtures/blog_public/subdir/index.html new file mode 100644 index 0000000000..517bded335 --- /dev/null +++ b/actionpack/test/fixtures/blog_public/subdir/index.html @@ -0,0 +1 @@ +/blog/subdir/index.html \ No newline at end of file -- cgit v1.2.3 From 2734d3819f4621bf797ea436d267b102deae67f7 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 29 Jul 2010 20:29:57 +0200 Subject: This is not needed --- .../lib/action_controller/railties/url_helpers.rb | 26 ---------------------- 1 file changed, 26 deletions(-) delete mode 100644 actionpack/lib/action_controller/railties/url_helpers.rb (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/railties/url_helpers.rb b/actionpack/lib/action_controller/railties/url_helpers.rb deleted file mode 100644 index 3e6f211cda..0000000000 --- a/actionpack/lib/action_controller/railties/url_helpers.rb +++ /dev/null @@ -1,26 +0,0 @@ -module ActionController - module Railties - - module UrlHelpers - def self.with(routes) - Module.new do - define_method(:inherited) do |klass| - super(klass) - klass.send(:include, routes.url_helpers) - end - end - end - end - - module MountedHelpers - def self.with(routes, name = nil) - Module.new do - define_method(:inherited) do |klass| - super(klass) - klass.send(:include, routes.mounted_helpers(name)) - end - end - end - end - end -end -- cgit v1.2.3 From 99131939316230065b4297573d080d1585e4e5a7 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sat, 31 Jul 2010 11:27:08 +0200 Subject: For view_context we need to initialize RoutesProxy in context of controller, not view, quick fix, I need to dig into it later --- actionpack/lib/action_dispatch/routing/route_set.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 121e7c2c75..c67b0199ce 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -301,11 +301,13 @@ module ActionDispatch MountedHelpers end - def define_mounted_helper(name, helpers = nil) + def define_mounted_helper(name) + return if MountedHelpers.method_defined?(name) + routes = self MountedHelpers.class_eval do define_method "_#{name}" do - RoutesProxy.new(routes, self) + RoutesProxy.new(routes, (self.respond_to?(:controller) ? controller : self)) end end -- cgit v1.2.3 From c7664d112fadb313146da33f48d1da318f249927 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 30 Jul 2010 07:14:48 +0200 Subject: Include application's helpers and router helpers by default, but include engine's ones for controllers inside isolated namespace --- actionpack/lib/action_controller/base.rb | 8 ++++++-- actionpack/lib/action_controller/metal/helpers.rb | 6 +++++- actionpack/lib/action_controller/railtie.rb | 3 ++- .../lib/action_controller/railties/routes_helpers.rb | 17 +++++++++++++++++ 4 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 actionpack/lib/action_controller/railties/routes_helpers.rb (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 7a1464c2aa..3560ac5b8c 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -223,9 +223,13 @@ module ActionController def self.inherited(klass) super - klass.helper :all if klass.superclass == ActionController::Base + if namespace = klass.parents.detect {|m| m.respond_to?(:_railtie) } + klass.helper(all_helpers_from_path(namespace._railtie.config.paths.app.helpers.to_a)) + else + klass.helper :all if klass.superclass == ActionController::Base + end end ActiveSupport.run_load_hooks(:action_controller, self) end -end \ No newline at end of file +end diff --git a/actionpack/lib/action_controller/metal/helpers.rb b/actionpack/lib/action_controller/metal/helpers.rb index 4b6897c5dd..c5d7842db3 100644 --- a/actionpack/lib/action_controller/metal/helpers.rb +++ b/actionpack/lib/action_controller/metal/helpers.rb @@ -101,8 +101,12 @@ module ActionController # Extract helper names from files in app/helpers/**/*_helper.rb def all_application_helpers + all_helpers_from_path(helpers_path) + end + + def all_helpers_from_path(path) helpers = [] - Array.wrap(helpers_path).each do |path| + Array.wrap(path).each do |path| extract = /^#{Regexp.quote(path.to_s)}\/?(.*)_helper.rb$/ helpers += Dir["#{path}/**/*_helper.rb"].map { |file| file.sub(extract, '\1') } end diff --git a/actionpack/lib/action_controller/railtie.rb b/actionpack/lib/action_controller/railtie.rb index 7496dd57b2..23622b19e8 100644 --- a/actionpack/lib/action_controller/railtie.rb +++ b/actionpack/lib/action_controller/railtie.rb @@ -4,6 +4,7 @@ require "action_dispatch/railtie" require "action_view/railtie" require "active_support/deprecation/proxy_wrappers" require "active_support/deprecation" +require "action_controller/railties/routes_helpers" module ActionController class Railtie < Rails::Railtie @@ -50,7 +51,7 @@ module ActionController options.helpers_path ||= paths.app.helpers.to_a ActiveSupport.on_load(:action_controller) do - include app.routes.url_helpers + extend ::ActionController::Railties::RoutesHelpers.with(app.routes) include app.routes.mounted_helpers(:app) options.each { |k,v| send("#{k}=", v) } end diff --git a/actionpack/lib/action_controller/railties/routes_helpers.rb b/actionpack/lib/action_controller/railties/routes_helpers.rb new file mode 100644 index 0000000000..a23f703f0b --- /dev/null +++ b/actionpack/lib/action_controller/railties/routes_helpers.rb @@ -0,0 +1,17 @@ +module ActionController + module Railties + module RoutesHelpers + def self.with(routes) + Module.new do + define_method(:inherited) do |klass| + super(klass) + if namespace = klass.parents.detect {|m| m.respond_to?(:_railtie) } + routes = namespace._railtie.routes + end + klass.send(:include, routes.url_helpers) + end + end + end + end + end +end -- cgit v1.2.3 From befa77fc18ba54c1be89553466312039c1073f02 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Mon, 2 Aug 2010 02:55:01 +0200 Subject: Fix generating urls with mounted helpers in view context There were actually 2 problems with this one: * script_name was added to options as a string and then it was used in RouteSet#url_for with usage of <<, which was changing the original script_name * the second issue was with _with_routes method. It was called in RoutesProxy to modify _routes in view_context, but url_helpers in views is just delegating it to controller, so another _with_routes call is needed there --- actionpack/lib/action_controller/metal/url_for.rb | 2 +- actionpack/lib/action_dispatch/routing/route_set.rb | 2 +- actionpack/lib/action_view/helpers/url_helper.rb | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/metal/url_for.rb b/actionpack/lib/action_controller/metal/url_for.rb index e7eb7485c4..1e34f21c77 100644 --- a/actionpack/lib/action_controller/metal/url_for.rb +++ b/actionpack/lib/action_controller/metal/url_for.rb @@ -7,7 +7,7 @@ module ActionController def url_options options = {} if _routes.equal?(env["action_dispatch.routes"]) - options[:script_name] = request.script_name + options[:script_name] = request.script_name.dup end super.merge(options).reverse_merge( diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index c67b0199ce..6e7e133cc5 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -307,7 +307,7 @@ module ActionDispatch routes = self MountedHelpers.class_eval do define_method "_#{name}" do - RoutesProxy.new(routes, (self.respond_to?(:controller) ? controller : self)) + RoutesProxy.new(routes, self) end end diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb index b8df2d9a69..f21cffea26 100644 --- a/actionpack/lib/action_view/helpers/url_helper.rb +++ b/actionpack/lib/action_view/helpers/url_helper.rb @@ -29,7 +29,9 @@ module ActionView # def url_options return super unless controller.respond_to?(:url_options) - controller.url_options + controller.send(:_with_routes, _routes) do + controller.url_options + end end # Returns the URL for the set of +options+ provided. This takes the -- cgit v1.2.3 From 4131a2d804c54960ac70984e7453069fe8688365 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Mon, 2 Aug 2010 17:38:44 +0200 Subject: Move ActionController::Railties::RoutesHelpers and ActionMailer::Railties::RoutesHelper to AbstractController::Railties::RoutesHelpers --- .../lib/abstract_controller/railties/routes_helpers.rb | 18 ++++++++++++++++++ actionpack/lib/action_controller/railtie.rb | 4 ++-- .../lib/action_controller/railties/routes_helpers.rb | 17 ----------------- 3 files changed, 20 insertions(+), 19 deletions(-) create mode 100644 actionpack/lib/abstract_controller/railties/routes_helpers.rb delete mode 100644 actionpack/lib/action_controller/railties/routes_helpers.rb (limited to 'actionpack') diff --git a/actionpack/lib/abstract_controller/railties/routes_helpers.rb b/actionpack/lib/abstract_controller/railties/routes_helpers.rb new file mode 100644 index 0000000000..dec1e9d6d9 --- /dev/null +++ b/actionpack/lib/abstract_controller/railties/routes_helpers.rb @@ -0,0 +1,18 @@ +module AbstractController + module Railties + module RoutesHelpers + def self.with(routes) + Module.new do + define_method(:inherited) do |klass| + super(klass) + if namespace = klass.parents.detect {|m| m.respond_to?(:_railtie) } + klass.send(:include, namespace._railtie.routes.url_helpers) + else + klass.send(:include, routes.url_helpers) + end + end + end + end + end + end +end diff --git a/actionpack/lib/action_controller/railtie.rb b/actionpack/lib/action_controller/railtie.rb index 23622b19e8..4b5a897b90 100644 --- a/actionpack/lib/action_controller/railtie.rb +++ b/actionpack/lib/action_controller/railtie.rb @@ -4,7 +4,7 @@ require "action_dispatch/railtie" require "action_view/railtie" require "active_support/deprecation/proxy_wrappers" require "active_support/deprecation" -require "action_controller/railties/routes_helpers" +require "abstract_controller/railties/routes_helpers" module ActionController class Railtie < Rails::Railtie @@ -51,7 +51,7 @@ module ActionController options.helpers_path ||= paths.app.helpers.to_a ActiveSupport.on_load(:action_controller) do - extend ::ActionController::Railties::RoutesHelpers.with(app.routes) + extend ::AbstractController::Railties::RoutesHelpers.with(app.routes) include app.routes.mounted_helpers(:app) options.each { |k,v| send("#{k}=", v) } end diff --git a/actionpack/lib/action_controller/railties/routes_helpers.rb b/actionpack/lib/action_controller/railties/routes_helpers.rb deleted file mode 100644 index a23f703f0b..0000000000 --- a/actionpack/lib/action_controller/railties/routes_helpers.rb +++ /dev/null @@ -1,17 +0,0 @@ -module ActionController - module Railties - module RoutesHelpers - def self.with(routes) - Module.new do - define_method(:inherited) do |klass| - super(klass) - if namespace = klass.parents.detect {|m| m.respond_to?(:_railtie) } - routes = namespace._railtie.routes - end - klass.send(:include, routes.url_helpers) - end - end - end - end - end -end -- cgit v1.2.3 From 79bd92b7833d52b74f50259cf8a21f9b05f3e9e3 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Tue, 3 Aug 2010 19:36:53 +0200 Subject: Refactor ActionMailer to not use hide_actions --- actionpack/lib/abstract_controller.rb | 1 + actionpack/lib/abstract_controller/url_for.rb | 28 ++++++++++++++++++++++ actionpack/lib/action_controller/metal/url_for.rb | 15 +----------- .../lib/action_dispatch/routing/route_set.rb | 7 +++++- 4 files changed, 36 insertions(+), 15 deletions(-) create mode 100644 actionpack/lib/abstract_controller/url_for.rb (limited to 'actionpack') diff --git a/actionpack/lib/abstract_controller.rb b/actionpack/lib/abstract_controller.rb index f8fc79936f..cc5878c88e 100644 --- a/actionpack/lib/abstract_controller.rb +++ b/actionpack/lib/abstract_controller.rb @@ -24,4 +24,5 @@ module AbstractController autoload :Translation autoload :AssetPaths autoload :ViewPaths + autoload :UrlFor end diff --git a/actionpack/lib/abstract_controller/url_for.rb b/actionpack/lib/abstract_controller/url_for.rb new file mode 100644 index 0000000000..2e9de22ecd --- /dev/null +++ b/actionpack/lib/abstract_controller/url_for.rb @@ -0,0 +1,28 @@ +module AbstractController + module UrlFor + extend ActiveSupport::Concern + + include ActionDispatch::Routing::UrlFor + + def _routes + raise "In order to use #url_for, you must include routing helpers explicitly. " \ + "For instance, `include Rails.application.routes.url_helpers" + end + + module ClassMethods + def _routes + nil + end + + def action_methods + @action_methods ||= begin + if _routes + super - _routes.named_routes.helper_names + else + super + end + end + end + end + end +end diff --git a/actionpack/lib/action_controller/metal/url_for.rb b/actionpack/lib/action_controller/metal/url_for.rb index 1e34f21c77..85c6b0a9b5 100644 --- a/actionpack/lib/action_controller/metal/url_for.rb +++ b/actionpack/lib/action_controller/metal/url_for.rb @@ -2,7 +2,7 @@ module ActionController module UrlFor extend ActiveSupport::Concern - include ActionDispatch::Routing::UrlFor + include AbstractController::UrlFor def url_options options = {} @@ -16,18 +16,5 @@ module ActionController :_path_segments => request.symbolized_path_parameters ) end - - def _routes - raise "In order to use #url_for, you must include routing helpers explicitly. " \ - "For instance, `include Rails.application.routes.url_helpers" - end - - module ClassMethods - def action_methods - @action_methods ||= begin - super - _routes.named_routes.helper_names - end - end - end end end diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 6e7e133cc5..219fa37fcb 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -337,7 +337,12 @@ module ActionDispatch # Yes plz - JP included do routes.install_helpers(self) - singleton_class.send(:define_method, :_routes) { @_routes || routes } + singleton_class.send(:define_method, :_routes) { routes } + end + + def initialize(*) + @_routes = nil + super end define_method(:_routes) { @_routes || routes } -- cgit v1.2.3 From f3c703a32f6c7833705e46b8e14f172330a1c916 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 4 Aug 2010 16:20:56 +0200 Subject: Refactor RoutesProxy to avoid using _with_routes in helpers --- actionpack/lib/action_dispatch/routing/route_set.rb | 2 +- actionpack/lib/action_dispatch/routing/url_for.rb | 4 ++++ actionpack/lib/action_view/helpers/url_helper.rb | 8 +++++--- 3 files changed, 10 insertions(+), 4 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 219fa37fcb..363bcbd2b0 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -307,7 +307,7 @@ module ActionDispatch routes = self MountedHelpers.class_eval do define_method "_#{name}" do - RoutesProxy.new(routes, self) + RoutesProxy.new(routes, self._routes_context) end end diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index 19db730b6a..e836cf7c8e 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -141,6 +141,10 @@ module ActionDispatch ensure @_routes = old_routes end + + def _routes_context + self + end end end end diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb index f21cffea26..555be6ed2b 100644 --- a/actionpack/lib/action_view/helpers/url_helper.rb +++ b/actionpack/lib/action_view/helpers/url_helper.rb @@ -22,6 +22,10 @@ module ActionView include ActionDispatch::Routing::UrlFor include TagHelper + def _routes_context + controller + end + # Need to map default url options to controller one. # def default_url_options(*args) #:nodoc: # controller.send(:default_url_options, *args) @@ -29,9 +33,7 @@ module ActionView # def url_options return super unless controller.respond_to?(:url_options) - controller.send(:_with_routes, _routes) do - controller.url_options - end + controller.url_options end # Returns the URL for the set of +options+ provided. This takes the -- cgit v1.2.3 From 8fb9df535e9fcf4c117ffd3254027e0fe2425cb7 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 4 Aug 2010 23:00:33 +0200 Subject: Modified polymorphic_url to check for model's namespace This change allows using namespaced models with polymorphic_url, in the way that you would use them without namespace. Let's say that you have Blog::Post model in namespaced Engine. When you use polymorphic_path with Blog::Post instances, like in form_for(@post), it will look for blog_posts_path named url helper. As we are inside Blog::Engine, it's annoying to always use the prefix. With this commit, blog_ prefix will be removed and posts_path will be called. --- actionpack/lib/action_dispatch/routing/polymorphic_routes.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb index 15ee7c8051..037b94b577 100644 --- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb +++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb @@ -111,6 +111,10 @@ module ActionDispatch args.last.kind_of?(Hash) ? args.last.merge!(url_options) : args << url_options end + if namespace = record.class.parents.detect { |n| n.respond_to?(:_railtie) } + named_route.sub!(/#{namespace._railtie.railtie_name}_/, '') + end + url_for _routes.url_helpers.__send__("hash_for_#{named_route}", *args) end -- cgit v1.2.3 From e5af8b7d85abb94f21f4e873c1c267e27be2aad8 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 6 Aug 2010 16:34:48 +0200 Subject: Moved ActionMailer and ActionController railties options to inherited hook This change is needed, because we must take namespace into account and if controller's/mailer's class is namespaced, engine's paths should be set instead of application's ones. The nice side effect of this is removing unneeded logic in ActionController::Base.inherited - now the helpers_path should be set correctly even for engine's controllers, so helper(:all) will always include correct helpers. --- actionpack/lib/action_controller/base.rb | 6 +---- actionpack/lib/action_controller/railtie.rb | 14 +++-------- actionpack/lib/action_controller/railties/paths.rb | 28 ++++++++++++++++++++++ 3 files changed, 32 insertions(+), 16 deletions(-) create mode 100644 actionpack/lib/action_controller/railties/paths.rb (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 3560ac5b8c..1953e1869f 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -223,11 +223,7 @@ module ActionController def self.inherited(klass) super - if namespace = klass.parents.detect {|m| m.respond_to?(:_railtie) } - klass.helper(all_helpers_from_path(namespace._railtie.config.paths.app.helpers.to_a)) - else - klass.helper :all if klass.superclass == ActionController::Base - end + klass.helper :all if klass.superclass == ActionController::Base end ActiveSupport.run_load_hooks(:action_controller, self) diff --git a/actionpack/lib/action_controller/railtie.rb b/actionpack/lib/action_controller/railtie.rb index 4b5a897b90..2271a51e4e 100644 --- a/actionpack/lib/action_controller/railtie.rb +++ b/actionpack/lib/action_controller/railtie.rb @@ -5,6 +5,7 @@ require "action_view/railtie" require "active_support/deprecation/proxy_wrappers" require "active_support/deprecation" require "abstract_controller/railties/routes_helpers" +require "action_controller/railties/paths" module ActionController class Railtie < Rails::Railtie @@ -41,19 +42,10 @@ module ActionController end initializer "action_controller.set_configs" do |app| - paths = app.config.paths - options = app.config.action_controller - - options.assets_dir ||= paths.public.to_a.first - options.javascripts_dir ||= paths.public.javascripts.to_a.first - options.stylesheets_dir ||= paths.public.stylesheets.to_a.first - options.page_cache_directory ||= paths.public.to_a.first - options.helpers_path ||= paths.app.helpers.to_a - ActiveSupport.on_load(:action_controller) do - extend ::AbstractController::Railties::RoutesHelpers.with(app.routes) include app.routes.mounted_helpers(:app) - options.each { |k,v| send("#{k}=", v) } + extend ::AbstractController::Railties::RoutesHelpers.with(app.routes) + extend ::ActionController::Railties::Paths.with(app) end end diff --git a/actionpack/lib/action_controller/railties/paths.rb b/actionpack/lib/action_controller/railties/paths.rb new file mode 100644 index 0000000000..095beb7a2f --- /dev/null +++ b/actionpack/lib/action_controller/railties/paths.rb @@ -0,0 +1,28 @@ +module ActionController + module Railties + module Paths + def self.with(_app) + Module.new do + define_method(:inherited) do |klass| + super(klass) + if namespace = klass.parents.detect {|m| m.respond_to?(:_railtie) } + app = namespace._railtie + else + app = _app + end + + paths = app.config.paths + options = app.config.action_controller + + options.assets_dir ||= paths.public.to_a.first + options.javascripts_dir ||= paths.public.javascripts.to_a.first + options.stylesheets_dir ||= paths.public.stylesheets.to_a.first + options.page_cache_directory ||= paths.public.to_a.first + options.helpers_path ||= paths.app.helpers.to_a + options.each { |k,v| klass.send("#{k}=", v) } + end + end + end + end + end +end -- cgit v1.2.3 From 00874a2009ce209d0c3a3cc2bf6c26b1bb15f3e5 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sun, 22 Aug 2010 18:06:03 +0200 Subject: This was used only to clear warning in ActionMailer tests, it shouldn't be done like that --- actionpack/lib/action_dispatch/routing/route_set.rb | 5 ----- 1 file changed, 5 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 363bcbd2b0..c09c1fef6f 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -340,11 +340,6 @@ module ActionDispatch singleton_class.send(:define_method, :_routes) { routes } end - def initialize(*) - @_routes = nil - super - end - define_method(:_routes) { @_routes || routes } end -- cgit v1.2.3 From 8ec2175aee93ecfd928de67c0a125bccc5e1c152 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Mon, 23 Aug 2010 14:02:05 +0200 Subject: Added more tests for polymorphic_url with namespaced models and implemented missing use cases --- .../action_dispatch/routing/polymorphic_routes.rb | 15 ++++-- .../test/activerecord/polymorphic_routes_test.rb | 56 ++++++++++++++++++++++ 2 files changed, 66 insertions(+), 5 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb index 037b94b577..517936bc96 100644 --- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb +++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb @@ -111,10 +111,6 @@ module ActionDispatch args.last.kind_of?(Hash) ? args.last.merge!(url_options) : args << url_options end - if namespace = record.class.parents.detect { |n| n.respond_to?(:_railtie) } - named_route.sub!(/#{namespace._railtie.railtie_name}_/, '') - end - url_for _routes.url_helpers.__send__("hash_for_#{named_route}", *args) end @@ -159,7 +155,8 @@ module ActionDispatch if parent.is_a?(Symbol) || parent.is_a?(String) parent else - ActiveModel::Naming.plural(parent).singularize + str = ActiveModel::Naming.plural(parent).singularize + remove_namespace(str, parent) end end end @@ -168,6 +165,7 @@ module ActionDispatch route << record else route << ActiveModel::Naming.plural(record) + remove_namespace(route, record) route = [route.join("_").singularize] if inflection == :singular route << "index" if ActiveModel::Naming.uncountable?(record) && inflection == :plural end @@ -177,6 +175,13 @@ module ActionDispatch action_prefix(options) + route.join("_") end + def remove_namespace(string, parent) + if namespace = parent.class.parents.detect { |n| n.respond_to?(:_railtie) } + string.sub!(/#{namespace._railtie.railtie_name}_/, '') + end + string + end + def extract_record(record_or_hash_or_array) case record_or_hash_or_array when Array; record_or_hash_or_array.last diff --git a/actionpack/test/activerecord/polymorphic_routes_test.rb b/actionpack/test/activerecord/polymorphic_routes_test.rb index 90a1ef982c..94b8a8c7c3 100644 --- a/actionpack/test/activerecord/polymorphic_routes_test.rb +++ b/actionpack/test/activerecord/polymorphic_routes_test.rb @@ -25,6 +25,22 @@ class Series < ActiveRecord::Base set_table_name 'projects' end +module Blog + class Post < ActiveRecord::Base + set_table_name 'projects' + end + + class Blog < ActiveRecord::Base + set_table_name 'projects' + end + + def self._railtie + o = Object.new + def o.railtie_name; "blog" end + o + end +end + class PolymorphicRoutesTest < ActionController::TestCase include SharedTestRoutes.url_helpers self.default_url_options[:host] = 'example.com' @@ -37,6 +53,30 @@ class PolymorphicRoutesTest < ActionController::TestCase @tax = Tax.new @fax = Fax.new @series = Series.new + @blog_post = Blog::Post.new + @blog_blog = Blog::Blog.new + end + + def test_namespaced_model + with_namespaced_routes(:blog) do + @blog_post.save + assert_equal "http://example.com/posts/#{@blog_post.id}", polymorphic_url(@blog_post) + end + end + + def test_namespaced_model_with_name_the_same_as_namespace + with_namespaced_routes(:blog) do + @blog_blog.save + assert_equal "http://example.com/blogs/#{@blog_blog.id}", polymorphic_url(@blog_blog) + end + end + + def test_namespaced_model_with_nested_resources + with_namespaced_routes(:blog) do + @blog_post.save + @blog_blog.save + assert_equal "http://example.com/blogs/#{@blog_blog.id}/posts/#{@blog_post.id}", polymorphic_url([@blog_blog, @blog_post]) + end end def test_with_record @@ -385,6 +425,22 @@ class PolymorphicRoutesTest < ActionController::TestCase end end + def with_namespaced_routes(name) + with_routing do |set| + set.draw do + namespace(name, :shallow_path => nil, :path => nil, :as => nil) do + resources :blogs do + resources :posts + end + resources :posts + end + end + + self.class.send(:include, @routes.url_helpers) + yield + end + end + def with_test_routes(options = {}) with_routing do |set| set.draw do |map| -- cgit v1.2.3 From 98ab4ded376c3d04540bdbdfe6dbbf88c0738701 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Mon, 23 Aug 2010 18:31:29 +0200 Subject: Set only helpers_path on inherited hook in action_controller/railtie.rb and use helper(:all) just after that --- actionpack/lib/action_controller/base.rb | 5 ----- actionpack/lib/action_controller/railtie.rb | 9 +++++++++ actionpack/lib/action_controller/railties/paths.rb | 6 ++---- 3 files changed, 11 insertions(+), 9 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 1953e1869f..b37bc02127 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -221,11 +221,6 @@ module ActionController # Rails 2.x compatibility include ActionController::Compatibility - def self.inherited(klass) - super - klass.helper :all if klass.superclass == ActionController::Base - end - ActiveSupport.run_load_hooks(:action_controller, self) end end diff --git a/actionpack/lib/action_controller/railtie.rb b/actionpack/lib/action_controller/railtie.rb index 2271a51e4e..0cb4041855 100644 --- a/actionpack/lib/action_controller/railtie.rb +++ b/actionpack/lib/action_controller/railtie.rb @@ -42,10 +42,19 @@ module ActionController end initializer "action_controller.set_configs" do |app| + paths = app.config.paths + options = app.config.action_controller + + options.assets_dir ||= paths.public.to_a.first + options.javascripts_dir ||= paths.public.javascripts.to_a.first + options.stylesheets_dir ||= paths.public.stylesheets.to_a.first + options.page_cache_directory ||= paths.public.to_a.first + ActiveSupport.on_load(:action_controller) do include app.routes.mounted_helpers(:app) extend ::AbstractController::Railties::RoutesHelpers.with(app.routes) extend ::ActionController::Railties::Paths.with(app) + options.each { |k,v| send("#{k}=", v) } end end diff --git a/actionpack/lib/action_controller/railties/paths.rb b/actionpack/lib/action_controller/railties/paths.rb index 095beb7a2f..81d03f5e73 100644 --- a/actionpack/lib/action_controller/railties/paths.rb +++ b/actionpack/lib/action_controller/railties/paths.rb @@ -14,12 +14,10 @@ module ActionController paths = app.config.paths options = app.config.action_controller - options.assets_dir ||= paths.public.to_a.first - options.javascripts_dir ||= paths.public.javascripts.to_a.first - options.stylesheets_dir ||= paths.public.stylesheets.to_a.first - options.page_cache_directory ||= paths.public.to_a.first options.helpers_path ||= paths.app.helpers.to_a options.each { |k,v| klass.send("#{k}=", v) } + + klass.helper :all end end end -- cgit v1.2.3 From e35c2043b135a95104e3eeb3e12cbcde541fa1b4 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Mon, 23 Aug 2010 19:25:04 +0200 Subject: Include all helpers from non-namespaced engines --- actionpack/lib/action_controller/railties/paths.rb | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/railties/paths.rb b/actionpack/lib/action_controller/railties/paths.rb index 81d03f5e73..e1b318b566 100644 --- a/actionpack/lib/action_controller/railties/paths.rb +++ b/actionpack/lib/action_controller/railties/paths.rb @@ -1,22 +1,16 @@ module ActionController module Railties module Paths - def self.with(_app) + def self.with(app) Module.new do define_method(:inherited) do |klass| super(klass) if namespace = klass.parents.detect {|m| m.respond_to?(:_railtie) } - app = namespace._railtie + klass.helpers_path = namespace._railtie.config.paths.app.helpers.to_a else - app = _app + klass.helpers_path = app.config.helpers_paths end - paths = app.config.paths - options = app.config.action_controller - - options.helpers_path ||= paths.app.helpers.to_a - options.each { |k,v| klass.send("#{k}=", v) } - klass.helper :all end end -- cgit v1.2.3 From b1c66f060bba22d16abf6d24d3df762c240e367c Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 25 Aug 2010 13:41:56 +0200 Subject: Move RoutesProxy to separate file --- actionpack/lib/action_dispatch/routing.rb | 1 + .../lib/action_dispatch/routing/route_set.rb | 32 -------------------- .../lib/action_dispatch/routing/routes_proxy.rb | 35 ++++++++++++++++++++++ 3 files changed, 36 insertions(+), 32 deletions(-) create mode 100644 actionpack/lib/action_dispatch/routing/routes_proxy.rb (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb index 0b9689dc88..b2b0f4c08e 100644 --- a/actionpack/lib/action_dispatch/routing.rb +++ b/actionpack/lib/action_dispatch/routing.rb @@ -268,6 +268,7 @@ module ActionDispatch autoload :Mapper, 'action_dispatch/routing/mapper' autoload :Route, 'action_dispatch/routing/route' autoload :RouteSet, 'action_dispatch/routing/route_set' + autoload :RoutesProxy, 'action_dispatch/routing/routes_proxy' autoload :UrlFor, 'action_dispatch/routing/url_for' autoload :PolymorphicRoutes, 'action_dispatch/routing/polymorphic_routes' diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index c09c1fef6f..0d83ca956b 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -261,38 +261,6 @@ module ActionDispatch named_routes.install(destinations, regenerate_code) end - class RoutesProxy - include ActionDispatch::Routing::UrlFor - - attr_accessor :scope, :routes - alias :_routes :routes - - def initialize(routes, scope) - @routes, @scope = routes, scope - end - - def url_options - scope.send(:_with_routes, routes) do - scope.url_options - end - end - - def method_missing(method, *args) - if routes.url_helpers.respond_to?(method) - self.class.class_eval <<-RUBY, __FILE__, __LINE__ + 1 - def #{method}(*args) - options = args.extract_options! - args << url_options.merge((options || {}).symbolize_keys) - routes.url_helpers.#{method}(*args) - end - RUBY - send(method, *args) - else - super - end - end - end - module MountedHelpers end diff --git a/actionpack/lib/action_dispatch/routing/routes_proxy.rb b/actionpack/lib/action_dispatch/routing/routes_proxy.rb new file mode 100644 index 0000000000..f7d5f6397d --- /dev/null +++ b/actionpack/lib/action_dispatch/routing/routes_proxy.rb @@ -0,0 +1,35 @@ +module ActionDispatch + module Routing + class RoutesProxy #:nodoc: + include ActionDispatch::Routing::UrlFor + + attr_accessor :scope, :routes + alias :_routes :routes + + def initialize(routes, scope) + @routes, @scope = routes, scope + end + + def url_options + scope.send(:_with_routes, routes) do + scope.url_options + end + end + + def method_missing(method, *args) + if routes.url_helpers.respond_to?(method) + self.class.class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{method}(*args) + options = args.extract_options! + args << url_options.merge((options || {}).symbolize_keys) + routes.url_helpers.#{method}(*args) + end + RUBY + send(method, *args) + else + super + end + end + end + end +end -- cgit v1.2.3 From 613cbe1f0075eed7ebf1ac521e99f652f6891330 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 25 Aug 2010 15:42:24 +0200 Subject: Add possibility to explicitly call engine's routes through polymorphic_routes, for example: polymorphic_url([blog, @post]) --- .../action_dispatch/routing/polymorphic_routes.rb | 21 ++++++++++++++++++++- .../test/activerecord/polymorphic_routes_test.rb | 8 ++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb index 517936bc96..e8ba1de40e 100644 --- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb +++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb @@ -42,6 +42,18 @@ module ActionDispatch # # edit_polymorphic_path(@post) # => "/posts/1/edit" # polymorphic_path(@post, :format => :pdf) # => "/posts/1.pdf" + # + # == Using with mounted engines + # + # If you use mounted engine, there is a possibility that you will need to use + # polymorphic_url pointing at engine's routes. To do that, just pass proxy used + # to reach engine's routes as a first argument: + # + # For example: + # + # polymorphic_url([blog, @post]) # it will call blog.post_path(@post) + # form_for([blog, @post]) # => "/blog/posts/1 + # module PolymorphicRoutes # Constructs a call to a named RESTful route for the given record and returns the # resulting URL string. For example: @@ -78,6 +90,9 @@ module ActionDispatch def polymorphic_url(record_or_hash_or_array, options = {}) if record_or_hash_or_array.kind_of?(Array) record_or_hash_or_array = record_or_hash_or_array.compact + if record_or_hash_or_array.first.is_a?(ActionDispatch::Routing::RoutesProxy) + proxy = record_or_hash_or_array.shift + end record_or_hash_or_array = record_or_hash_or_array[0] if record_or_hash_or_array.size == 1 end @@ -111,7 +126,11 @@ module ActionDispatch args.last.kind_of?(Hash) ? args.last.merge!(url_options) : args << url_options end - url_for _routes.url_helpers.__send__("hash_for_#{named_route}", *args) + if proxy + proxy.send(named_route, *args) + else + url_for _routes.url_helpers.__send__("hash_for_#{named_route}", *args) + end end # Returns the path component of a URL for the given record. It uses diff --git a/actionpack/test/activerecord/polymorphic_routes_test.rb b/actionpack/test/activerecord/polymorphic_routes_test.rb index 94b8a8c7c3..23c9fb839e 100644 --- a/actionpack/test/activerecord/polymorphic_routes_test.rb +++ b/actionpack/test/activerecord/polymorphic_routes_test.rb @@ -57,6 +57,14 @@ class PolymorphicRoutesTest < ActionController::TestCase @blog_blog = Blog::Blog.new end + def test_passing_routes_proxy + with_namespaced_routes(:blog) do + proxy = ActionDispatch::Routing::RoutesProxy.new(_routes, self) + @blog_post.save + assert_equal "http://example.com/posts/#{@blog_post.id}", polymorphic_url([proxy, @blog_post]) + end + end + def test_namespaced_model with_namespaced_routes(:blog) do @blog_post.save -- cgit v1.2.3 From 706a3223a303d56feeee2cc7601da1bd9f381243 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 25 Aug 2010 15:59:25 +0200 Subject: Add short note on using url_for instead of directly calling named route in polymorphic_url --- actionpack/lib/action_dispatch/routing/polymorphic_routes.rb | 3 +++ 1 file changed, 3 insertions(+) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb index e8ba1de40e..ecc1651dfe 100644 --- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb +++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb @@ -129,6 +129,9 @@ module ActionDispatch if proxy proxy.send(named_route, *args) else + # we need to use url_for, because polymorphic_url can be used in context of other than + # current routes (e.g. engine's routes). As named routes from engine are not included + # calling engine's named route directly would fail. url_for _routes.url_helpers.__send__("hash_for_#{named_route}", *args) end end -- cgit v1.2.3 From 2607def8621c41d5b0bee09e379ae26890b27f7d Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Tue, 31 Aug 2010 23:43:32 +0200 Subject: Use new ActiveModel::Naming.route_key in polymorphic_routes --- .../lib/action_dispatch/routing/polymorphic_routes.rb | 13 ++----------- actionpack/test/activerecord/polymorphic_routes_test.rb | 2 +- 2 files changed, 3 insertions(+), 12 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb index ecc1651dfe..02ba5236ee 100644 --- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb +++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb @@ -177,8 +177,7 @@ module ActionDispatch if parent.is_a?(Symbol) || parent.is_a?(String) parent else - str = ActiveModel::Naming.plural(parent).singularize - remove_namespace(str, parent) + ActiveModel::Naming.route_key(parent).singularize end end end @@ -186,8 +185,7 @@ module ActionDispatch if record.is_a?(Symbol) || record.is_a?(String) route << record else - route << ActiveModel::Naming.plural(record) - remove_namespace(route, record) + route << ActiveModel::Naming.route_key(record) route = [route.join("_").singularize] if inflection == :singular route << "index" if ActiveModel::Naming.uncountable?(record) && inflection == :plural end @@ -197,13 +195,6 @@ module ActionDispatch action_prefix(options) + route.join("_") end - def remove_namespace(string, parent) - if namespace = parent.class.parents.detect { |n| n.respond_to?(:_railtie) } - string.sub!(/#{namespace._railtie.railtie_name}_/, '') - end - string - end - def extract_record(record_or_hash_or_array) case record_or_hash_or_array when Array; record_or_hash_or_array.last diff --git a/actionpack/test/activerecord/polymorphic_routes_test.rb b/actionpack/test/activerecord/polymorphic_routes_test.rb index 23c9fb839e..448aaa5eee 100644 --- a/actionpack/test/activerecord/polymorphic_routes_test.rb +++ b/actionpack/test/activerecord/polymorphic_routes_test.rb @@ -436,7 +436,7 @@ class PolymorphicRoutesTest < ActionController::TestCase def with_namespaced_routes(name) with_routing do |set| set.draw do - namespace(name, :shallow_path => nil, :path => nil, :as => nil) do + scope(:module => name) do resources :blogs do resources :posts end -- cgit v1.2.3 From 6f3119d3c298c007e7a4eed8375d9fc30b961d06 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 1 Sep 2010 01:37:02 +0200 Subject: Remove namespace for isolated namespaced models in forms --- actionpack/lib/action_view/helpers/form_helper.rb | 10 +++++----- actionpack/test/lib/controller/fake_models.rb | 15 +++++++++++++++ actionpack/test/template/form_helper_test.rb | 17 +++++++++++++++++ 3 files changed, 37 insertions(+), 5 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 94dc25eb85..43dbedc448 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -304,12 +304,12 @@ module ActionView object_name = record_or_name_or_array when Array object = record_or_name_or_array.last - object_name = options[:as] || ActiveModel::Naming.singular(object) + object_name = options[:as] || ActiveModel::Naming.param_key(object) apply_form_for_options!(record_or_name_or_array, options) args.unshift object else object = record_or_name_or_array - object_name = options[:as] || ActiveModel::Naming.singular(object) + object_name = options[:as] || ActiveModel::Naming.param_key(object) apply_form_for_options!([object], options) args.unshift object end @@ -539,7 +539,7 @@ module ActionView object_name = record else object = record - object_name = ActiveModel::Naming.singular(object) + object_name = ActiveModel::Naming.param_key(object) end builder = options[:builder] || ActionView::Base.default_form_builder @@ -1168,11 +1168,11 @@ module ActionView end when Array object = record_or_name_or_array.last - name = "#{object_name}#{index}[#{ActiveModel::Naming.singular(object)}]" + name = "#{object_name}#{index}[#{ActiveModel::Naming.param_key(object)}]" args.unshift(object) else object = record_or_name_or_array - name = "#{object_name}#{index}[#{ActiveModel::Naming.singular(object)}]" + name = "#{object_name}#{index}[#{ActiveModel::Naming.param_key(object)}]" args.unshift(object) end diff --git a/actionpack/test/lib/controller/fake_models.rb b/actionpack/test/lib/controller/fake_models.rb index 37b200d57a..c4127ee699 100644 --- a/actionpack/test/lib/controller/fake_models.rb +++ b/actionpack/test/lib/controller/fake_models.rb @@ -149,3 +149,18 @@ class Author < Comment attr_accessor :post def post_attributes=(attributes); end end + +module Blog + def self._railtie + self + end + + class Post < Struct.new(:title, :id) + extend ActiveModel::Naming + include ActiveModel::Conversion + + def persisted? + id.present? + end + end +end diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb index ec57b6a2ab..97a08d45ba 100644 --- a/actionpack/test/template/form_helper_test.rb +++ b/actionpack/test/template/form_helper_test.rb @@ -75,6 +75,8 @@ class FormHelperTest < ActionView::TestCase @post.body = "Back to the hill and over it again!" @post.secret = 1 @post.written_on = Date.new(2004, 6, 15) + + @blog_post = Blog::Post.new("And his name will be forty and four.", 44) end Routes = ActionDispatch::Routing::RouteSet.new @@ -675,6 +677,21 @@ class FormHelperTest < ActionView::TestCase assert_dom_equal expected, output_buffer end + def test_form_for_with_isolated_namespaced_model + form_for(@blog_post) do |f| + concat f.text_field :title + concat f.submit('Edit post') + end + + expected = + "" + + snowman + + "" + + "" + + "" + + "" + end + def test_form_for_with_symbol_object_name form_for(@post, :as => "other_name", :html => { :id => 'create-post' }) do |f| concat f.label(:title, :class => 'post_title') -- cgit v1.2.3 From b8d6dc3c84321c751ab2ca8232e1e3fb332a844c Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 1 Sep 2010 19:17:47 +0200 Subject: Implemented RouteSet#default_scope, which allows to set the scope for the entire routes object --- actionpack/lib/action_dispatch/routing/mapper.rb | 6 +++++ .../lib/action_dispatch/routing/route_set.rb | 8 ++++-- actionpack/test/dispatch/routing_test.rb | 29 ++++++++++++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index b437d7a17d..900900ee24 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -274,6 +274,12 @@ module ActionDispatch end alias_method :default_url_options, :default_url_options= + def with_default_scope(scope, &block) + scope(scope) do + instance_exec(&block) + end + end + private def app_name(app) return unless app.respond_to?(:routes) diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 0d83ca956b..107e44287d 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -199,7 +199,7 @@ module ActionDispatch end end - attr_accessor :set, :routes, :named_routes + attr_accessor :set, :routes, :named_routes, :default_scope attr_accessor :disable_clear_and_finalize, :resources_path_names attr_accessor :default_url_options, :request_class, :valid_conditions @@ -230,7 +230,11 @@ module ActionDispatch if block.arity == 1 mapper.instance_exec(DeprecatedMapper.new(self), &block) else - mapper.instance_exec(&block) + if default_scope + mapper.with_default_scope(default_scope, &block) + else + mapper.instance_exec(&block) + end end finalize! unless @disable_clear_and_finalize diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index c90c1041ed..b642adc06b 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -2151,3 +2151,32 @@ private %(You are being redirected.) end end + + +class TestDefaultScope < ActionController::IntegrationTest + module ::Blog + class PostsController < ActionController::Base + def index + render :text => "blog/posts#index" + end + end + end + + DefaultScopeRoutes = ActionDispatch::Routing::RouteSet.new + DefaultScopeRoutes.default_scope = {:module => :blog} + DefaultScopeRoutes.draw do + resources :posts + end + + def app + DefaultScopeRoutes + end + + include DefaultScopeRoutes.url_helpers + + def test_default_scope + get '/posts' + assert_equal "blog/posts#index", @response.body + end +end + -- cgit v1.2.3 From 89bd715f6be4235ac7632de10349e9939be04e75 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 3 Sep 2010 11:01:24 +0200 Subject: Forgot to move that line to railtie on rebase --- actionpack/lib/action_controller/railties/paths.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/railties/paths.rb b/actionpack/lib/action_controller/railties/paths.rb index e1b318b566..fa71d55946 100644 --- a/actionpack/lib/action_controller/railties/paths.rb +++ b/actionpack/lib/action_controller/railties/paths.rb @@ -11,7 +11,7 @@ module ActionController klass.helpers_path = app.config.helpers_paths end - klass.helper :all + klass.helper :all if klass.superclass == ActionController::Base end end end -- cgit v1.2.3 From 9f0a1ae14e2a9306605d7b572612ccf36fa8b2da Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 3 Sep 2010 12:48:21 +0200 Subject: Optimize ActionDispatch::Static --- .../lib/action_dispatch/middleware/static.rb | 86 +++++++++------------- 1 file changed, 35 insertions(+), 51 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/middleware/static.rb b/actionpack/lib/action_dispatch/middleware/static.rb index c2d686f514..e7e335df49 100644 --- a/actionpack/lib/action_dispatch/middleware/static.rb +++ b/actionpack/lib/action_dispatch/middleware/static.rb @@ -1,44 +1,43 @@ require 'rack/utils' module ActionDispatch - class Static - class FileHandler - def initialize(at, root) - @at = at.chomp("/") - @file_server = ::Rack::File.new(root) - end - - def file_exist?(path) - (path = full_readable_path(path)) && File.file?(path) - end - - def directory_exist?(path) - (path = full_readable_path(path)) && File.directory?(path) - end - - def call(env) - env["PATH_INFO"].gsub!(/^#{@at}/, "") - @file_server.call(env) - end + class FileHandler + def initialize(at, root) + @at, @root = at.chomp('/'), root.chomp('/') + @compiled_at = Regexp.compile(/^#{Regexp.escape(at)}/) unless @at.blank? + @compiled_root = Regexp.compile(/^#{Regexp.escape(root)}/) + @file_server = ::Rack::File.new(root) + + ext = ::ActionController::Base.page_cache_extension + @ext = "{,#{ext},/index#{ext}}" + end - private - def includes_path?(path) - @at == "" || path =~ /^#{@at}/ + def match?(path) + path = path.dup + if @compiled_at.blank? || path.sub!(@compiled_at, '') + full_path = File.join(@root, ::Rack::Utils.unescape(path)) + paths = "#{full_path}#{@ext}" + + matches = Dir[paths] + match = matches.detect { |m| File.file?(m) } + if match + match.sub!(@compiled_root, '') + match end + end + end - def full_readable_path(path) - return unless includes_path?(path) - path = path.gsub(/^#{@at}/, "") - File.join(@file_server.root, ::Rack::Utils.unescape(path)) - end + def call(env) + @file_server.call(env) end + end + class Static FILE_METHODS = %w(GET HEAD).freeze def initialize(app, roots) @app = app - roots = normalize_roots(roots) - @file_handlers = file_handlers(roots) + @file_handlers = create_file_handlers(roots) end def call(env) @@ -46,14 +45,9 @@ module ActionDispatch method = env['REQUEST_METHOD'] if FILE_METHODS.include?(method) - if file_handler = file_exist?(path) - return file_handler.call(env) - else - cached_path = directory_exist?(path) ? "#{path}/index" : path - cached_path += ::ActionController::Base.page_cache_extension - - if file_handler = file_exist?(cached_path) - env['PATH_INFO'] = cached_path + @file_handlers.each do |file_handler| + if match = file_handler.match?(path) + env["PATH_INFO"] = match return file_handler.call(env) end end @@ -63,22 +57,12 @@ module ActionDispatch end private - def file_exist?(path) - @file_handlers.detect { |f| f.file_exist?(path) } - end + def create_file_handlers(roots) + roots = { '' => roots } unless roots.is_a?(Hash) - def directory_exist?(path) - @file_handlers.detect { |f| f.directory_exist?(path) } - end - - def normalize_roots(roots) - roots.is_a?(Hash) ? roots : { "/" => roots.chomp("/") } - end - - def file_handlers(roots) roots.map do |at, root| - FileHandler.new(at, root) - end + FileHandler.new(at, root) if File.exist?(root) + end.compact end end end -- cgit v1.2.3 From c3c1a1e14859e6716970283caeab0c4c3720862e Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 3 Sep 2010 23:25:57 +0200 Subject: Do not use ActionController::Base.page_cache_extension in initialize to not load more ActiveSupport than we need --- actionpack/lib/action_dispatch/middleware/static.rb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/middleware/static.rb b/actionpack/lib/action_dispatch/middleware/static.rb index e7e335df49..581cadbeb4 100644 --- a/actionpack/lib/action_dispatch/middleware/static.rb +++ b/actionpack/lib/action_dispatch/middleware/static.rb @@ -7,16 +7,13 @@ module ActionDispatch @compiled_at = Regexp.compile(/^#{Regexp.escape(at)}/) unless @at.blank? @compiled_root = Regexp.compile(/^#{Regexp.escape(root)}/) @file_server = ::Rack::File.new(root) - - ext = ::ActionController::Base.page_cache_extension - @ext = "{,#{ext},/index#{ext}}" end def match?(path) path = path.dup if @compiled_at.blank? || path.sub!(@compiled_at, '') full_path = File.join(@root, ::Rack::Utils.unescape(path)) - paths = "#{full_path}#{@ext}" + paths = "#{full_path}#{ext}" matches = Dir[paths] match = matches.detect { |m| File.file?(m) } @@ -30,6 +27,13 @@ module ActionDispatch def call(env) @file_server.call(env) end + + def ext + @ext ||= begin + ext = ::ActionController::Base.page_cache_extension + "{,#{ext},/index#{ext}}" + end + end end class Static -- cgit v1.2.3