-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add cop to guard again ActiveRecord::Base.transaction use
- Loading branch information
Showing
12 changed files
with
129 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
PATH | ||
remote: . | ||
specs: | ||
rubocop-vendor (0.12.2) | ||
rubocop-vendor (0.13.0) | ||
rubocop | ||
|
||
GEM | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
82 changes: 82 additions & 0 deletions
82
lib/rubocop/cop/vendor/active_record_base_transaction_use.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module Cop | ||
module Vendor | ||
# Flags uses of ActiveRecord::Base.transaction, | ||
# as subclasses of ActiveRecord::Base may use a different | ||
# database connection. | ||
# | ||
# This becomes relevant if, for instance, your application | ||
# defines models or any subclass of ActiveRecord::Base | ||
# specifying connection configurations, e.g. using `connects_to`. | ||
# | ||
# The guarantee that transaction connection matches the | ||
# model connection is strongest when `MyModelClass.transaction` | ||
# wraps database operations on instances of MyModelClass only. | ||
# | ||
# If multiple model classes are involved in a .transaction | ||
# call, `.transaction` only needs to be called on one of them, | ||
# or a common ancestor sharing the same connection | ||
# if both models share the same underlying connection. | ||
# | ||
# If not, a workaround would be to open a transaction on both | ||
# model classes. | ||
# | ||
# @example | ||
# | ||
# # bad | ||
# ActiveRecord::Base.transaction do | ||
# ... database operations | ||
# end | ||
# | ||
# # good | ||
# MyModelClass.transaction do | ||
# ... database operations on instances of MyModelClass | ||
# end | ||
# | ||
# # also good | ||
# my_model_instance.with_lock do | ||
# ... database operations on my_model_instance | ||
# end | ||
# | ||
# # good if and only if both models share a database connection | ||
# MyModelClass.transaction do | ||
# ... database operations on instances of MyModelClass | ||
# ... database operations on instances of MyOtherModelClass | ||
# end | ||
# | ||
# # good if and only if ApplicationRecord shares a database | ||
# # connection with all models involved | ||
# ApplicationRecord.transaction do | ||
# ... database operations on instances of MyModelClass | ||
# ... database operations on instances of MyOtherModelClass | ||
# end | ||
# | ||
# # good if the models do not share a database connection | ||
# MyModelClass.transaction do | ||
# MyOtherModelClass.transaction do | ||
# ... database operations on instances of MyModelClass | ||
# ... database operations on instances of MyOtherModelClass | ||
# end | ||
# end | ||
# | ||
class ActiveRecordBaseTransactionUse < Base | ||
MSG = 'Avoid using `ActiveRecord::Base.transaction, as models inheriting a subclass of ActiveRecord::Base may use a different database connection from ActiveRecord::Base.connection.' | ||
|
||
# @!method uses_active_record_base?(node) | ||
def_node_matcher :uses_active_record_base?, <<-PATTERN | ||
(const (const {nil? cbase} :ActiveRecord) :Base) | ||
PATTERN | ||
|
||
def on_send(node) | ||
receiver_node, method_name = *node | ||
|
||
return unless uses_active_record_base?(receiver_node) && method_name == :transaction | ||
|
||
add_offense(node) | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,6 @@ | |
|
||
module RuboCop | ||
module Vendor | ||
VERSION = '0.12.2' | ||
VERSION = '0.13.0' | ||
end | ||
end |
30 changes: 30 additions & 0 deletions
30
spec/rubocop/cop/vendor/active_record_base_transaction_use_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
RSpec.describe RuboCop::Cop::Vendor::ActiveRecordBaseTransactionUse, :config do | ||
subject(:cop) { described_class.new } | ||
|
||
let(:msg) { 'Avoid using `ActiveRecord::Base.transaction, as models inheriting a subclass of ActiveRecord::Base may use a different database connection from ActiveRecord::Base.connection.' } | ||
|
||
it 'registers an offense for usage of ActiveRecord::Base.transaction' do | ||
expect_offense(<<~RUBY) | ||
class MyModel < ApplicationRecord | ||
def do_something | ||
ActiveRecord::Base.transaction do | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Vendor/ActiveRecordBaseTransactionUse: #{msg} | ||
nil | ||
end | ||
end | ||
end | ||
RUBY | ||
end | ||
|
||
it 'registers no offense for usage of MyModelClass.transaction' do | ||
expect_no_offenses(<<~RUBY) | ||
class MyModelClass < ApplicationRecord | ||
def do_something | ||
MyModelClass.transaction do | ||
nil | ||
end | ||
end | ||
end | ||
RUBY | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters