diff --git a/CHANGELOG.md b/CHANGELOG.md index a6fd406349..429a470f44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ### Bug fixes * [#12](https://github.com/rubocop-hq/rubocop-rails/issues/12): Fix a false positive for `Rails/SkipsModelValidations` when passing a boolean literal to `touch`. ([@eugeneius][]) +* [#238](https://github.com/rubocop-hq/rubocop-rails/issues/238): Fix auto correction for `Rails/IndexBy` when the `.to_h` invocation is separated in multiple lines. ([@diogoosorio][]) ### Changes @@ -183,3 +184,4 @@ [@sunny]: https://github.com/sunny [@hoshinotsuyoshi]: https://github.com/hoshinotsuyoshi [@tejasbubane]: https://github.com/tejasbubane +[@diogoosorio]: https://github.com/diogoosorio diff --git a/lib/rubocop/cop/mixin/index_method.rb b/lib/rubocop/cop/mixin/index_method.rb index 2e8e2b5d5a..7659cb4679 100644 --- a/lib/rubocop/cop/mixin/index_method.rb +++ b/lib/rubocop/cop/mixin/index_method.rb @@ -112,7 +112,14 @@ def self.from_each_with_object(node, match) end def self.from_map_to_h(node, match) - strip_trailing_chars = node.parent&.block_type? ? 0 : '.to_h'.length + strip_trailing_chars = 0 + + unless node.parent&.block_type? + map_range = node.children.first.source_range + node_range = node.source_range + strip_trailing_chars = node_range.end_pos - map_range.end_pos + end + new(match, node.children.first, 0, strip_trailing_chars) end diff --git a/spec/rubocop/cop/rails/index_by_spec.rb b/spec/rubocop/cop/rails/index_by_spec.rb index 9566a5a1d3..13fa67190a 100644 --- a/spec/rubocop/cop/rails/index_by_spec.rb +++ b/spec/rubocop/cop/rails/index_by_spec.rb @@ -94,6 +94,34 @@ end end + context 'when `to_h` is on a different line' do + it 'registers an offense for `map { ... }.to_h`' do + expect_offense(<<~RUBY) + x.map { |el| [el.to_sym, el] }. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `index_by` over `map { ... }.to_h`. + to_h + RUBY + + expect_correction(<<~RUBY) + x.index_by { |el| el.to_sym } + RUBY + end + end + + context 'when `.to_h` is on a different line' do + it 'registers an offense for `map { ... }.to_h`' do + expect_offense(<<~RUBY) + x.map { |el| [el.to_sym, el] } + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `index_by` over `map { ... }.to_h`. + .to_h + RUBY + + expect_correction(<<~RUBY) + x.index_by { |el| el.to_sym } + RUBY + end + end + context 'when to_h is not called on the result' do it 'does not register an offense for `map { ... }.to_h`' do expect_no_offenses('x.map { |el| [el.to_sym, el] }')