Class: RuboCop::Cop::Rails::RootPathnameMethods

Inherits:
Base
  • Object
show all
Extended by:
AutoCorrector
Includes:
RangeHelp
Defined in:
lib/rubocop/cop/rails/root_pathname_methods.rb

Overview

Use ‘Rails.root` IO methods instead of passing it to `File`.

‘Rails.root` is an instance of `Pathname` so we can apply many IO methods directly.

This cop works best when used together with ‘Style/FileRead`, `Style/FileWrite` and `Rails/RootJoinChain`.

Examples:

# bad
File.open(Rails.root.join('db', 'schema.rb'))
File.open(Rails.root.join('db', 'schema.rb'), 'w')
File.read(Rails.root.join('db', 'schema.rb'))
File.binread(Rails.root.join('db', 'schema.rb'))
File.write(Rails.root.join('db', 'schema.rb'), content)
File.binwrite(Rails.root.join('db', 'schema.rb'), content)
Dir.glob(Rails.root.join('db', 'schema.rb'))
Dir[Rails.root.join('db', 'schema.rb')]

# good
Rails.root.join('db', 'schema.rb').open
Rails.root.join('db', 'schema.rb').open('w')
Rails.root.join('db', 'schema.rb').read
Rails.root.join('db', 'schema.rb').binread
Rails.root.join('db', 'schema.rb').write(content)
Rails.root.join('db', 'schema.rb').binwrite(content)
Rails.root.glob("db/schema.rb")

Constant Summary collapse

MSG =
'`%<rails_root>s` is a `Pathname`, so you can use `%<replacement>s`.'
DIR_GLOB_METHODS =
%i[[] glob].to_set.freeze
DIR_NON_GLOB_METHODS =
%i[
  children
  delete
  each_child
  empty?
  entries
  exist?
  mkdir
  open
  rmdir
  unlink
].to_set.freeze
DIR_METHODS =
(DIR_GLOB_METHODS + DIR_NON_GLOB_METHODS).freeze
FILE_METHODS =
%i[
  atime
  basename
  binread
  binwrite
  birthtime
  blockdev?
  chardev?
  chmod
  chown
  ctime
  delete
  directory?
  dirname
  empty?
  executable?
  executable_real?
  exist?
  expand_path
  extname
  file?
  fnmatch
  fnmatch?
  ftype
  grpowned?
  join
  lchmod
  lchown
  lstat
  mtime
  open
  owned?
  pipe?
  read
  readable?
  readable_real?
  readlines
  readlink
  realdirpath
  realpath
  rename
  setgid?
  setuid?
  size
  size?
  socket?
  split
  stat
  sticky?
  symlink?
  sysopen
  truncate
  unlink
  utime
  world_readable?
  world_writable?
  writable?
  writable_real?
  write
  zero?
].to_set.freeze
FILE_TEST_METHODS =
%i[
  blockdev?
  chardev?
  directory?
  empty?
  executable?
  executable_real?
  exist?
  file?
  grpowned?
  owned?
  pipe?
  readable?
  readable_real?
  setgid?
  setuid?
  size
  size?
  socket?
  sticky?
  symlink?
  world_readable?
  world_writable?
  writable?
  writable_real?
  zero?
].to_set.freeze
FILE_UTILS_METHODS =
%i[chmod chown mkdir mkpath rmdir rmtree].to_set.freeze
RESTRICT_ON_SEND =
(DIR_METHODS + FILE_METHODS + FILE_TEST_METHODS + FILE_UTILS_METHODS).to_set.freeze

Instance Method Summary collapse

Instance Method Details

#on_send(node) ⇒ Object



192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/rubocop/cop/rails/root_pathname_methods.rb', line 192

def on_send(node)
  evidence(node) do |method, path, args, rails_root|
    replacement = if dir_glob?(node)
                    build_path_glob_replacement(path)
                  else
                    build_path_replacement(path, method, args)
                  end

    message = format(MSG, rails_root: rails_root.source, replacement: replacement)
    add_offense(node, message: message) do |corrector|
      corrector.replace(node, replacement)
    end
  end
end

#pathname_method_for_ruby_2_4_or_lower(node) ⇒ Object



166
167
168
169
170
171
172
173
# File 'lib/rubocop/cop/rails/root_pathname_methods.rb', line 166

def_node_matcher :pathname_method_for_ruby_2_4_or_lower, <<~PATTERN
  {
    (send (const {nil? cbase} :Dir) $DIR_NON_GLOB_METHODS $_ $...)
    (send (const {nil? cbase} {:IO :File}) $FILE_METHODS $_ $...)
    (send (const {nil? cbase} :FileTest) $FILE_TEST_METHODS $_ $...)
    (send (const {nil? cbase} :FileUtils) $FILE_UTILS_METHODS $_ $...)
  }
PATTERN

#pathname_method_for_ruby_2_5_or_higher(node) ⇒ Object



156
157
158
159
160
161
162
163
# File 'lib/rubocop/cop/rails/root_pathname_methods.rb', line 156

def_node_matcher :pathname_method_for_ruby_2_5_or_higher, <<~PATTERN
  {
    (send (const {nil? cbase} :Dir) $DIR_METHODS $_ $...)
    (send (const {nil? cbase} {:IO :File}) $FILE_METHODS $_ $...)
    (send (const {nil? cbase} :FileTest) $FILE_TEST_METHODS $_ $...)
    (send (const {nil? cbase} :FileUtils) $FILE_UTILS_METHODS $_ $...)
  }
PATTERN

#rails_root?(node) ⇒ Object



188
189
190
# File 'lib/rubocop/cop/rails/root_pathname_methods.rb', line 188

def_node_matcher :rails_root?, <<~PATTERN
  (send (const {nil? cbase} :Rails) {:root :public_path})
PATTERN