このページの内容は以下のリポジトリに1日遅れで反映されます(記事執筆前に前日分をコミットしています)。
https://github.com/hkob/hkob_blog
はじめに
Rails Tips の 72 回目です。昨日、status 属性を追加しましたが、この属性は public, private, archived だけの値だけを設定できるものになっています。これをテストできるような値限定制約という shared example を追加したいと思います。
値限定制約 shared example
値限定制約は key
と ok_values
, ng_values
を渡し、ok_values の場合にはエラーにならず、ng_values の場合にはエラーになることを確認します。存在制約を真似て以下のように作ってみました。
shared_examples_for "値限定制約" do |key, ok_values, ng_values| ok_values.each do |value| it "#{key} の内容が #{value} のとき、エラーにならないこと" do subject[key] = value expect(subject).to be_valid end end ng_values.each do |value| it "#{key} の内容が #{value} のとき、エラーになること" do subject[key] = value expect(subject).not_to be_valid end end end
article_spec と comment_spec は以下のようになります。
it_behaves_like "存在制約", %i[title body] it_behaves_like "値限定制約", :status, %w[public private archived], %w[NG]
it_behaves_like "存在制約", %i[commenter body article_id] it_behaves_like "値限定制約", :status, %w[public private archived], %w[NG]
migration しておきます。
class Article < ApplicationRecord VALID_STATUSES = %w[public private archived] validates :title, presence: true validates :body, presence: true, length: { minimum: 10 } validates :status, inclusion: { in: VALID_STATUSES } has_many :comments, dependent: :destroy end
class Comment < ApplicationRecord VALID_STATUSES = %w[public private archived] validates :commenter, presence: true validates :body, presence: true, length: { minimum: 10 } validates :status, inclusion: { in: VALID_STATUSES } belongs_to :article scope :order_created_at_desc, -> { order(created_at: :desc) } end
どちらのテストも以下のように成功しました。
behaves like 値限定制約 status の内容が public のとき、エラーにならないこと status の内容が private のとき、エラーにならないこと status の内容が archived のとき、エラーにならないこと status の内容が NG のとき、エラーになること
おわりに
値限定制約を追加しました。あまり使うことは多くないかもしれませんが、自分の shared example にも追加しておきます。