# Dirty

跟踪对象的变化情况。其实，它们都属于脏数据，所以起这名字。但有时候很有用，例如某个字段一经生成不允许更改，或者某字段每次更改要确保与上次不同。

使用 ActiveModel::Dirty，需要:

* include ActiveModel::Dirty
* 调用 `define_attribute_methods` 参数是你想跟踪的属性
* 在改变属性的值之前，调用 `attr_name_will_change!` (把 attr\_name 换成真正的属性名)
* 在改变属性的值之后，调用 `changes_applied`

举例:

```ruby
class Person
  include ActiveModel::Dirty

  define_attribute_methods :name

  def name
    @name
  end

  def name=(val)
    name_will_change! unless val == @name
    @name = val
  end

  def save
    # do persistence work
    changes_applied
  end

  def reload!
    # reset_changes
  end
end
```

运用 **Attribute Methods** 生成的方法，能精确跟踪到某属性：

```ruby
attribute_method_suffix '_changed?', '_change', '_will_change!', '_was'

attribute_method_affix prefix: 'restore_', suffix: '!'
```

下面是对它们的解释

```ruby
x_changed?     # 返回 true/false, x 属性有没有更改？
x_change       # 返回一个数组有两个元素，第 1 个为 x 属性更改前的值，第 2 个为 x 属性更改后的值
x_will_change! # 声明 x 元素已被更改，即使实际上它并没有更改。
x_was          # 根据 x_changed? 而来。
               # 如果有更改则返回 changed_attributes 里 x 属性的部分，没有更改则返回 x 属性的值

restore_x!     # 消除对 x 属性的更改
```

除上述方法外，还有

```ruby
changed?       # 返回 true/false，整个对象有没有被更改？
changed        # 返回一个数组，所有被更改的属性
changes        # 返回一个 Hash. key 被更改的元素，value 是一个数组
               # (有两个元素，第 1 个为 x 属性更改前的值，第 2 个为 x 属性更改后的值)
previous_changes   # 类似 changes, 区别是更新成功之后才使用。
                   # 返回一个 Hash. key 被更改的元素，value 是一个数组
                   # (有两个元素，第 1 个为 x 属性更改前的值，第 2 个为 x 属性更改后的值)
changed_attributes # 返回一个 Hash. key 为被更改的元素，value 为其更改之前的值
restore_attributes # 清除更改数据

changes_applied
clear_changes_information

attribute_previously_changed? # 对已经保存的对象，之前改变了哪些属性
attribute_previous_change # 改变的属性值是什么
```

Active Record 也有同名模块，它只是对这里的 Dirty 的封装，并且它并没有对外提供 API.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://kelby.gitbook.io/rails-beginner-s-guide/activemodel/active_model__rails/model_dirty.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
