validate, callbackとacts_as_paranoidを組み合わせたときの挙動

## 環境
* ruby : 1.9.3p392
* rails : 3.2.13
* sqlite3 : 3.7.9
* rails3_acts_as_paranoid : 0.2.5
* この記事では、以下のモデルを使用する

```ruby
class User < ActiveRecord::Base
  acts_as_paranoid
  attr_accessible :email, :name, :tel

  validates :name, presence: true, uniqueness: true

  private

  def return_false
    false
  end

  def add_error
    errors.add(:base, 'added error')
  end

  def raise_error
    raise StandardError
  end
end
```

## 一覧

| validateでの指定 | 専用メソッド              | 内容           |
|------------------|---------------------------|----------------|
| presence         | validates_presence_of     | 値が空でないか |
| uniqueness       | validates_uniqueness_of   | 一意性         |
| acceptance       | validates_acceptance_of   | チェックボックスにチェックが入っているか |
| confirmation     | validates_confirmation_of | 2つのフィールドが等しいか |
| exclusion        | validates_exclusion_of    | 値が配列・範囲に含まれていないか |
| format           | validates_format_of       | 正規表現に一致するか検証 |
| inclusion        | validates_inclusion_of    | 値が配列・範囲に含まれるか |
| length           | validates_length_of       | 文字列の長さ   |
| numericality     | validates_numericality_of | 数値の大小、型 |
| ---              | validates_absence_of      | 空白か         |
| ---              | validates_associated      | 関連先の検証   |

* その他
 * validate : モデルの検証を定義する
 * verify : 実行前にリクエストの検証

## 挙動
* 基本的な挙動
 1. モデルに検証する条件を定義
 2. 保存前に検証される
 3. 検証でエラーが無ければ保存、エラーがあればエラーメッセージ表示

### before_validationとafter_validation
* before_validation
 * falseを返すと、validateは実行されずロールバックされる

```ruby
# before_validation :return_false
# after_validation  :raise_error
User.create(name: "val")  #=> rollback
```

* after_validation
 * falseを返しても、validateがtrueならロールバックされない
 * errors.add を実行してもtrueが返る

```ruby
# after_validation  :return_false
User.create(name: "aaaa")  #=> save
```

```ruby
# after_validation  :add_error
User.create(name: "bbbb")  #=> false
```

### 実行順
* valid?
* before_validation
* before_validation :on => {:create, :update}
* validate
* validate :on => {:create, :update}
* after_validation
* after_validation :on => {:create, :update}

### callbackの無効化と有効化

* skip_callback, set_callbackを使う
* callbackの登録に使われているメソッド

```ruby
# Disable
#   before_create :raise_error
User.skip_callback(:create, :before, :raise_error)
user = User.new
user.name = "hoge"
user.save                  #=> true
User.create(name: "fuga")  #=> true

# Enable
User.set_callback(:create, :before, :raise_error)
user = User.new
user.name = "piyo"
user.save                  #=> StandardError
User.create(name: "fuga")  #=> StandardError
```

## acts_as_paranoidとの組み合わせ
* acts_as_paranoidはdestroyを書き換え, recoverやdestroy!を追加する
 * recover用のcallbackとしてbefore_recover, after_recoverが追加される
* どのcallbackを定義したら効くか

### 結論
* acts_as_paranoidの書き換えは気にしなくてもいい
 * destroy, destroy!ともにxxx_destroyのcallbackだけ効く
 * recoverにはxxx_updateのcallbackが効く

### before_create, after_create, around_create
* destroy, recoverには無関係

```ruby
# after_create :raise_error
User.only_deleted.last.recover  #=> true
```

### before_update, after_update, around_update
* recoverに有効

```ruby
# around_update :raise_error
User.last.destroy                                    #=> true
User.last.destroy!                                   #=> true
User.only_deleted.last.destroy                       #=> true
User.destroy_all                                     #=> true
User.delete(1)                                       #=> true
User.delete_all                                      #=> true
User.last.update_attribute(:deleted_at, Time.now)    #=> StandardError
User.only_deleted.update_attribute(:deleted_at, nil) #=> StandardError
User.only_deleted.last.recover                       #=> StandardError
```

### before_destroy, after_destroy, around_destroy
* destroy, destroy!, destroy_allに有効

```ruby
# around_destroy :raise_error
User.last.destroy                                 #=> StandardError
User.last.destroy!                                #=> StandardError
User.only_deleted.last.destroy                    #=> StandardError
User.destroy_all                                  #=> StandardError
User.delete(1)                                    #=> true
User.delete_all                                   #=> true
User.last.update_attribute(:deleted_at, Time.now) #=> true
```

## 参考
* http://railsdoc.com/validation
* http://www.techscore.com/blog/2012/12/25/rails%E3%81%AE%E3%82%B3%E3%83%BC%E3%83%AB%E3%83%90%E3%83%83%E3%82%AF%E3%81%BE%E3%81%A8%E3%82%81/
* http://d.akiroom.com/2013-05/rails-activerecord-no-callback-update/
* http://gendosu.ddo.jp/redmine/projects/1/wiki/Active_record%E3%81%AE%E3%82%B3%E3%83%BC%E3%83%AB%E3%83%90%E3%83%83%E3%82%AF%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89
* http://maeshima.hateblo.jp/entry/20110329/1301428776