检测上次更新期间属性值是否更改不适用于 Active Model Dirty

Dav*_*mar 6 attributes controller ruby-on-rails activemodel

仅当当前更新修改了我的列状态值时,我才尝试在我的 rails 应用程序中发送通知电子邮件。我尝试按照某些帖子和status_changed?方法中的建议使用 Active Model Dirty 。不幸的是,我的电子邮件从未发送过,因为@partnership.status_changed?即使状态的值在上次更新期间确实发生了变化,也会不断返回 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
Run Code Online (Sandbox Code Playgroud)

我还在我的模型中包含了 Active Model Dirty :

class Partnership < ActiveRecord::Base
  include ActiveModel::Dirty
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么 ?

oll*_*lpu 5

.update更新数据后也会保存模型,因此重置脏值。尝试使用.assign_attributes. 它只会分配属性,然后您可以检查更改,最后记住保存模型。


Dan*_*n L 5

正如@Thounder 指出的那样,只要您保存记录,就会重置该ActiveModel::Dirty方法<attribute>_changed?。因此,它仅跟踪保存之间的更改。

对于您的用例,您要使用的是previous_changes方法,它返回一个哈希,其中键是更改的属性,值是 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
Run Code Online (Sandbox Code Playgroud)

我的伪代码可能有误,但原理可行。我以前被这个“陷阱”咬过,我希望 Rails 核心团队能改变它。

我理解他们的推理,但对我来说<attribute>_changed?在保存后跟踪更有意义,因为这对我来说似乎是常见的用例。