Skip to content

Commit 1325bda

Browse files
authored
Merge pull request #612 from fatkodima/multiple-databases-migration-cops
Support multiple databases for `ReversibleMigration` and `ReversibleMigrationMethodDefinition` cops
2 parents 07cfcb4 + bad5645 commit 1325bda

File tree

8 files changed

+86
-15
lines changed

8 files changed

+86
-15
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* [#463](https://github.com/rubocop/rubocop-rails/issues/463): Support multiple databases for `ReversibleMigration` and `ReversibleMigrationMethodDefinition` cops. ([@fatkodima][])

config/default.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -702,15 +702,17 @@ Rails/ReversibleMigration:
702702
Reference: 'https://api.rubyonrails.org/classes/ActiveRecord/Migration/CommandRecorder.html'
703703
Enabled: true
704704
VersionAdded: '0.47'
705+
VersionChanged: '<<next>>'
705706
Include:
706-
- db/migrate/*.rb
707+
- db/**/*.rb
707708

708709
Rails/ReversibleMigrationMethodDefinition:
709710
Description: 'Checks whether the migration implements either a `change` method or both an `up` and a `down` method.'
710711
Enabled: false
711712
VersionAdded: '2.10'
713+
VersionChanged: '<<next>>'
712714
Include:
713-
- db/migrate/*.rb
715+
- db/**/*.rb
714716

715717
Rails/RootJoinChain:
716718
Description: 'Use a single `#join` instead of chaining on `Rails.root` or `Rails.public_path`.'
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# frozen_string_literal: true
2+
3+
module RuboCop
4+
module Cop
5+
# Common functionality for cops working with migrations
6+
module MigrationsHelper
7+
extend NodePattern::Macros
8+
9+
def_node_matcher :migration_class?, <<~PATTERN
10+
(class
11+
(const nil? _)
12+
(send
13+
(const (const {nil? cbase} :ActiveRecord) :Migration)
14+
:[]
15+
(float _))
16+
_)
17+
PATTERN
18+
19+
def in_migration?(node)
20+
node.each_ancestor(:class).any? do |class_node|
21+
migration_class?(class_node)
22+
end
23+
end
24+
end
25+
end
26+
end

lib/rubocop/cop/rails/reversible_migration.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ module Rails
176176
#
177177
# @see https://api.rubyonrails.org/classes/ActiveRecord/Migration/CommandRecorder.html
178178
class ReversibleMigration < Base
179+
include MigrationsHelper
180+
179181
MSG = '%<action>s is not reversible.'
180182

181183
def_node_matcher :irreversible_schema_statement_call, <<~PATTERN
@@ -207,7 +209,7 @@ class ReversibleMigration < Base
207209
PATTERN
208210

209211
def on_send(node)
210-
return unless within_change_method?(node)
212+
return unless in_migration?(node) && within_change_method?(node)
211213
return if within_reversible_or_up_only_block?(node)
212214

213215
check_irreversible_schema_statement_node(node)
@@ -220,7 +222,7 @@ def on_send(node)
220222
end
221223

222224
def on_block(node)
223-
return unless within_change_method?(node)
225+
return unless in_migration?(node) && within_change_method?(node)
224226
return if within_reversible_or_up_only_block?(node)
225227
return if node.body.nil?
226228

lib/rubocop/cop/rails/reversible_migration_method_definition.rb

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,19 +43,11 @@ module Rails
4343
# end
4444
# end
4545
class ReversibleMigrationMethodDefinition < Base
46+
include MigrationsHelper
47+
4648
MSG = 'Migrations must contain either a `change` method, or ' \
4749
'both an `up` and a `down` method.'
4850

49-
def_node_matcher :migration_class?, <<~PATTERN
50-
(class
51-
(const nil? _)
52-
(send
53-
(const (const {nil? cbase} :ActiveRecord) :Migration)
54-
:[]
55-
(float _))
56-
_)
57-
PATTERN
58-
5951
def_node_matcher :change_method?, <<~PATTERN
6052
[ #migration_class? `(def :change (args) _) ]
6153
PATTERN

lib/rubocop/cop/rails_cops.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
require_relative 'mixin/active_record_migrations_helper'
55
require_relative 'mixin/enforce_superclass'
66
require_relative 'mixin/index_method'
7+
require_relative 'mixin/migrations_helper'
78
require_relative 'mixin/target_rails_version'
89

910
require_relative 'rails/action_filter'

spec/rubocop/cop/rails/reversible_migration_method_definition_spec.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,28 @@ def change
106106
end
107107
RUBY
108108
end
109+
110+
context 'when multiple databases' do
111+
it 'does not register an offense with a change method' do
112+
expect_no_offenses(<<~RUBY, 'db/animals_migrate/20211007000002_add_nice_to_animals.rb')
113+
class AddNiceToAnimals < ActiveRecord::Migration[7.0]
114+
def change
115+
add_column :animals, :nice, :boolean, default: true
116+
end
117+
end
118+
RUBY
119+
end
120+
121+
it 'registers an offense with only an up method' do
122+
expect_offense(<<~RUBY, 'db/animals_migrate/20211007000002_add_nice_to_animals.rb')
123+
class AddNiceToAnimals < ActiveRecord::Migration[7.0]
124+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Migrations must contain either a `change` method, or both an `up` and a `down` method.
125+
126+
def up
127+
add_column :animals, :nice, :boolean, default: true
128+
end
129+
end
130+
RUBY
131+
end
132+
end
109133
end

spec/rubocop/cop/rails/reversible_migration_spec.rb

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
RSpec.describe RuboCop::Cop::Rails::ReversibleMigration, :config do
44
let(:source) do
55
<<~RUBY
6-
class ExampleMigration < ActiveRecord::Migration
6+
class ExampleMigration < ActiveRecord::Migration[7.0]
77
def change
88
#{code}
99
end
@@ -293,4 +293,27 @@ def change
293293
remove_index(:posts, name: :index_columns_on_body)
294294
RUBY
295295
end
296+
297+
context 'when multiple databases' do
298+
it 'does not register an offense for reversible operation' do
299+
expect_no_offenses(<<~RUBY, 'db/animals_migrate/20211007000002_create_animals.rb')
300+
class CreateAnimals < ActiveRecord::Migration[7.0]
301+
def change
302+
create_table :animals
303+
end
304+
end
305+
RUBY
306+
end
307+
308+
it 'registers an offense for irreversible operation' do
309+
expect_offense(<<~RUBY, 'db/animals_migrate/20211007000002_remove_animals.rb')
310+
class RemoveAnimals < ActiveRecord::Migration[7.0]
311+
def change
312+
drop_table :animals
313+
^^^^^^^^^^^^^^^^^^^ drop_table(without block) is not reversible.
314+
end
315+
end
316+
RUBY
317+
end
318+
end
296319
end

0 commit comments

Comments
 (0)