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

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

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

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

Q&A

解決済

2回答

2754閲覧

一つのフォームからのデータを同時に複数のテーブルに保存したい

pico0120

総合スコア2

Ruby on Rails 6

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

0グッド

0クリップ

投稿2020/10/29 07:08

編集2020/10/30 14:15

Railsでフリマアプリのクローンアプリを作成中です。
商品購入時に、商品の配送先(住所)情報と購入した商品の情報を同時にそれぞれのテーブルに保存できるようにしたいです。

自分では以下のように考えましたが、この記述では、"param is missing or the value is empty: order_address"というエラーが出てうまく情報を渡すことができません。

Formオブジェクトで、まずフォームからパラメーターとして送られてきた情報をテーブルに保存する。
order_address.rb

ruby

1class OrderAddress 2 include ActiveModel::Model 3 attr_accessor :postal_code, :prefecture_id, :city, :address_num, :building_name, :phone, :item.id, :params[:token], :current_user.id 4 5 with_options presence: true do 6 validates :postal_code, format: {with: /\A[0-9]{3}-[0-9]{4}\z/, message: "is invalid. Include hyphen(-)"} 7 validates :city, format: { with: /\A[ぁ-んァ-ン一-龥]/, message: "is invalid. Input full-width characters."} 8 validates :address_num 9 validates :phone, format: {with: /\A\d{10}\z|\A\d{11}\z/ , message: "is invalid."} 10 validates :token 11 end 12 validates :prefecture_id, numericality: { other_than: 0, message: "can't be blank" } 13 14 15 def save 16 Order.create(item:id) 17 Address.create(postal_code: postal_code, address_num: address_num, building_name: building_name, phone: pOrder.create(user: current_user.id, item: id) 18 Address.create(postal_code: postal_code, prefecture_id: prefecture_id, city: city, address_num: address_num, building_name: building_name, phone: phone)hone) 19 end 20end 21 22 23

次に、コントローラーのnewアクション、createアクションでFormオブジェクトのインスタンスを生成するようにする。
orders_controller.rb

ruby

1class OrdersController < ApplicationController 2 3 def index 4 @order = Order.new(order_params) 5 end 6 7 def new 8 end 9 10 def create 11 @order_address = OrderAddress.new(order_params) 12 if @order_address.valid? 13 @order_address.save 14 redirect_to root_path 15 else 16 render action: :index 17 end 18 end 19 20 private 21 def order_params 22 params.permit(:postal_code, :prefecture_id, :city, :address_num, :building_name, :phone, :item_id).merge(token: params[:token], user_id: current_user.id) 23 end 24 25 def pay_item 26 Payjp.api_key = ENV["PAYJP_SECRET_KEY"] 27 Payjp::Charge.create( 28 price: order_params[:id], 29 card: order_params[:token], 30 currency: 'jpy' 31 ) 32 end 33end 34 35

(PAY.JPでクレジットカード決済機能もつけています。)
card.js

ruby

1 2const pay = () => { 3 Payjp.setPublicKey(process.env.PAYJP_PUBLIC_KEY); 4 const form = document.getElementById("charge-form"); 5 form.addEventListener("submit", (e) => { 6 e.preventDefault(); 7 8 const formResult = document.getElementById("charge-form"); 9 const formData = new FormData(formResult); 10 11 const card = { 12 number: formData.get("order[number]"), 13 exp_month: formData.get("order[exp_month]"), 14 exp_year: `20${formData.get("order[exp_year]")}`, 15 cvc: formData.get("order[cvc]"), 16 }; 17 18 Payjp.createToken(card, (status, response) => { 19 if (status == 200) { 20 const token = response.id; 21 const renderDom = document.getElementById("charge-form"); 22 const tokenObj = `<input value=${token} name='token' type="hidden">`; 23 renderDom.insertAdjacentHTML("beforeend", tokenObj); 24 } 25 26 document.getElementById("card-number").removeAttribute("name"); 27 document.getElementById("card-exp-month").removeAttribute("name"); 28 document.getElementById("card-exp-year").removeAttribute("name"); 29 document.getElementById("card-cvc").removeAttribute("name"); 30 31 document.getElementById("charge-form").submit(); 32 }); 33 }); 34}; 35 36window.addEventListener("load",pay);

以下、フォームから入力する画面のビューです。
住所情報(postal_code, prefecture_id, city, address_num, building_name, phone, order_id)をadressesテーブル、購入情報(user_id, item_id)はordersテーブルに保存させようとしています。

ruby

1<div class='transaction-contents'> 2 <div class='transaction-main'> 3 <h1 class='transaction-title-text'> 4 購入内容の確認 5 </h1> 6 <%# 購入内容の表示 %> 7 <div class='buy-item-info'> 8 <%= image_tag "item-sample.png", class: 'buy-item-img' %> 9 <div class='buy-item-right-content'> 10 <h2 class='buy-item-text'> 11 <%= "商品名" %> 12 </h2> 13 <div class='buy-item-price'> 14 <p class='item-price-text'>¥<%= "999,999,999" %></p> 15 <p class='item-price-sub-text'>(税込)送料込み</p> 16 </div> 17 </div> 18 </div> 19 <%# /購入内容の表示 %> 20 21 <%# 支払額の表示 %> 22 <div class='item-payment'> 23 <h1 class='item-payment-title'> 24 支払金額 25 </h1> 26 <p class='item-payment-price'> 27 ¥<%= "販売価格" %> 28 </p> 29 </div> 30 <%# /支払額の表示 %> 31 32 <%= form_with(model: @order_address, url: item_orders_path, id: 'charge-form', class: 'transaction-form-wrap',local: true) do |f| %> 33 <%# カード情報の入力 %> 34 <div class='credit-card-form'> 35 <h1 class='info-input-haedline'> 36 クレジットカード情報入力 37 </h1> 38 <div class="form-group"> 39 <div class='form-text-wrap'> 40 <label class="form-text">カード情報</label> 41 <span class="indispensable">必須</span> 42 </div> 43 <%= f.text_field :number, class:"input-default", id:"card-number", placeholder:"カード番号(半角英数字)", maxlength:"16" %> 44 <div class='available-card'> 45 <%= image_tag 'card-visa.gif', class: 'card-logo'%> 46 <%= image_tag 'card-mastercard.gif', class: 'card-logo'%> 47 <%= image_tag 'card-jcb.gif', class: 'card-logo'%> 48 <%= image_tag 'card-amex.gif', class: 'card-logo'%> 49 </div> 50 </div> 51 <div class="form-group"> 52 <div class='form-text-wrap'> 53 <label class="form-text">有効期限</label> 54 <span class="indispensable">必須</span> 55 </div> 56 <div class='input-expiration-date-wrap'> 57 <%= f.text_area :exp_month, class:"input-expiration-date", id:"card-exp-month", placeholder:"例)3" %> 58 <p>月</p> 59 <%= f.text_area :exp_year, class:"input-expiration-date", id:"card-exp-year", placeholder:"例)23" %> 60 <p></p> 61 </div> 62 </div> 63 <div class="form-group"> 64 <div class='form-text-wrap'> 65 <label class="form-text">セキュリティコード</label> 66 <span class="indispensable">必須</span> 67 </div> 68 <%= f.text_field :cvc,class:"input-default", id:"card-cvc", placeholder:"カード背面4桁もしくは3桁の番号", maxlength:"4" %> 69 </div> 70 </div> 71 <%# /カード情報の入力 %> 72 73 <%# 配送先の入力 %> 74 <div class='shipping-address-form'> 75 <h1 class='info-input-haedline'> 76 配送先入力 77 </h1> 78 <div class="form-group"> 79 <div class='form-text-wrap'> 80 <label class="form-text">郵便番号</label> 81 <span class="indispensable">必須</span> 82 </div> 83 <%= f.text_field :postal_code, class:"input-default", id:"postal-code", placeholder:"例)123-4567", maxlength:"8" %> 84 </div> 85 <div class="form-group"> 86 <div class='form-text-wrap'> 87 <label class="form-text">都道府県</label> 88 <span class="indispensable">必須</span> 89 </div> 90 <%= f.collection_select(:prefecture_id, Prefecture.all, :id, :name, {}, {class:"select-box", id:"prefecture"}) %> 91 </div> 92 <div class="form-group"> 93 <div class='form-text-wrap'> 94 <label class="form-text">市区町村</label> 95 <span class="indispensable">必須</span> 96 </div> 97 <%= f.text_field :city, class:"input-default", id:"city", placeholder:"例)横浜市緑区"%> 98 </div> 99 <div class="form-group"> 100 <div class='form-text-wrap'> 101 <label class="form-text">番地</label> 102 <span class="indispensable">必須</span> 103 </div> 104 <%= f.text_field :address_num, class:"input-default", id:"addresses", placeholder:"例)青山1-1-1"%> 105 </div> 106 <div class="form-group"> 107 <div class='form-text-wrap'> 108 <label class="form-text">建物名</label> 109 <span class="form-any">任意</span> 110 </div> 111 <%= f.text_field :building_name, class:"input-default", id:"building", placeholder:"例)柳ビル103"%> 112 </div> 113 <div class="form-group"> 114 <div class='form-text-wrap'> 115 <label class="form-text">電話番号</label> 116 <span class="indispensable">必須</span> 117 </div> 118 <%= f.text_field :phone, class:"input-default", id:"phone-number", placeholder:"例)09012345678",maxlength:"11"%> 119 </div> 120 </div> 121 <%# /配送先の入力 %> 122 <div class='buy-btn'> 123 <%= f.submit "購入" ,class:"buy-red-btn" %> 124 </div> 125 <% end %> 126 </div> 127</div>

大変恐縮ですが、何が問題かご教授いただけませんでしょうか。
超初心者のため謎コードが多いかもしれませんが、どうぞよろしくお願いいたします。

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

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

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

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

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

winterboum

2020/10/30 02:38

formからどういう構造のデータが送られてくるのか そのどの部分をどのtableに入れたいのか も見せてください
pico0120

2020/10/30 05:24

ご返信ありがとうございます! ご指摘いただいた不足情報を追記いたしました。 大変お手数をおかけしますが、よろしくお願いします。
guest

回答2

0

viewからおくられてくるパラメーターとorder_paramsの記述がマッチしていないように思われます。
logをみるとパラメーターが出ていますから、それと比べてください。

また、パラメーターに「何をいくらで買う」のかという情報が含まれないように思われます。それは別に持っているから不要ということでしょうか?

投稿2020/10/30 12:04

winterboum

総合スコア23347

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

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

pico0120

2020/10/30 14:22

いつも早々にご回答くださりありがとうございます! ご指摘いただいた内容を踏まえ修正しました。 購入情報がうまく取得できていなかったのが原因だったようです。 「何をいくらで買う」のかという情報はordersテーブルに存在し、order_address.rbでOrder.createを変数orderに代入し、Address.createでorder.idとして取得し保存できました。 おかげさまで解決いたしました☺︎ ありがとうございました✨
guest

0

自己解決

ruby

1 2class OrderAddress 3 include ActiveModel::Model 4 attr_accessor :postal_code, :prefecture_id, :city, :address_num, :building_name, :phone, :item_id, :token, :user_id 5 6 with_options presence: true do 7 validates :postal_code, format: {with: /\A[0-9]{3}-[0-9]{4}\z/, message: "is invalid. Include hyphen(-)"} 8 validates :city, format: { with: /\A[ぁ-んァ-ン一-龥]/, message: "is invalid. Input full-width characters."} 9 validates :address_num 10 validates :phone, format: {with: /\A\d{10}\z|\A\d{11}\z/ , message: "is invalid."} 11 validates :token 12 end 13 14 validates :prefecture_id, numericality: { other_than: 0, message: "can't be blank" } 15 16 17 def save 18 order = Order.create(user_id: user_id, item_id: item_id) 19 Address.create(postal_code: postal_code, prefecture_id: prefecture_id, city: city, address_num: address_num, building_name: building_name, phone: phone, order_id: order.id) 20 end 21end 22 23 24

投稿2020/10/30 14:24

pico0120

総合スコア2

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問