LoginSignup
19
23

More than 5 years have passed since last update.

Railsのバリデーションで配列のサイズを制限する方法

Posted at

Storyモデルのバリデーションを行う。
Storyがhas_many:taggings なとき、1つのstoryが持てるtaggingsの数を制限したい。

方法1: Sexy Validationを使う

taggingsはArrayなので、lengthメソッドあるいはsizeメソッドでサイズを知ることができる。だからもしかしてvalidatesで:lengthが使えるんじゃないかなーと思っていたら、

使えた。

story.rb
  validates :taggings, :length => {
    :maximum   => STORY_TAGGINGS_LIMIT_SIZE,
    :too_long  => "タグ数が限界を超えました! 限界タグ数は%{count}です!"
  }

とすればバリデーションは完成。

なお、タグづけの方法は

を参考にして作った。この場合は、taggingsを直接入力しないので

story.rb
  validates :tag_ids, :length => {
    :maximum   => STORY_TAGGINGS_LIMIT_SIZE,
    :too_long  => "タグ数が限界を超えました! 限界タグ数は%{count}です!"
  }

のように、validatesの引数は:tag_idsや:tag_listに変えることになる。

方法2: 独自validate_eachメソッドを作る方法

上記のSexy Validationを使う方法がシンプルでよいのだけど、ほかの方法もある。
当初はvalidatesの:lengthオプションがarray相手に使えることを知らなかったので、以下の手法を用いた。

app/modelディレクリにsize_in_array_validator.rbというファイルを作る。

size_in_array_validator.rb
class SizeInArrayValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    if value.size > STORY_TAGGINGS_LIMIT_SIZE
      record.errors.add(attribute, "too much!")
    end
  end
end

modelディレクトリに入れれば自動的に読み込まれる。
app/model/story.rbの中に、以下のコードを入れる。

story.rb
validates :taggings, :size_in_array => true

これでバリデーションが動いた。

参考:Railsで任意のValidateを設定するには? QA@IT http://qa.atmarkit.co.jp/q/2508

不可解なエラー

独自validate_eachメソッドを作ったところ、Rspec 2.13.0 + Factory Girl 4.2.0でのエラーが発生した。

$ rspec

したら、

.../gems/activerecord-3.2.13/lib/active_record/validations.rb:56:in `save!': Validation failed: Email already exists. (ActiveRecord::RecordInvalid)

で、factory_girlがFactoryGirl.create(:story)を作る際になぜかsequenceが動かない……? という状況になった。

独自バリデーションが原因な気がしたのでコメントアウトした。

story.rb
# validates :taggings, :size_in_array => true

rspecをやりなおすと、エラーは発生しなかった。
どうしてこうなったのか本当によくわからない。
Sexy Validationを使えばこのエラーは発生しない。

19
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
23