Ruby on rails 如何从模型中检测属性更改?

Ruby on rails 如何从模型中检测属性更改?,ruby-on-rails,Ruby On Rails,我想在rails中创建一个回调函数,该函数在保存模型后执行 我有一个模型,索赔有一个属性“status”,它根据索赔的状态而变化,可能的值是挂起、背书、批准、拒绝 数据库具有默认值为“挂起”的“状态” 我希望在第一次创建模型或从一个状态更新到另一个状态后执行某些任务,具体取决于模型从哪个状态更改 我的想法是在模型中有一个函数: after_save :check_state def check_state # if status changed from nil t

我想在rails中创建一个回调函数,该函数在保存模型后执行

我有一个模型,索赔有一个属性“status”,它根据索赔的状态而变化,可能的值是挂起、背书、批准、拒绝

数据库具有默认值为“挂起”的“状态”

我希望在第一次创建模型或从一个状态更新到另一个状态后执行某些任务,具体取决于模型从哪个状态更改

我的想法是在模型中有一个函数:

    after_save :check_state

    def check_state
      # if status changed from nil to pending (created)
      do this

      # if status changed from pending to approved
      performthistask
     end

我的问题是,在模型中进行更改之前,如何检查以前的值?

我建议您查看一个可用的状态机插件:

任何一个都可以让您设置状态和状态之间的转换。非常有用且简单的方法来处理您的需求。

您应该查看模块: 您应该能够对索赔模型执行以下操作:

claim.status_changed?  # returns true if 'status' attribute has changed
claim.status_was       # returns the previous value of 'status' attribute
claim.status_change    # => ['old value', 'new value'] returns the old and 
                       # new value for 'status' attribute

claim.name = 'Bob'
claim.changed # => ["name"]
claim.changes # => {"name" => ["Bill", "Bob"]}
哦!!铁路的乐趣

你可以用这个

self.changed
它返回此记录中更改的所有列的数组

你也可以使用

self.changes

它以数组的形式返回更改的列的散列以及结果前后的散列

我在很多地方看到了这个问题的出现,所以我为它编写了一个小rubygem,以使代码更漂亮一点(并避免到处出现一百万条if/else语句):。
我希望这会有所帮助。

使用经过良好测试的解决方案(如gem)会更好。

对于Rails 5.1+,您应该使用active record属性方法:

已保存\u更改为\u属性?(属性名称,**选项)`

上次保存时此属性是否更改?这种方法是可行的 调用为
已保存\u将\u更改为\u名称?
而不是
已保存\u更改为\u属性?(“名称”)
。行为类似于
属性\u已更改?
。此方法在回调后到时非常有用 确定保存调用是否更改了某个属性

选项

from
传递时,此方法将返回false,除非原始 值等于给定的选项

传递时,此方法将返回false,除非该值为 更改为给定值

因此,如果您想根据属性值的变化调用某个方法,您的模型将如下所示:

class Claim < ApplicationRecord
  
  after_save :do_this, if: Proc.new { saved_change_to_status?(from: nil, to: 'pending') }

  after_save :do_that, if: Proc.new { saved_change_to_status?(from: 'pending', to: 'approved') }

  
  def do_this
    ..
    ..
  end

  def do_that
    ..
    ..
  end

end
类别声明
如果不想检查回调中的值更改,可以执行以下操作:

class Claim < ApplicationRecord

  after_save: :do_this, if: saved_change_to_status?


  def do_this
    ..
    ..
  end

end
类别声明
我要尝试一下rubyist aasm。假设我有类声明:enter_pending def enter_pending Notifier.deliver_pending_notification(self)end end end,数据库中的my status字段的默认值为“pending”。如果我在不填写状态字段的情况下执行Claim.create(以便运行'pending'),AASM会运行'enter_pending'方法吗?这在模型保存后不起作用,这是他要求的。@TomRossi,
dirty
调用在保存后
中起作用(在Rails 2.3和3.x中)。我已经用过好几次了。@TomRossi,脏标志在提交后被重置,因此它们在Rails 3.x中引入的
提交后
回调中不可用。保存后它们肯定会在
中工作。我不知道!我还以为它们在保存后就被重置了呢@几年前,托马罗西一世也是以同样的假设开始的。当我试图在保存后检查脏标志时,它起作用了。本质上,
after\u save
是对DML
之后的
和提交之前的
之间状态的回调。您可以在保存后通过抛出异常在
中终止整个事务。如果您想在保存后执行某些操作而不影响当前操作,请在提交后使用
self
:-)这只是一个小提示,说明没有必要在这些操作上使用
self.
——您可以只说
changed
changes
@user664833更具体地说,您可以在模型本身中省略
self
,但是您可以对任何具有
object.changed
object.changes
:)的对象调用这些