質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

RSpec

RSpecはRuby用のBDD(behaviour-driven development)フレームワークです。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

1回答

3081閲覧

attr_accessorのバリデーションをRspecでテストするとエラーになる

no1knows

総合スコア3365

Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

RSpec

RSpecはRuby用のBDD(behaviour-driven development)フレームワークです。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2019/08/16 10:26

編集2019/08/16 11:59

前提・実現したいこと

データベースに保存しないインスタンス変数のバリデーションをRspecでモデルテストを行うとエラーが表示されてしまいました。

前提:
郵便番号用に2つの入力欄(attr_accessorのcompany_zip_1、company_zip_2)を用意。
保存時は、company_zip_1とcompany_zip_2を' 'でjoinした値をcompany_zipカラムに保存。
バリデーションとして、company_zip_1とcompany_zip_2を入力必須にする。

発生している問題・エラーメッセージ

is invalid without a company_zip_1 (FAILED - 1)
1) Company is invalid without a company_zip_1 Failure/Error: expect(@company).not_to be_valid expected #<Company id: 1, company_zip: " 6126", created_at: "2019-08-16 05:55:42", updated_at: "2019-08-16 05:55:42"> not to be valid

該当のソースコード

view

<div class="form-inputs"> <%= f.input :company_zip_1 %> <%= f.input :company_zip_2 %> </div>

model

attr_accessor :company_zip_1, :company_zip_2 validates :company_zip_1, :company_zip_2, presence: true # 初期値の設定(編集時など) def company_zip_1 company_zip.present? ? company_zip.split(' ').first : @company_zip_1 end def company_zip_2 company_zip.present? ? company_zip.split(' ').last : @company_zip_2 end # 保存時の設定 after_validation :set_company_zip def set_company_zip self.company_zip = [@company_zip_1, @company_zip_2].join(' ') end

rspec

RSpec.describe Company, type: :model do before do @company = Company.create( company_zip_1: "106", company_zip_2: "6126", ) end # 住所(zip1)がなければ無効な状態であること it "is invalid without a company_zip_1" do @company.update(company_zip_1: "") expect(@company).not_to be_valid end # 郵便番号のインスタンスメソッドの動作確認 it "join company_zip_1 and company_zip_2" do expect(@company.company_zip).to eq "106 6126" end end

試したこと

・Everyday Rails - RSpecによるRailsテスト入門にてattr_accesorについて検索⇒該当なし
・ネットで検索したのですが、該当する回答をうまく見つけることができませんでした。

気になること

errorにあるようにexpectedの内容が下記のようになっています。

・company_zipのみが表示される => company_zip_1は表示されない
・company_zip: ” 6126" となっており、company_zip_1=“”、company_zip_2=“6126" を' ’でjoinした形になっている

そのためテーブルにカラムを持っていないattr_accessorは、Rspecでテストできない、または簡単にはできないのではと思っています。

補足情報(FW/ツールのバージョンなど)

rails 5.2.3
ruby 2.6.3

追記

実際の画面上で動作確認すると期待通りの動きができています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

winterboum

2019/08/16 11:27

attr_accessorもvalidationできるんですね!今知りました。ということはmethodでもOK? と考えたところで、そか、DBの属性もrailsがmethodにしているんだから当然か。 となると、update でerrorにならないのはおかしいですね。 ということでいま手元で試したところ、saveでもupdateでも機能してました。 う〜〜む。。。
winterboum

2019/08/16 11:44

あ、もしかして、実際の動きでは期待通りvalidationに掛かるのだが rspecだとかからない ですか? 上のテストは rspec ではなく consoleだったので
no1knows

2019/08/16 11:47

そうです!!実際の動きではきちんと動いてくれました。 ただrspecでエラーがでてしまいました。。。
winterboum

2019/08/16 11:53

それは厄介ですね。。。。 個人的な興味で申し訳ないですが、 save でのvalidation, valid? の結果も「引っ掛けてくれない」になるでしょうか
no1knows

2019/08/16 12:00

知識不足で申し訳ありません。save でのvalidation, valid? とはどういうことでしょうか? ご指示いただければこちらでテストします!
no1knows

2019/08/16 12:23

下記のような形で大丈夫でしょうか? company=Company.new(company_zip_1: "106", company_zip_2: "6126") company.valid? =>true
no1knows

2019/08/16 12:29

またCompany.createでも=>trueでした。
winterboum

2019/08/16 12:34

company=Company.new(company_zip_1: "", company_zip_2: "6126") company.valid? ではどうでしょう。 Company.createでtrueというのは ( company_zip_1: "106", company_zip_2: "6126" ) でですか? ( company_zip_1: "", company_zip_2: "6126" ) でですか?
no1knows

2019/08/16 13:02

下記のようになりました。 company=Company.new(company_zip_1: "106", company_zip_2: "6126") company.valid? => true company=Company.new(company_zip_1: "", company_zip_2: "6126") company.valid? => false company=Company.create(company_zip_1: "106", company_zip_2: "6126") company.valid? => true company=Company.create(company_zip_1: "", company_zip_2: "6126") ======== rollback transaction ======== company.valid? => true
guest

回答1

0

こんばんは。
include ActiveModel::Validations を追加ではいかがでしょうか?

company_zip_1, company_zip_2双方がセットされていない場合、
company.valid? で falseになる、company.errors.message でバリデーションの理由が "cannot be blank” になることが期待値でよいでしょうか。

実際にセットされている値の妥当性を詳しく調べたり、条件によってはバリデーションをスキップする場合は、カスタムバリデータを使うなどで行けるのかな?と思います。

もしくは、before_save でさらに実際のカラムにセットする際の値を検証するなど。

投稿2019/08/16 13:21

suama

総合スコア1997

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

no1knows

2019/08/18 02:43

ありがとうございます! リンクの内容を実施したところ、irbでは期待する動作を確認することができました。 ※なぜか include ActiveModel::Validations の有無に関わらず同じ結果でした。 ただrspecでは、エラーのままなのはなぜでしょうか? こちらはrspecのモデルテストだから、DBに保存されない値だからバリデーションテストができないのでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問