mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #29662 from deivid-rodriguez/engine_multiple_mount_points
Allow mounting same engine under several locations
This commit is contained in:
commit
c8ce345964
5 changed files with 112 additions and 10 deletions
|
@ -652,19 +652,26 @@ module ActionDispatch
|
||||||
def define_generate_prefix(app, name)
|
def define_generate_prefix(app, name)
|
||||||
_route = @set.named_routes.get name
|
_route = @set.named_routes.get name
|
||||||
_routes = @set
|
_routes = @set
|
||||||
app.routes.define_mounted_helper(name)
|
|
||||||
app.routes.extend Module.new {
|
script_namer = ->(options) do
|
||||||
def optimize_routes_generation?; false; end
|
|
||||||
define_method :find_script_name do |options|
|
|
||||||
if options.key? :script_name
|
|
||||||
super(options)
|
|
||||||
else
|
|
||||||
prefix_options = options.slice(*_route.segment_keys)
|
prefix_options = options.slice(*_route.segment_keys)
|
||||||
prefix_options[:relative_url_root] = "".freeze
|
prefix_options[:relative_url_root] = "".freeze
|
||||||
# We must actually delete prefix segment keys to avoid passing them to next url_for.
|
# We must actually delete prefix segment keys to avoid passing them to next url_for.
|
||||||
_route.segment_keys.each { |k| options.delete(k) }
|
_route.segment_keys.each { |k| options.delete(k) }
|
||||||
_routes.url_helpers.send("#{name}_path", prefix_options)
|
_routes.url_helpers.send("#{name}_path", prefix_options)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
app.routes.define_mounted_helper(name, script_namer)
|
||||||
|
|
||||||
|
app.routes.extend Module.new {
|
||||||
|
def optimize_routes_generation?; false; end
|
||||||
|
|
||||||
|
define_method :find_script_name do |options|
|
||||||
|
if options.key? :script_name
|
||||||
|
super(options)
|
||||||
|
else
|
||||||
|
script_namer.call(options)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -449,7 +449,7 @@ module ActionDispatch
|
||||||
MountedHelpers
|
MountedHelpers
|
||||||
end
|
end
|
||||||
|
|
||||||
def define_mounted_helper(name)
|
def define_mounted_helper(name, script_namer = nil)
|
||||||
return if MountedHelpers.method_defined?(name)
|
return if MountedHelpers.method_defined?(name)
|
||||||
|
|
||||||
routes = self
|
routes = self
|
||||||
|
@ -457,7 +457,7 @@ module ActionDispatch
|
||||||
|
|
||||||
MountedHelpers.class_eval do
|
MountedHelpers.class_eval do
|
||||||
define_method "_#{name}" do
|
define_method "_#{name}" do
|
||||||
RoutesProxy.new(routes, _routes_context, helpers)
|
RoutesProxy.new(routes, _routes_context, helpers, script_namer)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,10 @@ module ActionDispatch
|
||||||
attr_accessor :scope, :routes
|
attr_accessor :scope, :routes
|
||||||
alias :_routes :routes
|
alias :_routes :routes
|
||||||
|
|
||||||
def initialize(routes, scope, helpers)
|
def initialize(routes, scope, helpers, script_namer = nil)
|
||||||
@routes, @scope = routes, scope
|
@routes, @scope = routes, scope
|
||||||
@helpers = helpers
|
@helpers = helpers
|
||||||
|
@script_namer = script_namer
|
||||||
end
|
end
|
||||||
|
|
||||||
def url_options
|
def url_options
|
||||||
|
@ -29,7 +30,9 @@ module ActionDispatch
|
||||||
self.class.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
self.class.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
||||||
def #{method}(*args)
|
def #{method}(*args)
|
||||||
options = args.extract_options!
|
options = args.extract_options!
|
||||||
args << url_options.merge((options || {}).symbolize_keys)
|
options = url_options.merge((options || {}).symbolize_keys)
|
||||||
|
options.reverse_merge!(script_name: @script_namer.call(options)) if @script_namer
|
||||||
|
args << options
|
||||||
@helpers.#{method}(*args)
|
@helpers.#{method}(*args)
|
||||||
end
|
end
|
||||||
RUBY
|
RUBY
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
* Allow mounting the same engine several times in different locations.
|
||||||
|
|
||||||
|
Fixes #20204.
|
||||||
|
|
||||||
|
*David Rodríguez*
|
||||||
|
|
||||||
* Clear screenshot files in `tmp:clear` task.
|
* Clear screenshot files in `tmp:clear` task.
|
||||||
|
|
||||||
*Yuji Yaginuma*
|
*Yuji Yaginuma*
|
||||||
|
|
|
@ -1341,6 +1341,92 @@ YAML
|
||||||
assert_equal "/foo/bukkits/bukkit", last_response.body
|
assert_equal "/foo/bukkits/bukkit", last_response.body
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "isolated engine can be mounted under multiple static locations" do
|
||||||
|
app_file "app/controllers/foos_controller.rb", <<-RUBY
|
||||||
|
class FoosController < ApplicationController
|
||||||
|
def through_fruits
|
||||||
|
render plain: fruit_bukkits.posts_path
|
||||||
|
end
|
||||||
|
|
||||||
|
def through_vegetables
|
||||||
|
render plain: vegetable_bukkits.posts_path
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
app_file "config/routes.rb", <<-RUBY
|
||||||
|
Rails.application.routes.draw do
|
||||||
|
scope "/fruits" do
|
||||||
|
mount Bukkits::Engine => "/bukkits", as: :fruit_bukkits
|
||||||
|
end
|
||||||
|
|
||||||
|
scope "/vegetables" do
|
||||||
|
mount Bukkits::Engine => "/bukkits", as: :vegetable_bukkits
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/through_fruits" => "foos#through_fruits"
|
||||||
|
get "/through_vegetables" => "foos#through_vegetables"
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
@plugin.write "config/routes.rb", <<-RUBY
|
||||||
|
Bukkits::Engine.routes.draw do
|
||||||
|
resources :posts, only: :index
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
boot_rails
|
||||||
|
|
||||||
|
get("/through_fruits")
|
||||||
|
assert_equal "/fruits/bukkits/posts", last_response.body
|
||||||
|
|
||||||
|
get("/through_vegetables")
|
||||||
|
assert_equal "/vegetables/bukkits/posts", last_response.body
|
||||||
|
end
|
||||||
|
|
||||||
|
test "isolated engine can be mounted under multiple dynamic locations" do
|
||||||
|
app_file "app/controllers/foos_controller.rb", <<-RUBY
|
||||||
|
class FoosController < ApplicationController
|
||||||
|
def through_fruits
|
||||||
|
render plain: fruit_bukkits.posts_path(fruit_id: 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
def through_vegetables
|
||||||
|
render plain: vegetable_bukkits.posts_path(vegetable_id: 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
app_file "config/routes.rb", <<-RUBY
|
||||||
|
Rails.application.routes.draw do
|
||||||
|
resources :fruits do
|
||||||
|
mount Bukkits::Engine => "/bukkits"
|
||||||
|
end
|
||||||
|
|
||||||
|
resources :vegetables do
|
||||||
|
mount Bukkits::Engine => "/bukkits"
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/through_fruits" => "foos#through_fruits"
|
||||||
|
get "/through_vegetables" => "foos#through_vegetables"
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
@plugin.write "config/routes.rb", <<-RUBY
|
||||||
|
Bukkits::Engine.routes.draw do
|
||||||
|
resources :posts, only: :index
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
boot_rails
|
||||||
|
|
||||||
|
get("/through_fruits")
|
||||||
|
assert_equal "/fruits/1/bukkits/posts", last_response.body
|
||||||
|
|
||||||
|
get("/through_vegetables")
|
||||||
|
assert_equal "/vegetables/1/bukkits/posts", last_response.body
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def app
|
def app
|
||||||
Rails.application
|
Rails.application
|
||||||
|
|
Loading…
Reference in a new issue