Skip to content

Commit

Permalink
[Fix rubocop#42] Add new Rails/PreferFetch cop
Browse files Browse the repository at this point in the history
  • Loading branch information
tejasbubane committed Jun 6, 2019
1 parent c4e05e5 commit 666b8a0
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 0 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## master (unreleased)

### New features

* [#42](https://github.com/rubocop-hq/rubocop-rails/issues/42): Add new `Rails/PreferFetch` cop. ([@tejasbubane][])

## 2.0.0 (2019-05-22)

### New features
Expand All @@ -11,3 +15,4 @@

[@koic]: https://github.com/koic
[@andyw8]: https://github.com/andyw8
[@tejasbubane]: https://github.com/tejasbubane
5 changes: 5 additions & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ Rails/CreateTableWithTimestamps:
Include:
- db/migrate/*.rb

Rails/CredentialsDirectAccess:
Description: 'Checks for access of app secrets and credentials.'
Enabled: true
VersionAdded: '2.0.1'

Rails/Date:
Description: >-
Checks the correct usage of date aware methods,
Expand Down
40 changes: 40 additions & 0 deletions lib/rubocop/cop/rails/credentials_direct_access.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# frozen_string_literal: true

module RuboCop
module Cop
module Rails
# This cop checks for access of app secrets and credentials.
# Direct access returns nil if the entry does not exist. This can happen
# with typo of entry name. Fetch raises an error upfront to avoid subtle
# issues with nil.
#
# @example
# # bad
# Rails.application.secrets.foo
# Rails.application.credentials.bar
#
# # good
# Rails.application.secrets.fetch(:foo)
# Rails.application.credentials.fetch(:bar)
# Rails.application.credentials.fetch(:baz, "default_baz")
class CredentialsDirectAccess < Cop
MSG = 'Prefer fetch over direct access.'

def_node_matcher :direct_access?, <<-PATTERN
(send (send (send (const nil? :Rails) :application) ${:secrets :credentials}) _)
PATTERN

def on_send(node)
add_offense(node, location: :selector) if direct_access?(node)
end

def autocorrect(node)
selector = node.loc.selector
lambda do |corrector|
corrector.replace(selector, "fetch(:#{selector.source})")
end
end
end
end
end
end
1 change: 1 addition & 0 deletions lib/rubocop/cop/rails_cops.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ module Cop
require_relative 'rails/blank'
require_relative 'rails/bulk_change_table'
require_relative 'rails/create_table_with_timestamps'
require_relative 'rails/credentials_direct_access'
require_relative 'rails/date'
require_relative 'rails/delegate'
require_relative 'rails/delegate_allow_blank'
Expand Down
1 change: 1 addition & 0 deletions manual/cops.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* [Rails/Blank](cops_rails.md#railsblank)
* [Rails/BulkChangeTable](cops_rails.md#railsbulkchangetable)
* [Rails/CreateTableWithTimestamps](cops_rails.md#railscreatetablewithtimestamps)
* [Rails/CredentialsDirectAccess](cops_rails.md#railscredentialsdirectaccess)
* [Rails/Date](cops_rails.md#railsdate)
* [Rails/Delegate](cops_rails.md#railsdelegate)
* [Rails/DelegateAllowBlank](cops_rails.md#railsdelegateallowblank)
Expand Down
24 changes: 24 additions & 0 deletions manual/cops_rails.md
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,30 @@ Name | Default value | Configurable values
--- | --- | ---
Include | `db/migrate/*.rb` | Array

## Rails/CredentialsDirectAccess

Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
--- | --- | --- | --- | ---
Enabled | Yes | Yes | - | -

This cop checks for access of app secrets and credentials.
Direct access returns nil if the entry does not exist. This can happen
with typo of entry name. Fetch raises an error upfront to avoid subtle
issues with nil.

### Examples

```ruby
# bad
Rails.application.secrets.foo
Rails.application.credentials.bar

# good
Rails.application.secrets.fetch(:foo)
Rails.application.credentials.fetch(:bar)
Rails.application.credentials.fetch(:baz, "default_baz")
```

## Rails/Date

Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
Expand Down
61 changes: 61 additions & 0 deletions spec/rubocop/cop/rails/credentials_direct_access_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Rails::CredentialsDirectAccess do
subject(:cop) { described_class.new(config) }

let(:config) { RuboCop::Config.new }

context 'secrets' do
it 'registers an offense when not using fetch' do
expect_offense(<<~RUBY)
Rails.application.secrets.foo
^^^ Prefer fetch over direct access.
Rails.application.secrets.bar
^^^ Prefer fetch over direct access.
RUBY
end

it 'does not register an offense with fetch' do
expect_no_offenses(<<~RUBY)
Rails.application.secrets.fetch(:foo)
RUBY
end

it 'autocorrects to fetch' do
new_source = autocorrect_source(<<~RUBY)
Rails.application.secrets.foo
RUBY

expect(new_source).to eq(<<~RUBY)
Rails.application.secrets.fetch(:foo)
RUBY
end
end

context 'credentials' do
it 'registers an offense when not using fetch' do
expect_offense(<<~RUBY)
Rails.application.credentials.foo
^^^ Prefer fetch over direct access.
Rails.application.credentials.bar
^^^ Prefer fetch over direct access.
RUBY
end

it 'does not register an offense with fetch' do
expect_no_offenses(<<~RUBY)
Rails.application.credentials.fetch(:foo)
RUBY
end

it 'autocorrects to fetch' do
new_source = autocorrect_source(<<~RUBY)
Rails.application.credentials.foo
RUBY

expect(new_source).to eq(<<~RUBY)
Rails.application.credentials.fetch(:foo)
RUBY
end
end
end

0 comments on commit 666b8a0

Please sign in to comment.