Skip to content

Commit

Permalink
[Fix rubocop#227] Make Rails/UniqueValidationWithoutIndex aware of …
Browse files Browse the repository at this point in the history
…updating schema.rb

Fixes rubocop#227.

This PR makes `Rails/UniqueValidationWithoutIndex` aware of updating
db/schema.rb

`Rails/UniqueValidationWithoutIndex` cop needs to know both model
and db/schema.rb changes to register an offense. However, with
default RuboCop, only changes to the model affect cache behavior.

This PR ensures that changes to db/schema.rb affect the cache by
overriding the following method:

```ruby
# This method should be overridden when a cop's behavior depends
# on state that lives outside of these locations:
#
#   (1) the file under inspection
#   (2) the cop's source code
#   (3) the config (eg a .rubocop.yml file)
#
# For example, some cops may want to look at other parts of
# the codebase being inspected to find violations. A cop may
# use the presence or absence of file `foo.rb` to determine
# whether a certain violation exists in `bar.rb`.
#
# Overriding this method allows the cop to indicate to RuboCop's
# ResultCache system when those external dependencies change,
# ie when the ResultCache should be invalidated.
def external_dependency_checksum
  nil
end
```

https://github.com/rubocop-hq/rubocop/blob/v0.81.0/lib/rubocop/cop/cop.rb#L222-L239
  • Loading branch information
koic committed Apr 9, 2020
1 parent 02e73e4 commit 418d6c0
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 14 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## master (unreleased)

### Bug fixes

* [#227](https://github.com/rubocop-hq/rubocop-rails/issues/227): Make `Rails/UniqueValidationWithoutIndex` aware of updating db/schema.rb. ([@koic][])

## 2.5.1 (2020-04-02)

### Bug fixes
Expand Down
17 changes: 17 additions & 0 deletions lib/rubocop/cop/mixin/active_record_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,23 @@ module ActiveRecordHelper
(send nil? :belongs_to {str sym} ...)
PATTERN

def external_dependency_checksum
if defined?(@external_dependency_checksum)
return @external_dependency_checksum
end

schema_path = RuboCop::Rails::SchemaLoader.db_schema_path
return nil if schema_path.nil?

schema_code = File.read(schema_path)

@external_dependency_checksum ||= Digest::SHA1.hexdigest(schema_code)
end

def schema
RuboCop::Rails::SchemaLoader.load(target_ruby_version)
end

def table_name(class_node)
table_name = find_set_table_name(class_node).to_a.last&.first_argument
return table_name.value.to_s if table_name
Expand Down
4 changes: 0 additions & 4 deletions lib/rubocop/cop/rails/unique_validation_without_index.rb
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,6 @@ def array_node_to_array(node)
end
end
end

def schema
RuboCop::Rails::SchemaLoader.load(target_ruby_version)
end
end
end
end
Expand Down
20 changes: 10 additions & 10 deletions lib/rubocop/rails/schema_loader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,6 @@ def reset!
remove_instance_variable(:@schema)
end

private

def load!(target_ruby_version)
path = db_schema_path
return unless path

ast = parse(path, target_ruby_version)
Schema.new(ast)
end

def db_schema_path
path = Pathname.pwd
until path.root?
Expand All @@ -46,6 +36,16 @@ def db_schema_path
nil
end

private

def load!(target_ruby_version)
path = db_schema_path
return unless path

ast = parse(path, target_ruby_version)
Schema.new(ast)
end

def parse(path, target_ruby_version)
klass_name = :"Ruby#{target_ruby_version.to_s.sub('.', '')}"
klass = ::Parser.const_get(klass_name)
Expand Down
47 changes: 47 additions & 0 deletions spec/rubocop/cop/active_record_helper_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::ActiveRecordHelper, :isolated_environment do
include FileHelper

module RuboCop
module Cop
class Example < Cop
include ActiveRecordHelper
end
end
end

let(:cop) do
RuboCop::Cop::Example.new
end

let(:schema_path) { 'db/schema.rb' }

describe '#external_dependency_checksum' do
subject { cop.external_dependency_checksum }

context 'with db/schema.rb' do
before do
create_file(schema_path, <<~RUBY)
ActiveRecord::Schema.define(version: 2020_04_08_082625) do
create_table "articles" do |t|
t.string "title", null: false
end
end
RUBY
end

it { is_expected.to eq '1f263bed5ada8f2292ce7ceebd3c518bac3d2d1d' }
end

context 'with empty db/schema.rb' do
before { create_empty_file(schema_path) }

it { is_expected.to eq 'adc83b19e793491b1c6ea0fd8b46cd9f32e592fc' }
end

context 'without db/schema.rb' do
it { is_expected.to be_nil }
end
end
end

0 comments on commit 418d6c0

Please sign in to comment.