I am trying to figure out how to skip validations on a specific instance of an ActiveRecord object when my reservation model transitions on state machine via a rake task. I would like to skip all validations whenever reservation.close! is called. Would hope to call something like reservation.close!(:validate => false). FYI we are using https://github.com/pluginaweek/state_machine for state machine.
Here is a sample of my reservation model.
class Reservation < ActiveRecord::Base
validates :ride_id, :start_at, :end_at, presence: true
validate :proper_custom_price?, allow_nil: true, on: :update
validate :dates_valid?
validate :dates_make_sense?
scope :needs_close_transition, lambda { where("end_at < ?", Time.now).where("state" => ["requested", "negotiating", "approved"]) }
state_machine :initial => 'requested' do
all_prebooked = ["requested", "negotiating", "approved"]
event :close do
transition :from => all_prebooked,
:to => "precanceled"
end
before_transition :on => [:close] do |reservation|
reservation.cancel_reason = :admin
end
end
end
Here is a sample of my rake task.
namespace :reservation do
task :close => :environment do
puts "== close"
Reservation.needs_close_transition.each do |reservation|
puts "===> #{reservation.id}"
begin
reservation.close!(:validate => false)
rescue Exception => e
Airbrake.notify(e, error_message: e.message) if defined?(Airbrake)
end
end
end
I had the same problem, however I did not want to alter my current validations, so I checked the state machine code (version 1.2.0) and I found another solution, for your specific case it would be something like:
reservation.close!(false)
reservation.save(validate: false)
That will trigger all callbacks that you have defined in your state machine, and well this solution is working well for me.
When using the state_machine gem, the state
attribute is updated before the validations are run, so you can add an unless condition to the validation that tests the current state:
validates :start_at, :end_at, presence: true, unless: Proc.new {state == 'closed'}
If you want more complex logic, pass a method name symbox to unless
instead of a proc:
validates :start_at, :end_at, presence: true, unless: :requires_validation?
def requires_validation?
# complex logic to determine if the record should be validated
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With