はじめに
rails初学者の者です。オンラインでプログラミングを学習させて頂いてるのですが、さらに理解を深めていきたいと思い、学習したことを備忘録として、残して理解を深めていきたいと思います。
また、間違った点など、ありましたら、ご指摘いただけると幸いです。よろしくお願いします。
前提
Formオブジェクトクラスを作成して、モデル単体のテストコードの実装を行なっていました。具体的のスクールの課題でメルカリのコピーアプリのようなものを作成していた中で、今回のテストコードの実装がありました。
概要
商品購入機能を実装し、購入するにあたって、
「クレジットカード情報」
カード情報、有効期限、セキュリティコード
「配送先情報」
class CreateAddresses < ActiveRecord::Migration[6.0]
def change
create_table :addresses do |t|
t.string :post_code, null:false
t.integer :prefecture_id, null:false
t.string :city, null:false
t.string :address, null:false
t.string :building_name, null:false
t.string :phone_number, null:false
t.references :purchase, null:false,foreign_key: true
t.timestamps
end
end
end
郵便番号、都道府県、市区町村、番地、建物名、電話番号、
を入力する必要がありました。
カード情報は、「Pay.jp」を導入して行なっています。
さらに、「配達先情報」と「購入者情報」を同時に二つのテーブルに保存させるため、
「purchase_addressクラス」を作成しています。
class PurchaseAddress
include ActiveModel::Model
attr_accessor :post_code, :prefecture_id, :city, :address, :building_name, :phone_number, :user_id, :product_id, :token
with_options presence: true do
validates :address
validates :user_id
validates :product_id
validates :token
validates :post_code, format: {with: /\A[0-9]{3}-[0-9]{4}\z/, message: "is invalid. Include hyphen(-)"}
validates :city
validates :phone_number, format: {with: /\A\d{10,11}\z/}
end
validates :prefecture_id, numericality: { other_than: 1, message: "can't be blank" }
def save
purchase = Purchase.create(user_id: user_id, product_id: product_id)
Address.create(post_code: post_code, prefecture_id: prefecture_id, city: city, address: address, building_name: building_name,
phone_number: phone_number, purchase_id: purchase.id)
end
end
テストコードの概要
require 'rails_helper'
RSpec.describe PurchaseAddress, type: :model do
describe '商品購入記録の保存' do
before do
@user = FactoryBot.create(:user)
@product = FactoryBot.create(:product)
@purchase_address = FactoryBot.build(:purchase_address,user_id: @user.id, product_id: @product.id)
end
context '内容に問題ない場合' do
it 'すべての値が正しく入力されていれば購入できること' do
expect(@purchase_address).to be_valid
end
it '建物名が空でも購入できること' do
@purchase_address.building_name = ''
expect(@purchase_address).to be_valid
end
end
context '内容に問題がある場合' do
it '郵便番号は空では保存できないこと' do
@purchase_address.post_code = ''
@purchase_address.valid?
expect(@purchase_address.errors.full_messages).to include("Post code can't be blank")
end
it '郵便番号は『3桁ハイフン4桁』半角英数字でないと保存できないこと' do
@purchase_address.post_code = '123-1234'
@purchase_address.valid?
expect(@purchase_address.errors.full_messages).to include("Post code is invalid. Include hyphen(-)")
end
it '都道府県に「---」が選択されている場合は購入できないこと' do
@purchase_address.prefecture_id = '1'
@purchase_address.valid?
expect(@purchase_address.errors.full_messages).to include("Prefecture can't be blank")
end
it '市区町村が空だと購入できないこと' do
@purchase_address.city = ''
@purchase_address.valid?
expect(@purchase_address.errors.full_messages).to include("City can't be blank")
end
it '番地が空だと購入できないこと' do
@purchase_address.address = ''
@purchase_address.valid?
expect(@purchase_address.errors.full_messages).to include("Address can't be blank")
end
it '電話番号が空だと購入できないこと' do
@purchase_address.phone_number = nil
@purchase_address.valid?
expect(@purchase_address.errors.full_messages).to include("Phone number can't be blank")
end
it '電話番号が9桁以下だと購入できないこと' do
@purchase_address.phone_number = '090123456'
@purchase_address.valid?
expect(@purchase_address.errors.full_messages).to include("Phone number is invalid")
end
it '電話番号が12桁以上だと購入できない' do
@purchase_address.phone_number = '090123456789'
@purchase_address.valid?
expect(@purchase_address.errors.full_messages).to include("Phone number is invalid")
end
it '電話番号が半角数値でないと購入できないこと' do
@purchase_address.phone_number = '09012341234'
@purchase_address.valid?
expect(@purchase_address.errors.full_messages).to include("Phone number is invalid")
end
it 'tokenが空では購入できないこと' do
@purchase_address.token = nil
@purchase_address.valid?
expect(@purchase_address.errors.full_messages).to include("Token can't be blank")
end
it 'user_idが紐づいていなければ購入できないこと' do
@purchase_address.user_id = ''
@purchase_address.valid?
expect(@purchase_address.errors.full_messages).to include("User can't be blank")
end
it 'product_idが紐づいていなければ購入できないこと' do
@purchase_address.product_id = ''
@purchase_address.valid?
expect(@purchase_address.errors.full_messages).to include("Product can't be blank")
end
end
end
end
今回は商品を購入する場合、ユーザーと商品が紐づいてるidが必要であったため、
@purchase_addressにuser_idとproduct_idを代入しています。この辺も記述の仕方がよく分からなくて、調べたり、メンターの方に実装方針を確認をさせていただきました。
before do
@user = FactoryBot.create(:user)
@product = FactoryBot.create(:product)
@purchase_address = FactoryBot.build(:purchase_address,user_id: @user.id, product_id: @product.id)
end
FactoryBotの中身です。↓
FactoryBot.define do
factory :purchase_address do
post_code { '123-1234'}
prefecture_id { 3 }
city { '横浜市緑区' }
address { '3-4' }
building_name { '青山ビル' }
phone_number { '09012341234' }
token {"tok_abcdefghijk00000000000000000"}
association :user_id
association :product_id
end
end
困っていたエラー文
PurchaseAddress
商品購入記録の保存
内容に問題ない場合
すべての値が正しく入力されていれば購入できること
建物名が空でも購入できること
内容に問題がある場合
郵便番号は空では保存できないこと
郵便番号は『3桁ハイフン4桁』半角英数字でないと保存できないこと
都道府県に「---」が選択されている場合は購入できないこと
市区町村が空だと購入できないこと (FAILED - 1)
番地が空だと購入できないこと
電話番号が空だと購入できないこと
電話番号が9桁以下だと購入できないこと
電話番号が12桁以上だと購入できない
電話番号が半角数値でないと購入できないこと
tokenが空では購入できないこと
user_idが紐づいていなければ購入できないこと
product_idが紐づいていなければ購入できないこと
Failures:
1) PurchaseAddress 商品購入記録の保存 内容に問題がある場合 市区町村が空だと購入できないこと
Failure/Error: @user = FactoryBot.create(:user)
ActiveRecord::RecordInvalid:
Validation failed: Password is invalid
# ./spec/models/purchase_address_spec.rb:6:in `block (3 levels) in <top (required)>'
Finished in 3.19 seconds (files took 1.27 seconds to load)
14 examples, 1 failure
Failed examples:
rspec ./spec/models/purchase_address_spec.rb:37 # PurchaseAddress 商品購入記録の保存 内容に問題がある場合 市区町村が空だと購入できないこと
エラーなのですが、毎回、異なるexampleでエラーが発生してました。
Validation failed: Password is invalid
直訳すると、パスワードが無効です。とのことでした。
FactoryBot.define do
factory :user do
name { Faker::Name.initials(number: 2) }
email { Faker::Internet.free_email }
password { '1a1a1a1a' }#指定するまではFakerを使用していました。
password_confirmation { password }
first_name { '太郎' }
last_name { '田中' }
first_name_kana { 'タロウ' }
last_name_kana { 'タナカ' }
birthday { '1900-01-01' }
end
end
passwordの部分は元々Fakerを使用していて、指定しなおしたらテストコードが通るようになりました。
バリデーションの影響で通過できない、passwordが適用されていたということでしょうか。
PurchaseAddress
商品購入記録の保存
内容に問題ない場合
すべての値が正しく入力されていれば購入できること
建物名が空でも購入できること
内容に問題がある場合
郵便番号は空では保存できないこと
郵便番号は『3桁ハイフン4桁』半角英数字でないと保存できないこと
都道府県に「---」が選択されている場合は購入できないこと
市区町村が空だと購入できないこと
番地が空だと購入できないこと
電話番号が空だと購入できないこと
電話番号が9桁以下だと購入できないこと
電話番号が12桁以上だと購入できない
電話番号が半角数値でないと購入できないこと
tokenが空では購入できないこと
user_idが紐づいていなければ購入できないこと
product_idが紐づいていなければ購入できないこと
Finished in 3.22 seconds (files took 0.89895 seconds to load)
14 examples, 0 failures
一旦通るようになったので、備忘録として残しておくことにしました。この後、なぜそうなっていたのかを追求していこと思います。また、このようにアウトプットしようと思ったのは、自分の言葉で説明するのが得意ではなく、もちろん根本的な知識が足りないからだと思っています。しかしながら、少しずつでも続けていき、理解を深めていきたいと思っています。また、些細なことでも構わないので間違った箇所などありましたら、ご指摘いただければと思っております。今回はご覧になって頂けた方、ありがとうございました。