Sequel Model Validation

http://sequel.jeremyevans.net/rdoc/files/doc/validations_rdoc.html の要約

内容の理解が進み次第追記します。

### Validationの使い方

Validation内容は ```validate``` メソッドに実装する。
オブジェクトに対して ```valid?``` を呼び出すことでValidationをパスするか判断できる。

Validationをパスしない状態で ```save``` が呼ばれると ```Sequel::ValidationFailed``` エラーが発生する。

エラーを発生させたくない場合は ```raise_on_save_failure``` にfalseを設定すれば良い。

```ruby
class Album < Sequel::Model
  def validate
    super
    errors.add(:name, 'cannot be empty') if !name || name.empty?
  end
end

Album.new.valid? # false
Album.new(:name=>'').valid? # false
Album.new(:name=>'RF').valid? # true
```

```valid?``` がfalseを返した場合、 ```errors``` メソッドでエラー内容を取得できる。
```errors``` は ```valid?``` が呼ばれるまではセットされない。

```rb
a = Album.new
# => #<Album @values={}>
a.valid?
# => false
a.errors
# => {:name=>["cannot be empty"]}

# 下記はダメな例
Album.new.errors
# => {}
````

### Validationが行われる場合と行われない場合

最終的に ```save``` が呼ばれる場合、```validate``` メソッドが呼び出される。
例えば ```create``` は内部的に ```save``` を呼び出している。
```insert``` は ```save``` を経由しないためvalidationは行われない

```save``` に対して ``` :validate => false``` をつけて呼び出すとValidationはスキップされる。

### validation_helpers

Validationを簡単に書けるようにするヘルパーメソッドが定義されている。

```rb
class Album < Sequel::Model
  def validate
    super
    errors.add(:name, 'cannot be empty') if !name || name.empty?
    errors.add(:name, 'is already taken') if name && new? && Album[:name=>name]
    errors.add(:website, 'cannot be empty') if !website || website.empty?
    errors.add(:website, 'is not a valid URL') unless website =~ /\Ahttps?:\/\//
  end
end
```

上記は validation_helpersを使って下記のように書き換えられる。

```rb
class Album < Sequel::Model
  plugin :validation_helpers
  def validate
    super
    validates_presence [:name, :website]
    validates_unique :name
    validates_format /\Ahttps?:\/\//, :website, :message=>'is not a valid URL'
  end
end
```

#### validates_presence, validates_not_null

```validates_presence``` はNULL, nil, 空文字列じゃないなんらかの値が入っている。
またはempty?、blank?でfalseが返って来る値が入っている。

```validates_not_null``` はNULL, nilではないかだけ確認する。空文字列でもOK

```rb
class Album < Sequel::Model
  def validate
    super
    validates_presence [:name, :website, :debut_album]
  end
end
```

#### validates_format

与えられる正規表現を満足するかどうか。文字列が所定のフォーマットにのっとっているか確認できる。

```rb
class Album < Sequel::Model
  def validate
    super
    validates_format /\A\d\d\d-\d-\d{7}-\d-\d\z/, :isbn
    validates_format /\a[0-9a-zA-Z:' ]+\z/, :name
  end
end
```

#### validates_exact_length, validates_min_length, validates_max_length, validates_length_range

文字列長の一致、下限、上限、範囲を確認できる。

```ruby
class Album < Sequel::Model
  def validate
    super
    validates_exact_length 17, :isbn
    validates_min_length 3, :name
    validates_max_length 100, :name
    validates_length_range 3..100, :name
  end
end
```

#### validates_integer, validates_numeric

整数かどうかと、数値かどうかを確認できる。

```rb
class Album < Sequel::Model
  def validate
    super
    validates_integer :copies_sold
    validates_numeric :replaygain
  end
end
```

#### validates_includes

取りうる値の候補を配列で指定する。

```ruby
class Album < Sequel::Model
  def validate
    validates_includes [1, 2, 3, 4, 5], :rating
  end
end
```

#### validates_type

所定のクラスのオブジェクトかどうか確認する。

```rb
class Album < Sequel::Model
  def validate
    super
    validates_type String, [:name, :website]
    validates_type :Artist, :artist
    validates_type [String, Integer], :foo
  end
end
```

#### validates_schema_types

ざっと読んだけどよくわからず、後で追記するかも。原文参照のこと。

#### validates_unique

値がユニークか否か・・・ なんだけど使い方が他のhelperと異なるので原文を参照した方が良い。