I am having some troubles today and cannot think outside the box to fix this one.
Basically I have a model called Airplane, which has_many Payments. Each payment can be divided in many Installments. Ok!
Here is the info:
Model Airplane
- has_many payments
- before_save :checks_if_everything_has_been_paid
Model Payment
- belongs_to airplane
- has_many installments
Model Installment
- belongs_to payment
So, what I want to do is when the sum of the installments be equal or greater than the Airplane ticket value then the Airplane.paid will be true. I am doing that using the before_save "checks_if_everything_has_been_paid. But it only works when there are changes on the Airplane fields.
How can I run this class when there are changes both in the Payment and Installment fields?
I want to check if the payment is completed everytime an installment is changed or the Payment itself.
Thank you!
Instead of defining an after save
callback on the Airplane model, define a after_add
callback on the payments
association.
class Airplane < ActiveRecord::Base
has_many :payments, after_add: :checks_if_everything_has_been_paid
def checks_if_everything_has_been_paid
# work some magic
end
end
Update: I think the following may be a better approach if I understand your data model correctly. If a payment or installment is saved it will trigger the airplane to check for full payment:
class Airplane < ActiveRecord::Base
has_many :payments
has_many :installments, through: :payments
def check_for_full_payment
# work some magic
end
end
class Payment < ActiveRecord::Base
belongs_to :airplane
has_many :installments
after_save :trigger_full_payment_check
def trigger_payments_check
airplane.check_for_full_payment
end
end
class Installment < ActiveRecord::Base
belongs_to :payment
delegate :airplane, to: :payment
after_save :trigger_full_payment_check
def trigger_payments_check
airplane.check_for_full_payment
end
end
The nice thing about this approach is that the logic in Payment and Installment is identical, so you can extract it to a module:
module TriggerFullPaymentCheck
def self.included(base)
base.after_save :trigger_full_payment_check
end
def trigger_payments_check
airplane.check_for_full_payment
end
end
class Airplane < ActiveRecord::Base
has_many :payments
has_many :installments, through: :payments
def check_for_full_payment
# work some magic
end
end
class Payment < ActiveRecord::Base
include TriggerFullPaymentCheck
belongs_to :airplane
has_many :installments
end
class Installment < ActiveRecord::Base
include TriggerFullPaymentCheck
belongs_to :payment
delegate :airplane, to: :payment
end