rmagnum2002 rmagnum2002 - 2 months ago 16
Ruby Question

before save callback for boolean field

The before_save callback should update expired field value to

true
or
false
based on the code below:

class Package < ActiveRecord::Base
before_save :update_availabiltiy

def update_availabiltiy
self.expired = date_end.to_date < Date.today
end
end


but it won't work unless the value of this field is the same as stored one, in example: if this field is true in DB and the condition in callback will evaluate to true, record will be saved, otherwise controller will return 400

Started PUT "/api/venues/bogan-and-sons/packages/delicious-package" for ::1 at 2016-09-20 15:20:03 +0300
Processing by Api::PackagesController#update as JSON

Parameters: {"package"=>
{"date_start"=>"2016-08-27T00:00:00.000-04:00", "date_end"=>"2016-12-30, ...}
}
(0.2ms) BEGIN
(0.1ms) ROLLBACK
Completed 400 Bad Request in 81ms (Views: 0.6ms | ActiveRecord: 17.8ms)


object.errors returns empty array, so no actual error on object is present.

Update for Andrey:

[31, 40] in /Users/srosca/projects/venuezz/app/models/package.rb
31: !expired || (Date.today <= self.date_end.to_date)
32: end
33:
34: def update_availabiltiy
35: byebug
=> 36: self.expired = date_end.to_date < Date.today
37: end
38:
39: def calculate_discount
40: if discount_price
(byebug) expired
true
(byebug) date_end.to_date < Date.today
false
(byebug) self.expired = date_end.to_date < Date.today
false
(byebug) expired
false

Answer

The reason for the error is that before_save hooks have the ability to cancel save operation by returning false (which is what happens when your record is not expired.

Return something else, not result of the assignment. For example:

  def update_availabiltiy
    self.expired = date_end.to_date < Date.today

    true # no canceling
  end
Comments