概要
conditional
詳細
ActiveRecord で、validation時に if や unless を利用することで、
特定の条件下での validation を行うことができます。
サンプル
テーブル定義
CREATE TABLE "articles" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "title" varchar(255), "text" text, "created_at" datetime, "updated_at" datetime );
Validation その1
titleが5文字より大きい場合のみ、数値を強要する
class Article < ActiveRecord::Base has_many :comments, dependent: :destroy validates :title, numericality: { only_integer: true }, :if => :over_five? def over_five? return false if title.nil? title.size > 5 end end
試行 その1
rails console(pry)で試行します。
[1] pry(main)> a = Article.new => #<Article id: nil, title: nil, text: nil, created_at: nil, updated_at: nil> [2] pry(main)> a.title = 'abcde' => "abcde" [3] pry(main)> a.valid? => true [4] pry(main)> a.title = 'abcdef' => "abcdef" [5] pry(main)> a.valid? => false [6] pry(main)> a.errors.messages => {:title=>["is not a number"]} [7] pry(main)> a.title = 123456 => 123456 [8] pry(main)> a.valid? => true
Validation その2
titleが5文字以下の場合のみ、数値を強要する
class Article < ActiveRecord::Base has_many :comments, dependent: :destroy validates :title, numericality: { only_integer: true }, :unless => :over_five? def over_five? return false if title.nil? title.size > 5 end end
試行 その2
rails console(pry)で試行します。
[1] pry(main)> a = Article.new => #<Article id: nil, title: nil, text: nil, created_at: nil, updated_at: nil> [2] pry(main)> a.title = 'abcdef' => "abcdef" [3] pry(main)> a.valid? => true [4] pry(main)> a.title = 'abcde' => "abcde" [5] pry(main)> a.valid? => false [6] pry(main)> a.errors.messages => {:title=>["is not a number"]} [7] pry(main)> a.title = 12345 => 12345 [8] pry(main)> a.valid? => true
Validation その3
titleが5文字より大きい場合のみ、数値を強要する
(if: evalの文法を利用)
class Article < ActiveRecord::Base has_many :comments, dependent: :destroy validates :title, numericality: { only_integer: true }, :if => "title.nil? ? false : (title.size > 5)" end
試行 その3
rails console(pry)で試行します。
[1] pry(main)> a = Article.new => #<Article id: nil, title: nil, text: nil, created_at: nil, updated_at: nil> [2] pry(main)> a.title = 'abcde' => "abcde" [3] pry(main)> a.valid? => true [4] pry(main)> a.title = 'abcdef' => "abcdef" [5] pry(main)> a.valid? => false [6] pry(main)> a.errors.messages => {:title=>["is not a number"]} [7] pry(main)> a.title = 123456 => 123456 [8] pry(main)> a.valid? => true
Validation その4
titleが5文字より大きい場合のみ、数値を強要する
(if: Procの文法を利用)
class Article < ActiveRecord::Base has_many :comments, dependent: :destroy validates :title, numericality: { only_integer: true }, :if => Proc.new { |a|a.title.nil? ? false : (a.title.size > 5) } end
試行 その4
rails console(pry)で試行します。
[1] pry(main)> a = Article.new => #<Article id: nil, title: nil, text: nil, created_at: nil, updated_at: nil> [2] pry(main)> a.title = 'abcde' => "abcde" [3] pry(main)> a.valid? => true [4] pry(main)> a.title = 'abcdef' => "abcdef" [5] pry(main)> a.valid? => false [6] pry(main)> a.errors.messages => {:title=>["is not a number"]} [7] pry(main)> a.title = 123456 => 123456 [8] pry(main)> a.valid? => true
Validation その5
titleが5文字より大きい場合のみ、title/textに数値を強要する
class Article < ActiveRecord::Base has_many :comments, dependent: :destroy with_options :if => :over_five? do |a| a.validates :title, numericality: { only_integer: true } a.validates :text, numericality: { only_integer: true } end def over_five? return false if title.nil? title.size > 5 end end
試行 その5
rails console(pry)で試行します。
[1] pry(main)> a = Article.new => #<Article id: nil, title: nil, text: nil, created_at: nil, updated_at: nil> [2] pry(main)> a.title = 'abcde' => "abcde" [3] pry(main)> a.text = 'abcde' => "abcde" [4] pry(main)> a.valid? => true [5] pry(main)> a.title = 'abcdef' => "abcdef" [6] pry(main)> a.text = 'abcdef' => "abcdef" [7] pry(main)> a.valid? => false [8] pry(main)> a.errors.messages => {:title=>["is not a number"], :text=>["is not a number"]} [9] pry(main)> a.title = 123456 => 123456 [10] pry(main)> a.text = 123456 => 123456 [11] pry(main)> a.valid? => true
Validation その6
titleが5文字より大きい場合のみ、titleに数値を強要する
(if, unlessを同時に使用してみる)
class Article < ActiveRecord::Base has_many :comments, dependent: :destroy validates :title, numericality: { only_integer: true }, :if => Proc.new { |a|a.title.present? }, :unless => Proc.new { |a|a.title.size <= 5 } end
試行 その6
rails console(pry)で試行します。
[1] pry(main)> a = Article.new => #<Article id: nil, title: nil, text: nil, created_at: nil, updated_at: nil> [2] pry(main)> a.title = 'abcde' => "abcde" [3] pry(main)> a.valid? => true [4] pry(main)> a.title = 'abcdef' => "abcdef" [5] pry(main)> a.valid? => false [6] pry(main)> a.errors.messages => {:title=>["is not a number"]} [7] pry(main)> a.title = 123456 => 123456 [8] pry(main)> a.valid? => true