モデルにない属性のバリデーションのテスト方法について
- 評価
- クリップ 0
- VIEW 1,064
※当方、rails5から入った初心者です。ですのでruby自体も初心者です。
前提・実現したいこと
お問い合わせフォームのバリデーションのテストうち、モデルにない属性(確認ボタン)のバリデーションがうまくいかないです。
お問い合わせフォームは以下の要素を持っています。
- 名前
- メールアドレス
- 本文
- 確認ボタン
- 送信ボタン
DBに保存するのは、名前、メールアドレス、本文のみです。
該当のソースコード
※FactoryGirlの接頭辞は省略するように設定しています。
# app/views/contacts/index.html.slim
h1 お問い合わせ
= form_for @contact do |f|
- if @contact.errors.any?
= "#{pluralize(@contact.errors.count, 'error')}"
ul
- @contact.errors.full_messages.each do |msg|
li = msg
= f.label :name, '名前'
= f.text_field :name
br
= f.label :email, 'メールアドレス'
= f.email_field :email
br
= f.label :body, '内容'
= f.text_area :body
br
= f.label :confirmation, '確認'
= f.check_box :confirmation
br
= f.submi
# app/models/contact.rb
class Contact < ApplicationRecord
attr_accessor :confirmation
validates :name, presence: true
VALIDE_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, format: { with: VALIDE_EMAIL_REGEX }
validates :body, presence: true
validates :confirmation, acceptance: true
end
# db/migrate/2017040455604_create_contacts.rb
class CreateContacts < ActiveRecord::Migration[5.0]
def change
create_table :contacts do |t|
t.string :name, :null => false, :limit => 200
t.string :email, :null => false, :limit => 200
t.text :body, :null => false
t.timestamps
end
end
end
# spec/factories/contacts.rb
FactoryGirl.define do
factory :contact do
name "bcafe"
email "bcafe-to@example.com"
body "this is test."
factory :contact_with_empty_name do
name nil
end
factory :contact_with_empty_email do
email nil
end
factory :contact_with_empty_body do
body nil
end
factory :contact_with_empty_confirmation do
confirmation nil
end
end
end
# spec/models/contact_spec.rb
require 'rails_helper'
RSpec.describe Contact, type: :model do
describe 'validation' do
it 'is valid with name, email, body and confirmation' do
contact = build(:contact)
expect(contact).to be_valid
end
it 'is invalid without name' do
contact = build(:contact_with_empty_name)
contact.valid?
expect(contact.errors[:name].any?).to be true
end
it 'is invalid without email' do
contact = build(:contact_with_empty_email)
contact.valid?
expect(contact.errors[:email].any?).to be true
end
it 'is invalid without body' do
contact = build(:contact_with_empty_body)
contact.valid?
expect(contact.errors[:body].any?).to be true
end
it 'is invalid without confirmation' do
contact = build(:contact_with_empty_confirmation)
contact.valid?
expect(contact.errors[:confirmation].any?).to be true
end
end
describe 'database' do
it 'should save contact instance with no abnormality' do
assert build(:contact).save
end
it 'should not save contact instance with epmty name' do
contact = build(:contact_with_empty_name)
expect { contact.save!(validate: false) }.to raise_error ActiveRecord::StatementInvalid
end
it 'should not save contact instance wihout email' do
contact = build(:contact_with_empty_email)
expect { contact.save!(validate: false) }.to raise_error ActiveRecord::StatementInvalid
end
it 'should noe save contact instance withoud body' do
contact = build(:contact_with_empty_body)
expect { contact.save!(validate: false) }.to raise_error ActiveRecord::StatementInvalid
end
end
end
発生している問題・エラーメッセージ
Failures:
1) Contact validation is invalid without confirmation
Failure/Error: expect(contact.errors[:confirmation].any?).to be true
expected true
got false
# ./spec/models/contact_spec.rb:31:in `block (3 levels) in <top (required)>'
補足情報(言語/FW/ツール等のバージョンなど)
- ruby 2.4.0p0 (2016-12-24 revision 57164) [x86_64-darwin16]
- Rails 5.0.2
- RSpec 3.5.4
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
0
確認ボタンと聞くと、そこはかとなくレガシーのいやな感じがしますが…。
とりあえず、下記の規約に同意する等のconfirmだと思うことにしますね。
基本的に、ActiveRecordはtableに紐づいているので
送信ボタン(submit)を除いて存在しない、columnのvalidationはできません。
もしやりたい場合はActiveModelというClassを使うか、DraperといったPresenterを使い
ActiveRecordを拡張してやる必要があります。Railsをしっかりやる場合、両方覚えておいて損はないでしょう
しかし、逆の発想も可能で、登録時しか使わない、columnをtableに作ってしまうという方法です。
たかだか、不要なbooleanのcolumnが一つ増えたところで、テーブル設計がどうだというのでしょうか。
Ruby on Railsはパッと組み立て、サクッと動かせ、ちょちょっと直せるので、
ベストな方法を求め枝葉末節にこだわるより、動かして、その魅力を体感してください。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 89.96%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2017/04/15 13:06
提示して頂いた、ActiveModelとDraperについて学習します。ありがとうございました。
2017/04/15 14:28
頭を柔らかくした方がいいと思いますが…。
不要なcolumnを一つ追加して、とりあえず運用して、あとで
ActiveModel等に切り替えてもテストはほとんど変わらないで適用できますし…。
個人的には、そんなにキッチリしたいならSpring javaとかでやればいいのかなーと思ってしまいます。
まあ、こだわり方は人それぞれですし、ActiveModelもDraperいいものなので、とりあえず頑張ってください。