简体   繁体   中英

How can I skip before_validations in Rails?

I have code that updates/fixes some model data in my before_validation callbacks.

However, I'd like to be able to still run validations to see if a model is ok as-is.

More specifically, i'd like to know if a record in the database is valid or not. So I'd like to be able to load a value and ask .valid? without having my callbacks run that would affect the answer.

So, I tried this (and a few variations) but it didn't work:

skip_callback :validation, :before, unless: ->{self.changed?}

The docs for skip_callback are poor, so I'm not sure I'm using it properly. Can this be made to work?

Thanks.

According to APIDock skip_callback takes callback_name , then *filter_lists as arguments (then a block).

filter_list must include your callback method name. Like this below.

class User < ActiveRecord::Base
  validates_presence_of :name
  before_validation :set_name

  skip_callback :validation, :before, :set_name, unless: -> { self.changed? }

  def set_name
    self.name ||= 'foobar'
  end
end

#<User:0x007ffcd7165248 id: 2, name: nil, created_at: Fri, 03 Feb 2017 01:10:37 UTC +00:00, updated_at: Fri, 03 Feb 2017 01:10:37 UTC +00:00>

User.find(2).valid? # returns false

user = User.find(2)
user.updated_at = Time.now
user.valid? # returns true, because it invokes :set_name before validation

You can skip any callback. You have to skip the callback and do the transaction and set the call back again. Model.skip_callback(:callback_name, :callback_position, :callback_action_name)

For eg.

class ModelName < ApplicationRecord 
    before_validation :validation_action
    
    def validation_action
    end 

end 

To skip this validation when calling ModelName

ModelName.skip_validation(:validation, :before, :validation_action)
ModelName.create!()
ModelName.set_validation(:validation, :before, :validation_action)

Similarly, you can skip all callbacks from here

.. I'd like to be able to .. ask .valid? without having my callbacks run that would affect the answer.

Make the validation conditional on an attr_accessor .

# banana.rb
attr_accessor :use_validation_callbacks
before_validation :derp, if: { |b| b.use_validation_callbacks }
def initialize(*)
  self.use_validation_callbacks = true
  super
end

# elsewhere
banana = Banana.new
banana.use_validation_callbacks = false
banana.valid?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM