Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new Rails/RootPathnameMethods cop #587

Merged
merged 1 commit into from Jul 19, 2022

Conversation

leoarnold
Copy link
Contributor

@leoarnold leoarnold commented Nov 21, 2021

Rails.root is an instance of Pathname. So instead of

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)

we can simply write

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)

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


Before submitting the PR make sure the following are checked:

  • Wrote good commit messages.
  • Commit message starts with [Fix #issue-number] (if the related issue exists).
  • Feature branch is up-to-date with master (if not - rebase it).
  • Squashed related commits together.
  • Added tests.
  • Added an entry (file) to the changelog folder named {change_type}_{change_description}.md if the new code introduces user-observable changes. See changelog entry format for details.
  • The PR relates to only one subject with a clear title
    and description in grammatically correct, complete sentences.
  • Run bundle exec rake default. It executes all tests and RuboCop for itself, and generates the documentation.
  • If this is a new cop, consider making a corresponding update to the Rails Style Guide.

Copy link
Member

@pirj pirj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, thank you!
A few cosmetic notes. Wondering if those different node patterns can be collapsed into one.

lib/rubocop/cop/rails/root_pathname_methods.rb Outdated Show resolved Hide resolved
lib/rubocop/cop/rails/root_pathname_methods.rb Outdated Show resolved Hide resolved
lib/rubocop/cop/rails/root_pathname_methods.rb Outdated Show resolved Hide resolved
lib/rubocop/cop/rails/root_pathname_methods.rb Outdated Show resolved Hide resolved
lib/rubocop/cop/rails/root_pathname_methods.rb Outdated Show resolved Hide resolved
leoarnold added a commit to leoarnold/rubocop-rspec that referenced this pull request Nov 21, 2021
`RSpec` provides the convenience method

```ruby
file_fixture('path/some_file.csv')
```

which (by default) is equivalent to

```ruby
Rails.root.join('spec/fixtures/files/path/some_file.csv')
```

We add a cop which detects and autocorrects verbose `Rails.root`
constructions and works best in combination with
[`Rails/RootPathnameMethods`](rubocop/rubocop-rails#587).
config/default.yml Outdated Show resolved Hide resolved
CHANGELOG.md Outdated Show resolved Hide resolved
pirj added a commit to pirj/rubocop-rails that referenced this pull request Dec 4, 2021
pirj added a commit to pirj/rubocop-rails that referenced this pull request Dec 4, 2021
pirj added a commit to pirj/rubocop-rails that referenced this pull request Dec 4, 2021
pirj added a commit to pirj/rubocop-rails that referenced this pull request Dec 8, 2021
pirj added a commit to pirj/rubocop-rails that referenced this pull request Dec 9, 2021
@koic koic closed this in #594 Dec 10, 2021
koic added a commit that referenced this pull request Dec 10, 2021
…tion-on-belongs_to

[Fix #587] Add Rails/RedundantPresenceValidationOnBelongsTo cop
@koic koic reopened this Dec 10, 2021
@koic
Copy link
Member

koic commented Jul 16, 2022

@leoarnold ping :-)

@leoarnold leoarnold force-pushed the leoarnold/rails-pathname branch 8 times, most recently from c9e45ad to ef3f050 Compare July 16, 2022 22:34
@leoarnold
Copy link
Contributor Author

@koic Thanks for the ping. I resolved all comments.

Yet there is one very peculiar problem: codespell wants file test instead of FileTest (literal name of Ruby class from standard library)

codespell.txt Outdated Show resolved Hide resolved
@leoarnold leoarnold force-pushed the leoarnold/rails-pathname branch 2 times, most recently from b54990e to 5e3303d Compare July 17, 2022 11:03
unlink
].to_set.freeze

FILE_METHODS = %i[
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

File.methods - File.superclass.methods also returns e.g. :absolute_path which is not on those lists.
Which makes me think does it make sense to fill in those constants with those calls?
On the other hand, if the Ruby version with which rubocop is run is different from the target Ruby version, there might be differences.
However, does it matter much?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... but Pathname does not have a #absolute_path method. Not sure I can follow here.

I generated this list using

File.methods.sort.select do |m|
  Pathname.instance_methods.include?(m) && !Object.instance_methods.include?(m)
end

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood.
So basically (File.public_methods(false) & Pathname.instance_methods(false)).sort.
Does it make sense to set the constant to this statement?
What are the consequences? New methods being added on File and to Pathname in future Ruby versions change the behaviour of the cop?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, just because there is File.foo and Pathname#foo, it is not guaranteed that File.foo(p, ...) and p.foo(...) is the same, so I'd rather maintain a list of safe methods.

Also, there may be cases where the Ruby that runs Rubocop is not the Ruby which runs production code (e.g. you develop a gem on Ruby 2, but someone uses it on JRuby 9). Are those standard libraries necessarily equivalent?


RSpec.describe RuboCop::Cop::Rails::RootPathnameMethods, :config do
{
Dir: described_class::DIR_METHODS,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's my personal preference, but I don't feel too confident when some collections from the code are used in tests directly. It may sound far-fetched, but what if someone accidentally removes a line from that array? Specs won't fail.
I'll leave this to @koic to decide on.

`Rails.root` is an instance of `Pathname`. So instead of

```ruby
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)
```

we can simply write

```ruby
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)
```

This cop works best when used together with
[`Style/FileRead`](rubocop/rubocop#10261),
[`Style/FileWrite`](rubocop/rubocop#10260),
and [`Rails/RootJoinChain`](rubocop#586).
@koic
Copy link
Member

koic commented Jul 19, 2022

It covers possible use cases and is maintainable. It will take a while to ship, so we can adjust it later if necessary. Thank you.

@koic koic merged commit 3ad75cc into rubocop:master Jul 19, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants