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