aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/lib/abstract_controller/rendering.rb1
-rw-r--r--actionpack/lib/action_controller/railtie.rb3
-rw-r--r--actionpack/lib/action_controller/railties/url_helpers.rb26
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb5
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb59
-rw-r--r--actionpack/lib/action_dispatch/routing/url_for.rb28
-rw-r--r--actionpack/test/dispatch/prefix_generation_test.rb84
-rw-r--r--actionpack/test/dispatch/url_for_test.rb52
-rw-r--r--railties/test/railties/mounted_engine_test.rb32
9 files changed, 192 insertions, 98 deletions
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
diff --git a/railties/test/railties/mounted_engine_test.rb b/railties/test/railties/mounted_engine_test.rb
index 87bcf9b1f3..21c8658436 100644
--- a/railties/test/railties/mounted_engine_test.rb
+++ b/railties/test/railties/mounted_engine_test.rb
@@ -16,9 +16,10 @@ module ApplicationTests
app_file 'config/routes.rb', <<-RUBY
AppTemplate::Application.routes.draw do |map|
match "/engine_route" => "application_generating#engine_route"
+ match "/engine_route_in_view" => "application_generating#engine_route_in_view"
match "/url_for_engine_route" => "application_generating#url_for_engine_route"
scope "/:user", :user => "anonymous" do
- mount Blog::Engine => "/blog"
+ mount Blog::Engine => "/blog", :as => "blog_engine"
end
root :to => 'main#index'
end
@@ -39,6 +40,7 @@ module ApplicationTests
Blog::Engine.routes.draw do
resources :posts do
get :generate_application_route
+ get :application_route_in_view
end
end
RUBY
@@ -46,27 +48,34 @@ module ApplicationTests
@plugin.write "app/controllers/posts_controller.rb", <<-RUBY
class PostsController < ActionController::Base
def index
- render :text => url_for(Blog::Engine, :post_path, 1)
+ render :text => blog_engine.post_path(1)
end
def generate_application_route
- path = url_for(Rails.application,
- :controller => "main",
- :action => "index",
- :only_path => true)
+ path = app.url_for(:controller => "main",
+ :action => "index",
+ :only_path => true)
render :text => path
end
+
+ def application_route_in_view
+ render :inline => "<%= app.root_path %>"
+ end
end
RUBY
app_file "app/controllers/application_generating_controller.rb", <<-RUBY
class ApplicationGeneratingController < ActionController::Base
def engine_route
- render :text => url_for(Blog::Engine, :posts_path)
+ render :text => blog_engine.posts_path
+ end
+
+ def engine_route_in_view
+ render :inline => "<%= blog_engine.posts_path %>"
end
def url_for_engine_route
- render :text => url_for(Blog::Engine, :controller => "posts", :action => "index", :user => "john", :only_path => true)
+ render :text => blog_engine.url_for(:controller => "posts", :action => "index", :user => "john", :only_path => true)
end
end
RUBY
@@ -103,6 +112,10 @@ module ApplicationTests
# test generating engine's route from application
get "/engine_route"
assert_equal "/anonymous/blog/posts", last_response.body
+
+ get "/engine_route_in_view"
+ assert_equal "/anonymous/blog/posts", last_response.body
+
get "/url_for_engine_route"
assert_equal "/john/blog/posts", last_response.body
@@ -120,6 +133,9 @@ module ApplicationTests
get "/someone/blog/generate_application_route"
assert_equal "/", last_response.body
+ get "/somone/blog/application_route_in_view"
+ assert_equal "/", last_response.body
+
# test generating application's route from engine with default_url_options
script_name "/foo"
get "/someone/blog/generate_application_route", {}, 'SCRIPT_NAME' => '/foo'