バリデーションでエラーが出た後、前の情報を残したい
バリデーションでエラーが出た後、前の情報を残したい(formオブジェクトパタンを用いた購入機能を実装中)
質問の箇所
フリマアプリ formオブジェクトパタンを用いた購入機能を実装中。
質問の内容
問題に関する情報
class PurchasesController < ApplicationController before_action :authenticate_user!, except: :index def index @item = Item.find(params[:item_id]) @purchase = Purchase.new @address = @purchase.build_address @purchase_address = PurchaseAddress.new # @purchase_address = @item.build_purchase_address end def new @purchase_address = PurchaseAddress.new # @purchase_address = @item.build_purchase_address end def create @item = Item.find(params[:item_id]) @purchase_address = PurchaseAddress.new(purchase_params) if @purchase_address.valid? @purchase_address.save redirect_to root_path else render :index end # item = Item.find(params[:item_id]) # @purchase = item.create_purchase!(user_id: current_user.id) # @purchase.create_address!(address_params) # redirect_to root_path end private # def purchase_params # params.merge(user_id: current_user.id, item_id: params[:item_id]) # end # def address_params # params.permit(:postal_code, :prefecture_id, :city, :house_number, :phone_number, :building_name).merge(purchase_id: @purchase.id) # end def purchase_params params.permit(:postal_code, :prefecture_id, :city, :house_number, :phone_number, :building_name).merge(user_id: current_user.id, item_id: params[:item_id]) end end
<%= render "shared/second-header"%> <div class='transaction-contents'> <div class='transaction-main'> <h1 class='transaction-title-text'> 購入内容の確認 </h1> <%# 購入内容の表示 %> <div class='buy-item-info'> <%= image_tag @item.image, class: 'buy-item-img' %> <div class='buy-item-right-content'> <h2 class='buy-item-text'> <%= @item.name %> </h2> <div class='buy-item-price'> <p class='item-price-text'>¥<%= @item.price %></p> <p class='item-price-sub-text'><%= @item.shipping.shipping_id %></p> </div> </div> </div> <%# /購入内容の表示 %> <%# 支払額の表示 %> <div class='item-payment'> <h1 class='item-payment-title'> 支払金額 </h1> <p class='item-payment-price'> ¥<%= @item.price %> </p> </div> <%# /支払額の表示 %> <%= form_with url: item_purchases_path, method: [@purchase_address,@purchase,@address], id: 'charge-form', class: 'transaction-form-wrap', local: true do |f| %> <%= render 'shared/error_messages', model: @purchase_address %> <div class='shipping-address-form'> <h1 class='info-input-haedline'> 配送先入力 </h1> <div class="form-group"> <div class='form-text-wrap'> <label class="form-text">郵便番号</label> <span class="indispensable">必須</span> </div> <%= f.text_field :postal_code, class:"input-default", id:"postal-code", placeholder:"例)123-4567", maxlength:"8" %> </div> <div class="form-group"> <div class='form-text-wrap'> <label class="form-text">都道府県</label> <span class="indispensable">必須</span> </div> <%= f.collection_select(:prefecture_id, Prefecture.all, :id, :prefecture_id, {}, {class:"select-box", id:"prefecture"}) %> </div> <div class="form-group"> <div class='form-text-wrap'> <label class="form-text">市区町村</label> <span class="indispensable">必須</span> </div> <%= f.text_field :city, class:"input-default", id:"city", placeholder:"例)横浜市緑区"%> </div> <div class="form-group"> <div class='form-text-wrap'> <label class="form-text">番地</label> <span class="indispensable">必須</span> </div> <%= f.text_field :house_number, class:"input-default", id:"addresses", placeholder:"例)青山1-1-1"%> </div> <div class="form-group"> <div class='form-text-wrap'> <label class="form-text">建物名</label> <span class="form-any">任意</span> </div> <%= f.text_field :building_name, class:"input-default", id:"building", placeholder:"例)柳ビル103"%> </div> <div class="form-group"> <div class='form-text-wrap'> <label class="form-text">電話番号</label> <span class="indispensable">必須</span> </div> <%= f.text_field :phone_number, class:"input-default", id:"phone-number", placeholder:"例)09012345678",maxlength:"11"%> </div> </div> <%# /配送先の入力 %> <div class='buy-btn'> <%= f.submit "購入" ,class:"buy-red-btn", id:"button" %> </div> <%# <% end %> %> </div> </div> <% end %> <%= render "shared/second-footer"%>
class PurchaseAddress include ActiveModel::Model attr_accessor :user_id, :item_id, :postal_code, :city, :house_number, :phone_number, :building_name, :prefecture_id with_options presence: true do validates :postal_code, format: {with: /\A[0-9]{3}-[0-9]{4}\z/, message: "is invalid. Include hyphen(-)", allow_blank: true } validates :prefecture_id, numericality: {other_than: 1, message: "can't be blank"} validates :city validates :house_number validates :phone_number, format: { with: /\A0[0-9]+\z/, message: 'number is invalid. Include half-width numbers' , allow_blank: true } validates :user_id validates :item_id end def save purchase = Purchase.new address = @purchase.build_address purchase = Purchase.create(user_id: user_id, item_id: item_id) Address.create(postal_code: postal_code, city: city, house_number: house_number, phone_number: phone_number, building_name: building_name, prefecture_id: prefecture_id, purchase_id: purchase.id) end end
問題に関するターミナルやコンソールの情報:
From: /Users/user/projects/furima-35933/app/controllers/purchases_controller.rb:19 PurchasesController#create: 16: def create 17: @item = Item.find(params[:item_id]) 18: @purchase_address = PurchaseAddress.new(purchase_params) => 19: binding.pry 20: if @purchase_address.valid? 21: @purchase_address.save 22: redirect_to root_path 23: else 24: render :index 25: end 26: # item = Item.find(params[:item_id]) 27: # @purchase = item.create_purchase!(user_id: current_user.id) 28: # @purchase.create_address!(address_params) 29: # redirect_to root_path 30: end [1] pry(#<PurchasesController>)> @purchase_address => #<PurchaseAddress:0x00007ffd49fb2450 @building_name="", @city="日高市", @house_number="森山1-5-77", @item_id="31", @phone_number="09084842343", @postal_code="213-3456", @prefecture_id="3", @user_id=33> [2] pry(#<PurchasesController>)> @purchase_address.valid? => true [3] pry(#<PurchasesController>)> exit
解決したいこと
formオブジェクトパタンを用いた購入機能を実装中。 バリデーションでエラーが出た後、前の情報を残したい
調べた内容とそこから立てた仮説
カリキュラムの フォームオブジェクトパタンの定義方法を参考に購入機能を実装してみた コントローラでpurchase_addressのインスタンスを生成し、form_with に代入ができたと思いますが、form_wiht で入力したデータをコントローラで送ってきた値をバリデーションをかけ、入力問題がある時、エラーメッセージが出ていたが、入力した内容は消え、form_wihtにはコントローラで生成したpurchase_addressのインスタンスを指定したにも関わらず、残せないのは、今回の問題点ではと考えております、そのため、form_withに新たにpurchaseコントローラでインスタンス@purchase,@address を生成し、指定したが、解決できなかった、なので問題は別のところにあるのではと考えておりますが.今回においては、上記の@purchaseと@addressは、form_withの実装で特別使用することがないインスタンス変数になる め,@purchase_addressのみを使用して実装ができる記述で進めていきますので、今回は不要となります。
はい、ダメでした!
- 検証
- 「@purchase_address」というインスタンス変数に正しく値が入っているかを確認するところ
[1] pry(#<PurchasesController>)> @purchase_address => #<PurchaseAddress:0x00007ffd49fb2450 @building_name="", @city="日高市", @house_number="森山1-5-77", @item_id="31", @phone_number="09084842343", @postal_code="213-3456", @prefecture_id="3", @user_id=33> [2] pry(#<PurchasesController>)> @purchase_address.valid? => true
- ちゃんと入ってることがわかりましたが、、、 入力したデータを購入ページに反映させたい場合は、form_with内にある「@purchase_address」に含まれる値を受け取り、ビューに既存のデータとして反映させます。つまり、form_with の記述は問題があるかを確認する必要あるここでもう一回form_with 見直します。
<%= form_with method: @purchase_address, ←(キーが「method:」になっています)
それでform_withの記述を修正:
<%= form_with url: item_purchases_path, model: @purchase_address, id: 'charge-form', class: 'transaction-form-wrap', local: true do |f| %>
- そして、以下の手順にしたがって、
①rails sのし直し。 余計なエラーが出ることを防ぐため、一度最新の状態にリセットさせます。
②localhost: 3000のトップページから購入ページに移る。 こちらも上記の理由と同じです。確実に最新の状態でページを始められる状態にします。
③購入ページで「購入ボタン」を押した後に、入力情報が残るかどうかを確認。
ターミナル上:
From: /Users/user/projects/furima-35933/app/controllers/purchases_controller.rb:15 PurchasesController#create: 12: def create 13: @item = Item.find(params[:item_id]) 14: @purchase_address = PurchaseAddress.new(purchase_params) => 15: binding.pry 16: if @purchase_address.valid? 17: @purchase_address.save 18: redirect_to root_path 19: else 20: render :index 21: end 22: # item = Item.find(params[:item_id]) 23: # @purchase = item.create_purchase!(user_id: current_user.id) 24: # @purchase.create_address!(address_params) 25: # redirect_to root_path 26: end [1] pry(#<PurchasesController>)> @purchase_address => #<PurchaseAddress:0x00007ff483a4c750 @item_id="31", @user_id=33> [2] pry(#<PurchasesController>)> @purchase_address => #<PurchaseAddress:0x00007ff483a4c750 @item_id="31", @user_id=33> [3] pry(#<PurchasesController>)> @purchase_address.valid? => false [4] pry(#<PurchasesController>)> @purchase_address.errors.full_messages => ["Postal code can't be blank", "Prefecture can't be blank", "Prefecture can't be blank", "City can't be blank", "House number can't be blank", "Phone number can't be blank"] [5] pry(#<PurchasesController>)> exit
また、新たな問題発見!!!!
- どうやら、インスタンス @purchase_addressに@item_id="31", @user_id=33 の情報しかない、なぜ?ストロングパラメータに問題でも?
def purchase_params params.permit(:postal_code, :prefecture_id, :city, :house_number, :phone_number, :building_name).merge(user_id: current_user.id, item_id: params[:item_id])
permit(:postal_code, :prefecture_id, :city, :house_number, :phone_number, :building_name)
の情報が受け取らなかった!!!ていうことは、、、指定しなかったのでは、、、
def purchase_params params.require(:purchase_address).permit(:postal_code, :prefecture_id, :city, :house_number, :phone_number, :building_name).merge(user_id: current_user.id, item_id: params[:item_id]) end
require(:purchase_address)追記し、もう一回試したら、、、、
したら、無事解決できました!!!
まとめ:from_withの記述が間違ったことは今回の原因でした!!!とても初歩的なミス!!!もう二度と同じ間違いを犯さないようにメモとして残しときます。
最後:問題解決に手伝って頂いたメンターの方に感謝!!
(テックキャンプ 102期 受講生)
追記:クレジットカード情報の項目は省いております。
自己学習メモ:エラー解決(undefined local variable or method `purchase' for #<PurchaseAddress:0x00007ffd49e9b670>)
自己検証の内容:
エラー画面
スクリーンショットを貼る
undefined local variable or method `purchase' for #<PurchaseAddress:0x00007ffd49e9b670>
解決したいこと
- formオブジェクトパタンを用いた購入機能を実装中。
- form_withで入力したデータはdbに保存したいが、purchaseテーブルへの保存ができたが、address テーブルへの保存ができなかったこと
調べた内容とそこから立てた仮説
カリキュラムの donation appを参考に購入機能を実装してみた コントローラでpurchase_addressのインスタンスを生成し、form_with に代入ができたと思いますが、form_wiht で入力したデータをコントローラで送ってきた値をバリデーションをかけ、エラーメッセージも出ていて、purchase_address.rbでsaveできないのは今回の問題点かと思いますが、カリキュラムと同じ設定方法で記述したため、問題は別のところにあるのではと考えております。
仮説を元に行った作業内容
(例)コントローラーにbinding.pryを設け処理をとめた。 何が受け取れているのかを確認したところ、トークンの受け取りは確認できなかった。 JSからパラメーターが送られていないのか確認しようとしたが、適切に確認できているのか 分からなかった。
新たにmodelsディレクトリ直下にファイルを作成し、クラスを定義した(formオブジェクトパタンを実行)
class PurchaseAddress include ActiveModel::Model attr_accessor :user_id, :item_id, :postal_code, :city, :house_number, :phone_number, :building_name, :prefecture_id with_options presence: true do validates :postal_code, format: {with: /\A[0-9]{3}-[0-9]{4}\z/, message: "is invalid. Include hyphen(-)"} validates :prefecture_id, numericality: {other_than: 1, message: "can't be blank"} validates :city validates :house_number validates :phone_number, format: { with: /\A0[0-9]+\z/, message: 'number is invalid. Include half-width numbers' } validates :user_id validates :item_id end def save Purchase.create(user_id: user_id, item_id: item_id) Address.create(postal_code: postal_code, city: city, house_number: house_number, phone_number: phone_number, building_name: building_name, prefecture_id: prefecture_id, purchase_id: purchase.id) # item = Item.find(params[:item_id]) # @purchase = item.create_purchase!(user_id: current_user.id) # @purchase.create_address!(address_params) # redirect_to root_path end end
purchaseコントローラ
class PurchasesController < ApplicationController before_action :authenticate_user!, except: :index def index @item = Item.find(params[:item_id]) @purchase_address = PurchaseAddress.new # @purchase_address = @item.build_purchase_address end def new @purchase_address = PurchaseAddress.new # @purchase_address = @item.build_purchase_address end def create @item = Item.find(params[:item_id]) @purchase_address = PurchaseAddress.new(purchase_params) # @purchase_address = item.build_purchase_address(purchase_params) if @purchase_address.valid? @purchase_address.save redirect_to root_path else render :index end # item = Item.find(params[:item_id]) # @purchase = item.create_purchase!(user_id: current_user.id) # @purchase.create_address!(address_params) # redirect_to root_path end private # def purchase_params # params.merge(user_id: current_user.id, item_id: params[:item_id]) # end # def address_params # params.permit(:postal_code, :prefecture_id, :city, :house_number, :phone_number, :building_name).merge(purchase_id: @purchase.id) # end def purchase_params params.permit(:postal_code, :prefecture_id, :city, :house_number, :phone_number, :building_name).merge(user_id: current_user.id, item_id: params[:item_id]) end end
フォームのmodelオプションを設定したコード:現段階では、pay.jpを導入していないため、カード情報の入力をコメントアウトしている
<%= render "shared/second-header"%> <%= form_with url: item_purchases_path, method: @purchase_address, local: true do |f| %> <%= render 'shared/error_messages', model: @purchase_address %> <div class='transaction-contents'> <div class='transaction-main'> <h1 class='transaction-title-text'> 購入内容の確認 </h1> <%# 購入内容の表示 %> <div class='buy-item-info'> <%= image_tag @item.image, class: 'buy-item-img' %> <div class='buy-item-right-content'> <h2 class='buy-item-text'> <%= @item.name %> </h2> <div class='buy-item-price'> <p class='item-price-text'>¥<%= @item.price %></p> <p class='item-price-sub-text'><%= @item.shipping.shipping_id %></p> </div> </div> </div> <%# /購入内容の表示 %> <%# 支払額の表示 %> <div class='item-payment'> <h1 class='item-payment-title'> 支払金額 </h1> <p class='item-payment-price'> ¥<%= @item.price %> </p> </div> <%# /支払額の表示 %> <%# <%= form_with id: 'charge-form', class: 'transaction-form-wrap',local: true do |f| %> %> <%# カード情報の入力 %> <%# <div class='credit-card-form'> %> <%# <h1 class='info-input-haedline'> %> <%# クレジットカード情報入力 %> <%# </h1> %> <%# <div class="form-group"> %> <%# <div class='form-text-wrap'> %> <%# <label class="form-text">カード情報</label> %> <%# <span class="indispensable">必須</span> %> <%# </div> %> <%# <%= f.text_field :hoge, class:"input-default", id:"card-number", placeholder:"カード番号(半角英数字)", maxlength:"16" %> %> <%# <div class='available-card'> %> <%# <%= image_tag 'card-visa.gif', class: 'card-logo' %> %> <%# <%= image_tag 'card-mastercard.gif', class: 'card-logo' %> %> <%# <%= image_tag 'card-jcb.gif', class: 'card-logo' %> %> <%# <%= image_tag 'card-amex.gif', class: 'card-logo' %> %> <%# </div> %> <%# </div> %> <%# <div class="form-group"> %> <%# <div class='form-text-wrap'> %> <%# <label class="form-text">有効期限</label> %> <%# <span class="indispensable">必須</span> %> <%# </div> %> <%# <div class='input-expiration-date-wrap'> %> <%# <%= f.text_area :hoge, class:"input-expiration-date", id:"card-exp-month", placeholder:"例)3" %> %> <%# <p>月</p> %> <%# <%= f.text_area :hoge, class:"input-expiration-date", id:"card-exp-year", placeholder:"例)23" %> %> <%# <p>年</p> %> <%# </div> %> <%# </div> %> <%# <div class="form-group"> %> <%# <div class='form-text-wrap'> %> <%# <label class="form-text">セキュリティコード</label> %> <%# <span class="indispensable">必須</span> %> <%# </div> %> <%# <%= f.text_field :hoge, class:"input-default", id:"card-cvc", placeholder:"カード背面4桁もしくは3桁の番号", maxlength:"4" %> %> <%# </div> %> <%# </div> %> <%# /カード情報の入力 %> <%# 配送先の入力 %> <div class='shipping-address-form'> <h1 class='info-input-haedline'> 配送先入力 </h1> <div class="form-group"> <div class='form-text-wrap'> <label class="form-text">郵便番号</label> <span class="indispensable">必須</span> </div> <%= f.text_field :postal_code, class:"input-default", id:"postal-code", placeholder:"例)123-4567", maxlength:"8" %> </div> <div class="form-group"> <div class='form-text-wrap'> <label class="form-text">都道府県</label> <span class="indispensable">必須</span> </div> <%= f.collection_select(:prefecture_id, Prefecture.all, :id, :prefecture_id, {}, {class:"select-box", id:"prefecture"}) %> </div> <div class="form-group"> <div class='form-text-wrap'> <label class="form-text">市区町村</label> <span class="indispensable">必須</span> </div> <%= f.text_field :city, class:"input-default", id:"city", placeholder:"例)横浜市緑区"%> </div> <div class="form-group"> <div class='form-text-wrap'> <label class="form-text">番地</label> <span class="indispensable">必須</span> </div> <%= f.text_field :house_number, class:"input-default", id:"addresses", placeholder:"例)青山1-1-1"%> </div> <div class="form-group"> <div class='form-text-wrap'> <label class="form-text">建物名</label> <span class="form-any">任意</span> </div> <%= f.text_field :building_name, class:"input-default", id:"building", placeholder:"例)柳ビル103"%> </div> <div class="form-group"> <div class='form-text-wrap'> <label class="form-text">電話番号</label> <span class="indispensable">必須</span> </div> <%= f.text_field :phone_number, class:"input-default", id:"phone-number", placeholder:"例)09012345678",maxlength:"11"%> </div> </div> <%# /配送先の入力 %> <div class='buy-btn'> <%= f.submit "購入" ,class:"buy-red-btn", id:"button" %> </div> <%# <% end %> %> </div> </div> <% end %> <%= render "shared/second-footer"%>
もう一回 やり直してみたら、やっぱり問題点はここでした!!!
def save purchase = Purchase.create(user_id: user_id, item_id: item_id) # 変数purchase に代入しなかったため Address.create(postal_code: postal_code, city: city, house_number: house_number, phone_number: phone_number, building_name: building_name, prefecture_id: prefecture_id, purchase_id: purchase.id)
無事解決できたのは嬉しいけど、こんなミスをもう二度と経験したくないから、メモとして残しときます!!!
クレジット決済ミニアプリ実装について
その2テストコードを実装
RSpecとFactoryBotのGemを導入
Gemfileに以下を追記しましょう。:development, :testと指定するグループ内に記述すること
# 省略 group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] gem 'rspec-rails' gem 'factory_bot_rails' end # 省略
rspec gemを導入
USERnoMacBook-puro:payjp_practice user$ bundle install # 省略 Using webpacker 4.3.0 Bundle complete! 19 Gemfile dependencies, 80 gems now installed. Use `bundle info [gemname]` to see where a bundled gem is installed. USERnoMacBook-puro:payjp_practice user$
Rspecをインストール
USERnoMacBook-puro:payjp_practice user$ rails g rspec:install Running via Spring preloader in process 49554 create .rspec create spec create spec/spec_helper.rb create spec/rails_helper.rb USERnoMacBook-puro:payjp_practice user$
.rspecの設定ファイルに、テストコードの実行ログが見やすくなるため
--require spec_helper --format documentation # ←こちらを記述!
Orderモデルの単体テストコードを記述するspecファイルを生成
USERnoMacBook-puro:payjp_practice user$ rails g rspec:model order Running via Spring preloader in process 49604 create spec/models/order_spec.rb invoke factory_bot create spec/factories/orders.rb USERnoMacBook-puro:payjp_practice user$
FactoryBotでデータを生成
FactoryBot.define do factory :order do price {3000} #←こちらを記述 end end
テストコードを実装
require 'rails_helper' RSpec.describe Order, type: :model do pending "add some examples to (or delete) #{__FILE__}"#←こちらを削除 before do @order = FactoryBot.build(:order) # インスタンスを生成 end context '内容に問題ない場合' do it "priceがあれば保存ができること" do # example1 expect(@order).to be_valid end end context '内容に問題がある場合' do it "priceが空では保存ができないこと" do # example2 @order.price = nil @order.valid? expect(@order.errors.full_messages).to include("Price can't be blank") end end end
テスト成功か確認
USERnoMacBook-puro:payjp_practice user$ bundle exec rspec spec/models/order_spec.rb Order 内容に問題ない場合 priceがあれば保存ができること 内容に問題がある場合 priceが空では保存ができないこと Finished in 0.0213 seconds (files took 1.21 seconds to load) 2 examples, 0 failures # ← 成功した USERnoMacBook-puro:payjp_practice user$
未経験でのWebエンジニア転職を目指して、プログラミングを学習しています。日々の学習した内容をアウトプット用にはてなを書き始めました。TECH CAMP 102 期学生
クレジット決済ミニアプリ実装について
クレジット決済ミニアプリ実装について(その1)
クレジットカード決済代行サービスを利用することは、以下のようなメリットがあります。
- 会社ごとに事務的手続きをする必要がない
- 決済代行サービスが提供するAPIなどを用いることで、クレジットカード情報の取り扱いに関するセキュリティ対策をしなくても、安全なやり取りができる
早速、アプリケーションを作成レツゴ!!!
# アプリを作成するprojectsディレクトリに移動 % cd ~/projects # payjp_practiceという新規アプリをRailsバージョン6.0で、-dオプションをつけMySQLの使用を明示して作成 % rails _6.0.0_ new payjp_practice -d mysql # payjp_practiceに移動 % cd payjp_practice # データベースの生成 % rails db:create
# 開発用ファイル生成 USERnoMacBook-puro:payjp_practice user$ rails db:create Created database 'payjp_practice_development' Created database 'payjp_practice_test' USERnoMacBook-puro:payjp_practice user$
order モデルを作成
# rails g model order USERnoMacBook-puro:payjp_practice user$ rails g model order Running via Spring preloader in process 47891 invoke active_record create db/migrate/20211003013422_create_orders.rb create app/models/order.rb invoke test_unit create test/models/order_test.rb create test/fixtures/orders.yml USERnoMacBook-puro:payjp_practice user$
ordersテーブルを作成
class CreateOrders < ActiveRecord::Migration[6.0] def change create_table :orders do |t| t.integer :price ,null: false # ←追加 t.timestamps end end end
コマンドを実行してデータベースにテーブル情報を反映
USERnoMacBook-puro:payjp_practice user$ rails db:migrate == 20211003013422 CreateOrders: migrating ===================================== -- create_table(:orders) -> 0.0396s == 20211003013422 CreateOrders: migrated (0.0397s) ============================ USERnoMacBook-puro:payjp_practice user$
バリデーションを設定
class Order < ApplicationRecord validates :price, presence: true end
ルーティングを設定
Rails.application.routes.draw do root to: 'orders#index' resources :orders, only:[:create] end
ordersコントローラーを作成
USERnoMacBook-puro:payjp_practice user$ rails g controller orders Running via Spring preloader in process 48287 create app/controllers/orders_controller.rb invoke erb create app/views/orders invoke test_unit create test/controllers/orders_controller_test.rb invoke helper create app/helpers/orders_helper.rb invoke test_unit invoke assets invoke scss create app/assets/stylesheets/orders.scss USERnoMacBook-puro:payjp_practice user$
indexアクションとcreateアクションを定義
class OrdersController < ApplicationController def index end def create end end
ビューファイルindex.html.erbを作成,記述
<%= form_with model: @order, id: 'charge-form', class: 'card-form',local: true do |f| %> <div class='form-wrap'> <%= f.label :price, "金額" %> <%= f.text_field :price, class:"price", placeholder:"例)2000" %> </div> <%= f.submit "購入", class:"button", id: "button" %> <% end %>
とstyle.cssファイルを作成,記述略
保存できるようにする
class OrdersController < ApplicationController def index @order = Order.new end def create @order = Order.new(order_params) if @order.valid? @order.save return redirect_to root_path else render 'index' end end private def order_params params.require(:order).permit(:price) end end
ブラウザで挙動を確認
ok!!!しっかりデータ保存できた!
バリデーションがしっかりと機能し、エラーメッセージが出力されるか確認
- gemファイルにgem 'pry-rails'を記述
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] gem 'pry-rails'
USERnoMacBook-puro:payjp_practice user$ bundle install Using webpacker 4.3.0 中略 Bundle complete! 18 Gemfile dependencies, 78 gems now installed. Use `bundle info [gemname]` to see where a bundled gem is installed. USERnoMacBook-puro:payjp_practice user$
- 次orders_controller.rbにbinding.pryを追記
def create @order = Order.new(order_params) binding.pry # ←ここに記述 if @order.valid? @order.save binding.pry # ←ここに記述しても機能しない return redirect_to root_path else render 'index' end end
- からのデータを送信すると
Started POST "/orders" for ::1 at 2021-10-03 11:33:34 +0900 Processing by OrdersController#create as HTML Parameters: {"authenticity_token"=>"K8vy474+YQ1fEO0CXPTV/FfvsLN+DzPIqHqklYMmPqWvj2ujBzwm3XW3dMYNW+Rw7mZQ7gOEbhqUvjYDZFRbcQ==", "order"=>{"price"=>""}, "commit"=>"購入"} From: /Users/user/projects/payjp_practice/app/controllers/orders_controller.rb:8 OrdersController#create: 6: def create 7: @order = Order.new(order_params) => 8: binding.pry 9: if @order.valid? 10: @order.save 11: return redirect_to root_path 12: else 13: render 'index' 14: end 15: end [1] pry(#<OrdersController>)>
- @order.valid?を叩くと
[1] pry(#<OrdersController>)> @order.valid? => false
- 次エラーメッセージを確認:@order.erros.full_messages を叩く
[3] pry(#<OrdersController>)> @order.errors.full_messages => ["Price can't be blank"] [4] pry(#<OrdersController>)>
「"Price can't be blank"」のエラーメッセージが生成されることがわかりました
未経験でのWebエンジニア転職を目指して、プログラミングを学習しています。日々の学習した内容をアウトプット用にはてなを書き始めました。TECH CAMP 102 期学生
マークダウンの書き方の練習
クインペッパー
- 箇条書き
- ダイナソん
- 目が飛び出す
- 美しい白鳥
- クインのドレス
- クインのキラキラ王冠
マークダウン記法の練習
- ハイフン、プラス、アスタリスクのいずれかで箇条書きリストを記述可能。 ※ハイフン、プラス、アスタリスクと箇条書きの項目の間には半角スペースを1つ入れること
- ハイフン、プラス、アスタリスクのいずれかで箇条書きリストを記述可能。 ※ハイフン、プラス、アスタリスクと箇条書きの項目の間には半角スペースを1つ入れること
ハイフン、プラス、アスタリスクのいずれかで箇条書きリストを記述可能。 ※ハイフン、プラス、アスタリスクと箇条書きの項目の間には半角スペースを1つ入れること
リスト
- ネストリスト1
- ネストリスト1_1
- ネストリスト1_1_1
- ネストリスト1_1_2
- ネストリスト1_1
- ネストリスト2
- ネストリスト1
数値ドット+半角スペース+内容で 数値付き箇条書きできる 1
- . 数値ドット+半角スペース+内容で 数値付き箇条書きできる 3
- . 数値ドット+半角スペース+内容で 数値付き箇条書きできる 2
- 数値ドット+半角スペース+内容で 数値付き箇条書きできる 3
- . 数値ドット+半角スペース+内容で 数値付き箇条書きできる 3
数値ドット+半角スペース+内容で 数値付き箇条書きできる 3
番号付きリスト1
- 番号付きリスト1_1
- 番号付きリスト1_2
- 番号付きリスト1_3
- 番号付きリスト1_1
- 番号付きリスト2
- 番号付きリスト3
お世話になります。xxxです。
ご連絡いただいた、バグの件ですが、仕様です。
お世話になります。
ご連絡ありがとう
強調強調強調アスタリスク1つ
水平線
強調強調強調アスタリスク2つ
強調強調強調アスタリスク3つ
水平線
取り消し線チルダ2個
header1 | header2 | header3 |
---|---|---|
align left | align right | align center |
a | b | c |
header1 | header2 | header3 |
---|---|---|
align left | align right | align center |
a | b | c |
コード | 名前 | 誕生日 |
---|---|---|
1 | 山田太郎 | 1/1 |
2 | 山田花子 | 2/29 |
99 | その他 | 12/31 |
中央寄せ | 左寄せ | 右寄せ |
ユーザー管理機能の実装について
ユーザー管理機能の実装について
- ユーザーログイン機能
サインアウト、ログインしていない場合(条件分岐)からログイン画面への遷移時
使用するメソッドは図のように
- ユーザーの名前をDBへ保存できるように設定
deviseコントローラーに適応できるようにするために、全コントローラーの共通処理を記述し行えるapplication_controllerを編集する 下の各図
deviseコントロラーから呼び出された時使用するヘルパーメソッド
before_action処理を行う
devise_parameter_sanitizerメソッドとpermit(特定のカラムを許容するメソッド)組み合わせることで新規登録(:sign_up)ユーザー情報(:name)を取得する
自己研鑚のため発信しておりますので、不足の部分があるので、ご了承ください〜
じゃあまた明日〜
Gemのdeviseを用いてユーザー管理機能の実装
Gemのdeviseを用いてユーザー管理機能の実装
deviseのインストール
ターミナル上:
bundle install
- railsアプリケーションにdeviseを導入する
ターミナル上:
rails s
(deviseを導入する前、サーバーを再起動するため)
rails g devise:install
ユーザーテーブルの作成
- ターミナル上: rails g devise user
このコマンドでuserモデル(テーブル)と共にmigrateファイルやroutesもが生成する
- 必要のnameカラムをuserテーブルに追加する
下図の通りmigrateファイル中のemail,passwordカラムがもう生成されていた
ターミナル上:rails db:migrate 実行
今日はここまでにしよう。。。