diff --git a/changelog/fix_rails_file_path_to_detect_offenses_from_complex_string_interpolation.md b/changelog/fix_rails_file_path_to_detect_offenses_from_complex_string_interpolation.md new file mode 100644 index 0000000000..5f152c3b4d --- /dev/null +++ b/changelog/fix_rails_file_path_to_detect_offenses_from_complex_string_interpolation.md @@ -0,0 +1 @@ +* [#989](https://github.com/rubocop/rubocop-rails/pull/989): Fix `Rails/FilePath` to detect offenses from complex string interpolation. ([@r7kamura][]) diff --git a/lib/rubocop/cop/rails/file_path.rb b/lib/rubocop/cop/rails/file_path.rb index c3ffdaf95c..7da55ce58d 100644 --- a/lib/rubocop/cop/rails/file_path.rb +++ b/lib/rubocop/cop/rails/file_path.rb @@ -56,11 +56,8 @@ class FilePath < Base def on_dstr(node) return unless rails_root_nodes?(node) - return unless node.children.last.str_type? - - last_child_source = node.children.last.source - return unless last_child_source.start_with?('.') || last_child_source.include?(File::SEPARATOR) - return if last_child_source.start_with?(':') + return if dstr_separated_by_colon?(node) + return unless dstr_ending_with_file_extension?(node) || dstr_including_file_separator?(node) register_offense(node, require_to_s: false) end @@ -118,6 +115,22 @@ def build_message(require_to_s) format(message_template, to_s: to_s) end + + def dstr_ending_with_file_extension?(node) + node.children.last.str_type? && node.children.last.source.start_with?('.') + end + + def dstr_including_file_separator?(node) + node.children.any? do |child| + child.str_type? && child.source.include?(File::SEPARATOR) + end + end + + def dstr_separated_by_colon?(node) + node.children[1..].any? do |child| + child.str_type? && child.source.start_with?(':') + end + end end end end diff --git a/spec/rubocop/cop/rails/file_path_spec.rb b/spec/rubocop/cop/rails/file_path_spec.rb index a6e16e88f8..0dd3f60874 100644 --- a/spec/rubocop/cop/rails/file_path_spec.rb +++ b/spec/rubocop/cop/rails/file_path_spec.rb @@ -88,6 +88,15 @@ end end + context 'when using Rails.root called by double quoted string that ends with string interpolation' do + it 'registers an offense' do + expect_offense(<<~'RUBY') + "#{Rails.root}/a/#{b}" + ^^^^^^^^^^^^^^^^^^^^^^ Prefer `Rails.root.join('path/to')`. + RUBY + end + end + context 'when concat Rails.root and file separator using string interpolation' do it 'registers an offense' do expect_offense(<<~'RUBY')