Class: RuboCop::Cop::DevDoc::Migration::AvoidBypassingValidation

Inherits:
Base
  • Object
show all
Defined in:
lib/rubocop/cop/dev_doc/migration/avoid_bypassing_validation.rb

Overview

Avoid methods that bypass validations and callbacks.

## Rationale Avoid bypassing validation unless absolutely necessary. Methods like ‘update_column`, `update_all`, `insert_all`, `upsert_all`, `delete_all`, and `save(validate: false)` skip validations and callbacks, which hides data integrity issues rather than surfacing them.

Even in migrations, check the code to see if there is any blatant reason why existing records may be invalid. If there is, fix those records first rather than bypassing validation.

 Bypasses validation  hides data integrity issues
Faq.where(purpose: nil).update_all(purpose: :intro)

✔️ Runs validation  surfaces problems early
Faq.where(purpose: nil).find_each do |faq|
  faq.purpose = :intro
  faq.save!
end

Examples:

# bad
Faq.where(purpose: nil).update_all(purpose: :intro)

# bad
user.update_column(:status, 'active')

# bad
user.save(validate: false)

# bad
User.insert_all(rows)

# good
Faq.where(purpose: nil).find_each do |faq|
  faq.purpose = :intro
  faq.save!
end

Constant Summary collapse

MESSAGES =
{
  update_column: 'Avoid `update_column`; it bypasses validations. Use `save!` instead.',
  update_columns: 'Avoid `update_columns`; it bypasses validations. Use `save!` instead.',
  update_all: 'Avoid `update_all`; it bypasses validations. Use `save!` in a loop instead.',
  insert_all: 'Avoid `insert_all`; it bypasses validations. Use `create!` in a loop, ' \
              'or `# rubocop:disable` with a reason if bulk-insert is intentional.',
  upsert_all: 'Avoid `upsert_all`; it bypasses validations. Use `create!`/`update!` in a loop, ' \
              'or `# rubocop:disable` with a reason if bulk-upsert is intentional.',
  delete_all: 'Avoid `delete_all`; it bypasses callbacks. Use `destroy_all` to run callbacks, ' \
              'or `# rubocop:disable` with a reason if bulk-delete is intentional.'
}.freeze
SAVE_MSG =
'Avoid `save(validate: false)`; it bypasses validations. Use `save!` instead.'.freeze
RESTRICT_ON_SEND =
%i[update_column update_columns update_all insert_all upsert_all delete_all save].freeze

Instance Method Summary collapse

Instance Method Details

#on_send(node) ⇒ Object



61
62
63
64
65
66
67
68
69
# File 'lib/rubocop/cop/dev_doc/migration/avoid_bypassing_validation.rb', line 61

def on_send(node)
  if node.method?(:save)
    return unless save_with_validate_false?(node)

    add_offense(node.loc.selector, message: SAVE_MSG)
  else
    add_offense(node.loc.selector, message: MESSAGES[node.method_name])
  end
end