lib/rails/generators/actions.rb in railties-7.0.0 vs lib/rails/generators/actions.rb in railties-7.0.1

- old
+ new

@@ -277,30 +277,36 @@ # Make an entry in Rails routing file <tt>config/routes.rb</tt> # # 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 # Reads the given file at the source root and prints it in the console. # @@ -361,10 +367,11 @@ # Returns optimized string with indentation def optimize_indentation(value, amount = 0) # :doc: 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: " " * @indentation end @@ -384,9 +391,19 @@ end end 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