如何检查ActiveRecord模型的实例是否是最新的?

时间:2014-02-04 19:26:06

标签: ruby activerecord

出于测试原因,我想检查我的某个方法是否未更新数据库中的特定条目。如果ActiveRecord模型的实例与数据库同步,是否有一种简单的方法可以询问它?例如,如果我们有一个方法foobar?这可以做到这一点:

old_post = Post.find(1)
updated_post = Post.find(1)
updated_post.update_attributes(name: "this is a new name not like the old name")

old_post.foobar? #should return true, as its attributes are no longer up to date
updated_post.foobar? #should return false, as its attributes match the database directly

那么有一种方法就像foobar,或类似的东西?提前致谢。

1 个答案:

答案 0 :(得分:0)

我认为你的问题不仅仅是找到一个告诉你属性已被更新的方法,而是在实例化的不同对象之间的关系中。首先,重要的是要了解,old_postupdated_post无关的 ruby​​对象。他们知道如何将他们自己的状态保存到数据库中,但是他们彼此不了解。

因此,无法满足foobar?的第一个要求,因为只要没有更新任何属性,old_post就会认为它是最新的。相比之下,changed?方法将大致回答您尝试为updated_post实现的方式。但它是这样做的,因为认为自上次保存以来没有发生任何事情,每次调用changed?时都不会对数据库进行验证,因为这会浪费99.9中的数据库调用所有案例的百分比。

这意味着在您创建的对象之间生成异常非常容易,因为两者之间没有直接连接(除了它们曾经表示相同数据库行的隐式连接)。如果您更改一个对象中的属性(使用例如title='?',它将更改对象的值并记下changed - 数组中的更改。保存此对象后,它将保存其< em>将属性更改为数据库(通过创建单独构造的update - 语句)。

另一个已经实例化的对象 (在您的示例中为old_post知道此更改,如果您不小心可能会更改其他属性(如果再次更改,甚至是相同的)。根据您的数据库适配器,您可以尝试使用{em>将将对象与数据库同步的lock!方法,然后再进行任何修改。然而,这不会自动发生,因为在大多数控制器方法中,更新几乎不会发生冲突而值得同步,因为在大多数情况下它将是幂等的。

如果你想为你的控制器方法保证特定的ACID语义,那么rails不会让你无法考虑你的事务语义。