diff --git a/changelog/fix_index_by_index_with_enclosing_block.md b/changelog/fix_index_by_index_with_enclosing_block.md new file mode 100644 index 0000000000..2d8d6b6582 --- /dev/null +++ b/changelog/fix_index_by_index_with_enclosing_block.md @@ -0,0 +1 @@ +* [#1406](https://github.com/rubocop/rubocop-rails/pull/1406): Fix autocorrection for `Rails/IndexBy` and `Rails/IndexWith` when `map { ... }.to_h` is enclosed in another block. ([@franzliedke][], [@eugeneius][]) diff --git a/lib/rubocop/cop/mixin/index_method.rb b/lib/rubocop/cop/mixin/index_method.rb index 9174cebb35..17a5af8866 100644 --- a/lib/rubocop/cop/mixin/index_method.rb +++ b/lib/rubocop/cop/mixin/index_method.rb @@ -124,9 +124,9 @@ def self.from_to_h(node, match) end def self.from_map_to_h(node, match) - strip_trailing_chars = 0 - - unless node.parent&.block_type? + if node.block_literal? + strip_trailing_chars = 0 + else map_range = node.children.first.source_range node_range = node.source_range strip_trailing_chars = node_range.end_pos - map_range.end_pos diff --git a/spec/rubocop/cop/rails/index_by_spec.rb b/spec/rubocop/cop/rails/index_by_spec.rb index 5d7f4bf6d8..ab3cfded01 100644 --- a/spec/rubocop/cop/rails/index_by_spec.rb +++ b/spec/rubocop/cop/rails/index_by_spec.rb @@ -134,6 +134,27 @@ end end + context 'when enclosed in another block' do + it 'registers an offense for `map { ... }.to_h`' do + expect_offense(<<~RUBY) + wrapping do + x.map do |el| + ^^^^^^^^^^^^^ Prefer `index_by` over `map { ... }.to_h`. + [el.to_sym, el] + end.to_h + end + RUBY + + expect_correction(<<~RUBY) + wrapping do + x.index_by do |el| + el.to_sym + end + end + RUBY + end + end + it 'registers an offense for `Hash[map { ... }]`' do expect_offense(<<~RUBY) Hash[x.map { |el| [el.to_sym, el] }] diff --git a/spec/rubocop/cop/rails/index_with_spec.rb b/spec/rubocop/cop/rails/index_with_spec.rb index ea49367af7..d44c9509a8 100644 --- a/spec/rubocop/cop/rails/index_with_spec.rb +++ b/spec/rubocop/cop/rails/index_with_spec.rb @@ -107,6 +107,27 @@ end end + context 'when enclosed in another block' do + it 'registers an offense for `map { ... }.to_h`' do + expect_offense(<<~RUBY) + wrapping do + x.map do |el| + ^^^^^^^^^^^^^ Prefer `index_with` over `map { ... }.to_h`. + [el, el.to_sym] + end.to_h + end + RUBY + + expect_correction(<<~RUBY) + wrapping do + x.index_with do |el| + el.to_sym + end + end + RUBY + end + end + it 'registers an offense for `Hash[map { ... }]`' do expect_offense(<<~RUBY) Hash[x.map { |el| [el, el.to_sym] }]