前提・実現したいこと
ユーザー(selller)と住所(address_seller)を一緒に登録する機能のモデルのテストコードを実装したいのですが、バリデーションがうまく作用せず
どのように実装したら良いのか悩んでおります。
ローカルで動かしている時はしっかりバリデーションが作用しています。
発生している問題・エラーメッセージ
バリデーションが作用せず、からのデータがあったとしても@〜.valid?でtrueに返されてしまう。
該当のソースコード
spec モデルテストコード
require 'rails_helper'
RSpec.describe AddressSeller, type: :model do
describe '#create' do
before do
@address_seller = FactoryBot.build(:address_seller)
end
context '商品購入できるとき' do
it '全ての項目の入力が存在すれば登録できること' do
expect(@address_seller).to be_valid
end
it '建物名が存在しなくても登録できること' do
@address_seller.house_number = ""
expect(@address_seller).to be_valid
end
end
context '商品購入できないとき' do
it '郵便番号が空では登録できない' do
@address_seller.postal_code = ''
@address_seller.valid?
binding.pry
expect(@address_seller.errors.full_messages).to include()
end
end
end
end
spec FactoryBot
FactoryBot.define do
factory :address_seller do
postal_code { "333-3333" }
area { '東京' }
city { "浜田市" }
block_number { "夕香の塔" }
house_number { "309-11" }
phone_number { "11111111111" }
seller_id { 1 }
end
end
address_seller モデル
class AddressSeller < ApplicationRecord
belongs_to :seller, optional: true
include Addressable
end
concerns
module Addressable
extend ActiveSupport::Concern
included do
with_options presence: true do
validates :postal_code, format:{with: /\A\d{3}[-]\d{4}\z/}
validates :area
validates :city
validates :block_number
validates :phone_number, format:{with:/\A\d{11}\z/}
end
end
end
devise sellers コントローラー
class Sellers::RegistrationsController < Devise::RegistrationsController
# before_action :configure_sign_up_params, only: [:create]
# before_action :configure_account_update_params, only: [:update]
# GET /resource/sign_up
def new
@seller = Seller.new
end
def create
@seller = Seller.new(sign_up_params)
unless @seller.valid?
render :new and return
end
session["devise.regist_data"] = {seller: @seller.attributes}
session["devise.regist_data"][:seller]["password"] = params[:seller][:password]
@address = @seller.build_address_seller
render :new_address
end
def create_address
@seller = Seller.new(session["devise.regist_data"]["seller"])
@address = AddressSeller.new(address_params)
unless @address.valid?
render :new_address and return
end
@seller.build_address_seller(@address.attributes)
@seller.save
session["devise.regist_data"]["seller"].clear
sign_in(:seller, @seller)
end
private
def address_params
params.require(:address_seller).permit(:postal_code, :area, :city, :block_number, :phone_number, :house_number)
end
end
試したこと
binding.pryを記述し、コンソール内でvalid?をしたところtrueと返ってきてしまいました。
concernsの記述を引用していたのでsellerモデルに直接バリデーション を書き込んでみましたがバリデーションは作用しなかったです。
ですのでローカルで確認しましたが、ローカルの方ではしっかりとバリデーションがかかっていました。
sellerのモデルテストコードは問題なく実装できました。
rails cでコンソールを立ち上げ、実際に手打ちでしていくとしっかりバリデーションがかかるのですが
この文章をspecファイルで bundle exec rspec spec/models/address_seller_spec.rb で一連のテストコードを流してしまうとtrueになってしまうようです。
*手入力
[1] pry(main)> address_seller = AddressSeller.new(postal_code: '', area: 'ここ', city: 'ここ', block_number: 'ここ', phone_number: '11111111111')
(0.9ms) SET NAMES utf8, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
=> #<AddressSeller:0x00007faf5adcb980
id: nil,
postal_code: "",
area: "ここ",
city: "ここ",
block_number: "ここ",
house_number: nil,
phone_number: "11111111111",
seller_id: nil,
created_at: nil,
updated_at: nil>
[2] pry(main)> address_seller.valid?
=> false
[3] pry(main)> address_seller.errors.full_messages
=> ["Postal code can't be blank", "Postal code is invalid"]
*binding.pryを記述しbundle exec rspec spec/models/address_seller_spec.rbした
id: nil,
postal_code: "",
area: "ここ",
city: "ここ",
block_number: "ここ",
house_number: nil,
phone_number: "11111111111",
seller_id: nil,
created_at: nil,
updated_at: nil>
[3] pry(#<RSpec::ExampleGroups::AddressSeller::Create::Nested_2>)> address_seller.valid?
=> true
初歩的なことかもしれませんが教えていただけると助かります。
補足情報(FW/ツールのバージョンなど)
ここにより詳細な情報を記載してください。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
まだ回答がついていません
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.22%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正の依頼
shinoharat2
2021/02/24 12:47
現段階で提示して頂いているコードだと問題なさそうに見えます。
可能性があるとしたら、spec側にvalid?メソッドをスタブするような処理があるとかですかね……?
specのコードは貼って頂いたもので全部ですか?
もし一部の切り抜きなら、切り抜いた部分以外に原因があるかもしれないので、全体のコードを貼ってもらえると何か分かるかも知れません。
noah1111
2021/02/24 15:11
コメントありがとうどざいます!
現在、とても簡略化した文章で、再度試していました
require 'rails_helper'
RSpec.describe AddressSeller, type: :model do
describe 'ユーザー新規登録' do
it 'nicknameが空では登録できない' do
address_seller = AddressSeller.new(postal_code: '', area: 'ここ', city: 'ここ', block_number: 'ここ', phone_number: '11111111111')
address_seller.valid?
expect(address_seller.errors.full_messages).to include("Postal code can't be blank", "Postal code is invalid")
end
end
end
こちらになるのですが、こちらでもtrueで返されてしまうのです。
全てというのは他のモデルテストコードのファイルもでしょうか。
今回のaddress_sellerに関しましては全て貼らせていただきました。
shinoharat2
2021/02/27 11:13
返信遅れてすみません。
> 全てというのは他のモデルテストコードのファイルもでしょうか。
address_seller に関するものがすべて、という意味でした。
> 今回のaddress_sellerに関しましては全て貼らせていただきました。
そうなのですね。そうするとお手上げです・・・。
> 現在、とても簡略化した文章で、再度試していました
念の為確認ですが、簡略化したspecを1件のみ実行しても失敗するんですよね?
// ファイル名指定で実行する例
$ bundle exec rspec path/to/address_seller_spec.rb
noah1111
2021/02/27 16:08
はい、どうしても失敗してしまいます。。。
ですので対策法として、concernsの内容をモデルに直接書き込んだら一応バリデーションが作用したのでそのまま今回はいくことにしました。
今回は丁寧に教えていただきありがとうどざいました