3

我今天遇到了一些麻烦,无法跳出框框来解决这个问题。

基本上我有一个名为 Airplane 的模型,它有_many Payments。每笔付款可以分成许多分期付款。好的!

这是信息:

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

所以,我想要做的是,当分期付款的总和等于或大于机票价值时,Airplane.paid 将是真实的。我正在使用 before_save "checks_if_everything_has_been_paid 来做到这一点。但它仅在飞机字段发生更改时才有效。

当付款和分期付款字段都发生变化时,我该如何运行这个课程?

我想在每次更改分期付款或付款本身时检查付款是否完成。

谢谢!

4

2 回答 2

2

不要after save在 Airplane 模型上定义回调,而是after_addpayments关联上定义回调。

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

更新:如果我正确理解您的数据模型,我认为以下可能是更好的方法。如果付款或分期付款被保存,它将触发飞机检查全额付款:

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

这种方法的好处是付款和分期付款中的逻辑是相同的,因此您可以将其提取到一个模块中:

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
于 2014-07-25T01:14:43.523 回答
0

您可以尝试设置:autosave您的belongs_to关联。如果可行,这是一个聪明的解决方案:)。

更好的选择可能是创建一个after_save要求 Airplane 检查自身的钩子。

class Airplane
  has_many :payments

  def check_for_paid
    # use payments(true) to force the association to reload
    if payments(true).all?(&:paid?)
      paid = true
      save
    end
  end
end

class Payment
  # associations

  def paid?
    installments(true).all?(&:paid?)
  end
end

class Installment
  after_save :check_for_paid

  def check_for_paid
    payment.airplane.check_for_paid
  end
end

通过这种方式,可以更清楚地了解正在发生的事情和原因。不过,另一个肯定会更聪明。

于 2014-07-25T00:12:12.470 回答