mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #43984 from jonathanhefner/fix-route-action-revocation
Fix generated route revocation
This commit is contained in:
commit
f9761739a3
2 changed files with 76 additions and 15 deletions
|
@ -279,26 +279,32 @@ module Rails
|
|||
# route "root 'welcome#index'"
|
||||
# route "root 'admin#index'", namespace: :admin
|
||||
def route(routing_code, namespace: nil)
|
||||
routing_code = Array(namespace).reverse.reduce(routing_code) do |code, ns|
|
||||
"namespace :#{ns} do\n#{optimize_indentation(code, 2)}end"
|
||||
namespace = Array(namespace)
|
||||
namespace_pattern = route_namespace_pattern(namespace)
|
||||
routing_code = namespace.reverse.reduce(routing_code) do |code, name|
|
||||
"namespace :#{name} do\n#{rebase_indentation(code, 2)}end"
|
||||
end
|
||||
|
||||
log :route, routing_code
|
||||
|
||||
after_pattern = Array(namespace).each_with_index.reverse_each.reduce(nil) do |pattern, (ns, i)|
|
||||
margin = "\\#{i + 1}[ ]{2}"
|
||||
"(?:(?:^[ ]*\n|^#{margin}.*\n)*?^(#{margin})namespace :#{ns} do\n#{pattern})?"
|
||||
end.then do |pattern|
|
||||
/^([ ]*).+\.routes\.draw do[ ]*\n#{pattern}/
|
||||
end
|
||||
|
||||
in_root do
|
||||
if existing = match_file("config/routes.rb", after_pattern)
|
||||
base_indent, *, prev_indent = existing.captures.compact.map(&:length)
|
||||
routing_code = optimize_indentation(routing_code, base_indent + 2).lines.grep_v(/^[ ]{,#{prev_indent}}\S/).join
|
||||
if namespace_match = match_file("config/routes.rb", namespace_pattern)
|
||||
base_indent, *, existing_block_indent = namespace_match.captures.compact.map(&:length)
|
||||
existing_line_pattern = /^[ ]{,#{existing_block_indent}}\S.+\n?/
|
||||
routing_code = rebase_indentation(routing_code, base_indent + 2).gsub(existing_line_pattern, "")
|
||||
namespace_pattern = /#{Regexp.escape namespace_match.to_s}/
|
||||
end
|
||||
|
||||
inject_into_file "config/routes.rb", routing_code, after: after_pattern, verbose: false, force: false
|
||||
inject_into_file "config/routes.rb", routing_code, after: namespace_pattern, verbose: false, force: false
|
||||
|
||||
if behavior == :revoke && namespace.any? && namespace_match
|
||||
empty_block_pattern = /(#{namespace_pattern})((?:\s*end\n){1,#{namespace.size}})/
|
||||
gsub_file "config/routes.rb", empty_block_pattern, verbose: false, force: true do |matched|
|
||||
beginning, ending = empty_block_pattern.match(matched).captures
|
||||
ending.sub!(/\A\s*end\n/, "") while !ending.empty? && beginning.sub!(/^[ ]*namespace .+ do\n\s*\z/, "")
|
||||
beginning + ending
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -363,6 +369,7 @@ module Rails
|
|||
return "#{value}\n" unless value.is_a?(String)
|
||||
"#{value.strip_heredoc.indent(amount).chomp}\n"
|
||||
end
|
||||
alias rebase_indentation optimize_indentation
|
||||
|
||||
# Indent the +Gemfile+ to the depth of @indentation
|
||||
def indentation # :doc:
|
||||
|
@ -387,6 +394,16 @@ module Rails
|
|||
def match_file(path, pattern)
|
||||
File.read(path).match(pattern) if File.exist?(path)
|
||||
end
|
||||
|
||||
def route_namespace_pattern(namespace)
|
||||
namespace.each_with_index.reverse_each.reduce(nil) do |pattern, (name, i)|
|
||||
cummulative_margin = "\\#{i + 1}[ ]{2}"
|
||||
blank_or_indented_line = "^[ ]*\n|^#{cummulative_margin}.*\n"
|
||||
"(?:(?:#{blank_or_indented_line})*?^(#{cummulative_margin})namespace :#{name} do\n#{pattern})?"
|
||||
end.then do |pattern|
|
||||
/^([ ]*).+\.routes\.draw do[ ]*\n#{pattern}/
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -648,6 +648,43 @@ class ActionsTest < Rails::Generators::TestCase
|
|||
ROUTING_CODE
|
||||
end
|
||||
|
||||
test "route with namespace option revokes route without breaking existing namespace blocks" do
|
||||
run_generator
|
||||
action :route, <<~ROUTING_CODE.chomp
|
||||
namespace :baz do
|
||||
get 'foo1'
|
||||
namespace :qux do
|
||||
get 'foo2'
|
||||
namespace :hoge do
|
||||
get 'foo3'
|
||||
end
|
||||
end
|
||||
get 'bar1'
|
||||
end
|
||||
ROUTING_CODE
|
||||
|
||||
revoke :route, "get 'foo2'", namespace: %w[baz qux]
|
||||
assert_routes <<~ROUTING_CODE.chomp
|
||||
namespace :baz do
|
||||
get 'foo1'
|
||||
namespace :qux do
|
||||
namespace :hoge do
|
||||
get 'foo3'
|
||||
end
|
||||
end
|
||||
get 'bar1'
|
||||
end
|
||||
ROUTING_CODE
|
||||
|
||||
revoke :route, "get 'foo3'", namespace: %w[baz qux hoge]
|
||||
assert_routes <<~ROUTING_CODE.chomp
|
||||
namespace :baz do
|
||||
get 'foo1'
|
||||
get 'bar1'
|
||||
end
|
||||
ROUTING_CODE
|
||||
end
|
||||
|
||||
def test_readme
|
||||
run_generator
|
||||
assert_called(Rails::Generators::AppGenerator, :source_root, times: 2, returns: destination_root) do
|
||||
|
@ -682,8 +719,15 @@ class ActionsTest < Rails::Generators::TestCase
|
|||
end
|
||||
|
||||
private
|
||||
def action(*args, **kwargs, &block)
|
||||
capture(:stdout) { generator.send(*args, **kwargs, &block) }
|
||||
def action(...)
|
||||
capture(:stdout) { generator.send(...) }
|
||||
end
|
||||
|
||||
def revoke(...)
|
||||
original_behavior, generator.behavior = generator.behavior, :revoke
|
||||
action(...)
|
||||
ensure
|
||||
generator.behavior = original_behavior
|
||||
end
|
||||
|
||||
def assert_runs(commands, config = {}, &block)
|
||||
|
|
Loading…
Reference in a new issue