检测上次更新期间属性值是否更改不适用于 Active Model Dirty
Detecting if value of attribute changed during last update doesnt work with Active Model Dirty
我试图在我的 rails 应用程序中发送通知电子邮件,仅当我的列状态值被当前更新修改时。我尝试按照某些 post 和 status_changed?
方法中的建议使用 Active Model Dirty。不幸的是,我的电子邮件从未发送过,因为@partnership.status_changed?持续 returns false 即使状态的值在上次更新期间确实发生了变化。这是我的控制器代码:
def update
authorize @partnership
if @partnership.update(partnership_params)
send_notification_email
render json: {success: "partnership successfully updated"}, status: 200
else
render_error(nil, @partnership)
end
end
private
def send_notification_email
PartnershipMailer.partnership_status_change(@partnership).deliver_now if @partnership.status_changed?
end
我还在我的模型中加入了 Active Model Dirty :
class Partnership < ActiveRecord::Base
include ActiveModel::Dirty
我做错了什么?
.update
也会在更新数据后保存模型,因此会重置脏值。尝试使用 .assign_attributes
。它只会分配属性,然后您可以检查更改,最后记得保存模型。
您可以尝试使用此方法查看活动记录的更改属性。
@partnership.changed.include?("status")
如果 returns 为真,则我们的状态属性已在此记录中更改。
这是您可以在最适合您的情况的模型中使用的一种单行方法:
after_commit :send_notification_email, if: Proc.new { |model| model.previous_changes[:status]}
正如@Thounder 指出的那样,每当您保存记录时,ActiveModel::Dirty
方法 <attribute>_changed?
都会被重置。因此,它只跟踪保存之间的变化。
对于您的用例,您要使用的是 previous_changes
方法,该方法 returns 一个散列,其键是已更改的属性,值是 2 个值的数组:旧和新的。
person = Person.new(name: "Bob")
person.name_changed? # => true
person.save
person.name_changed? # => false (reset when save called)
person.previous_changes # => { name: [nil, "Bob"] }
person.previous_changes[:name] # => returns a "truthy" statement if :name attribute changed
我的伪代码可能有误,但原理是可行的。之前就被这个"gotcha"坑过,希望Rails核心团队改一下
我理解他们的推理,但对我来说在保存后跟踪 <attribute>_changed?
更有意义,因为这对我来说似乎是常见的用例。
根据 docs 使用 @partnership.saved_change_to_status?
或 @partnership.saved_change_to_attribute(:status)
。
我试图在我的 rails 应用程序中发送通知电子邮件,仅当我的列状态值被当前更新修改时。我尝试按照某些 post 和 status_changed?
方法中的建议使用 Active Model Dirty。不幸的是,我的电子邮件从未发送过,因为@partnership.status_changed?持续 returns false 即使状态的值在上次更新期间确实发生了变化。这是我的控制器代码:
def update
authorize @partnership
if @partnership.update(partnership_params)
send_notification_email
render json: {success: "partnership successfully updated"}, status: 200
else
render_error(nil, @partnership)
end
end
private
def send_notification_email
PartnershipMailer.partnership_status_change(@partnership).deliver_now if @partnership.status_changed?
end
我还在我的模型中加入了 Active Model Dirty :
class Partnership < ActiveRecord::Base
include ActiveModel::Dirty
我做错了什么?
.update
也会在更新数据后保存模型,因此会重置脏值。尝试使用 .assign_attributes
。它只会分配属性,然后您可以检查更改,最后记得保存模型。
您可以尝试使用此方法查看活动记录的更改属性。
@partnership.changed.include?("status")
如果 returns 为真,则我们的状态属性已在此记录中更改。
这是您可以在最适合您的情况的模型中使用的一种单行方法:
after_commit :send_notification_email, if: Proc.new { |model| model.previous_changes[:status]}
正如@Thounder 指出的那样,每当您保存记录时,ActiveModel::Dirty
方法 <attribute>_changed?
都会被重置。因此,它只跟踪保存之间的变化。
对于您的用例,您要使用的是 previous_changes
方法,该方法 returns 一个散列,其键是已更改的属性,值是 2 个值的数组:旧和新的。
person = Person.new(name: "Bob")
person.name_changed? # => true
person.save
person.name_changed? # => false (reset when save called)
person.previous_changes # => { name: [nil, "Bob"] }
person.previous_changes[:name] # => returns a "truthy" statement if :name attribute changed
我的伪代码可能有误,但原理是可行的。之前就被这个"gotcha"坑过,希望Rails核心团队改一下
我理解他们的推理,但对我来说在保存后跟踪 <attribute>_changed?
更有意义,因为这对我来说似乎是常见的用例。
根据 docs 使用 @partnership.saved_change_to_status?
或 @partnership.saved_change_to_attribute(:status)
。