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

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

ただいまの
回答率

87.77%

ruby on rails 配列のデータ送信方法

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 413

score 29

前提・実現したいこと

Ruby on rails 初心者です。
現在、ECサイトの構築を行っており、つまずいたのは「DBへの配列情報」の登録処理です。

cart_itemsテーブルに入っているカート情報が2つ以上の場合、配列を使ってordersテーブルに情報が登録される処理を作成しております。

「商品購入」ボタン押下→createアクションaddressesテーブルordrsテーブルに商品情報などを登録(購入する商品が1つの場合であれば問題ないのですが、2つ以上になると配列を使わないといけないかなと思っております。)

という流れを構築しようと考えています。

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

商品がテーブルに登録されない。
ログを見ると、"product_id"=>["6", "1"], "quantity"=>["1", "2"],というように、配列で送られているところまでは実装できましたが、
テーブルにsaveする時(もしくはその一個手前:今回の場合、address_paramsアクション)にSQL文が発行されないのではないかと考えております。

配列で送られてきたデータをテーブルに1つずつ(2つの商品があれば2レコード)送信する方法をどなたか教えていただけませんでしょうか。

該当のソースコード

(views/orders/index.html.erb)一部記載
<%= form_for(@address, url: orders_path) do |f|%>
                    <%= f.hidden_field :user_id, value: current_user.id %>
                    <%= f.hidden_field :last_name, value: session[:last_name] %>
                    <%= f.hidden_field :first_name, value: session[:first_name] %>
                    <%= f.hidden_field :furi_last_name, value: session[:furi_last_name] %>
                    <%= f.hidden_field :furi_first_name, value: session[:furi_first_name] %>
                    <%= f.hidden_field :postal_code, value: session[:postal_code] %>
                    <%= f.hidden_field :prefecture, value: session[:prefecture] %>
                    <%= f.hidden_field :address, value: session[:address] %>
                    <%= f.hidden_field :store, value: session[:store] %>
                    <%= f.hidden_field :how_to_pay, value: session[:how_to_pay] %>

                    <%= f.fields_for :orders do |o|%>
                        <% @cart_items.each do |cart_item|%>
                            <% product = Product.find_by(id: cart_item.product_id) %>
                                <%= hidden_field_tag "product_id[]", product.id %>
                                <%= hidden_field_tag "quantity[]", cart_item.quantity %>
                        <% end%>
                    <% end %>

                <p><%= f.submit "注文確定", class: 'btn' %></p>
                <% end %>
(controllers/ordes_controller.rb)★一部記載
def index
        cart = Cart.find_by(user_id: current_user.id)
        @cart_items = CartItem.where(cart_id: cart.id)
        @product= Product.find_by(id: current_user.id)

        @address = Address.new
        @order = @address.orders.build

    end

    def create
        @address = Address.new(address_params)
        if @address.save
            flash[:success] = "購入が完了しました。"
            session.delete(:store)
            session.delete(:last_name)
            session.delete(:first_name)
            session.delete(:furi_last_name)
            session.delete(:furi_first_name)
            session.delete(:postal_code)
            session.delete(:prefecture)
            session.delete(:address)
            session.delete(:how_to_pay)
            CartItem.where(cart_id: current_cart).delete_all
            redirect_to root_path
        else
            render "index"
        end
    end

    private

    def address_params
        params.require(:address).permit(:user_id, :last_name, :first_name, :furi_last_name, :furi_first_name, :postal_code, :prefecture, :address, :store, :how_to_pay, orders_attributes: [
            product_id:[], quantity:[]
        ])
    end
(models/address.rb)
class Address < ApplicationRecord
    has_many :orders
    accepts_nested_attributes_for :orders
end

 addressesテーブル(カラム)
id
user_id
last_name
first_name
furi_last_name
furi_first_name
postal_code
prefecture
address
store
how_to_pay
(models/order.rb)
class Order < ApplicationRecord
    belongs_to :address
    belongs_to :product
end

ordersテーブル(カラム)
id
product_id
quantity
address_id
(models/product.rb)※一部記載
class Product < ApplicationRecord

    has_many :orders

end

productsテーブル(カラム)
id
name
price
count
comment
category
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

check解決した方法

0

下記の通りに変更すると、うまくいきました!

(views/orders/index.html.erb)一部記載
<%= form_for(@address, url: orders_path) do |f|%>
                    <%= f.hidden_field :user_id, value: current_user.id %>
                    <%= f.hidden_field :last_name, value: session[:last_name] %>
                    <%= f.hidden_field :first_name, value: session[:first_name] %>
                    <%= f.hidden_field :furi_last_name, value: session[:furi_last_name] %>
                    <%= f.hidden_field :furi_first_name, value: session[:furi_first_name] %>
                    <%= f.hidden_field :postal_code, value: session[:postal_code] %>
                    <%= f.hidden_field :prefecture, value: session[:prefecture] %>
                    <%= f.hidden_field :address, value: session[:address] %>
                    <%= f.hidden_field :store, value: session[:store] %>
                    <%= f.hidden_field :how_to_pay, value: session[:how_to_pay] %>

                    <% @cart_items.each do |cart_item|%>★重要
                            <%= f.fields_for :orders do |o|%>
                            <% product = Product.find_by(id: cart_item.product_id) %>
                                <%= o.hidden_field :product_id, value: product.id %>
                                <%= o.hidden_field :quantity, value: cart_item.quantity %>
                        <% end%>
                    <% end %>

                <p><%= f.submit "注文確定", class: 'btn' %></p>
                <% end %>
private
def address_params
        params.require(:address).permit(:user_id, :last_name, :first_name, :furi_last_name, :furi_first_name, :postal_code, :prefecture, :address, :store, :how_to_pay, orders_attributes: [
            :product_id, :quantity
        ])
end

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

product_id、quantityには数値しか入らないため、配列を登録しようとしても登録はできませんね。
配列で受け取ったproduct_id:[], quantity:[]をそれぞれ1つづつ登録する必要があります。

Active Record Nested Attributes
少し調べた感じですと
↓ このように渡しているので、

Member.create(
  name: 'joe',
  posts_attributes: [
    { title: 'Foo' },
    { title: 'Bar' }
  ]
)

formから渡す内容を
↓ このようになるように作るとできるのではないでしょうか

orders_attributes: [
  { product_id: 6, quantity: 1 },
  { product_id: 1, quantity: 2 } 
])

また、渡すパラメータなどの整合性はmodelデータやテーブル設計を見ないとわらからないので、
それらの情報は載せておいたほうがよいですね!

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/09/13 10:32

    necocoa様
    ご回答ありがとうございます。
    また、調べていただいて、本当にありがとうございます。

    modelデータやテーブルのカラム情報も追記させていただきました!

    キャンセル

  • 2020/09/13 11:54

    index.html.erbの該当部分を下記のように変え、
    <%= hidden_field_tag "product_id[][product]", product.id %>
    <%= hidden_field_tag "quantity[][count]", cart_item.quantity %>

    orders_controller.rbの該当部分も下記のように変えました。
    def address_params
    params.require(:address).permit(:user_id, :last_name, :first_name, :furi_last_name, :furi_first_name, :postal_code, :prefecture, :address, :store, :how_to_pay, orders_attributes: [
    product_id: [:product],
    product_id: [:count]
    ])
    end

    その結果、パラメーターは
    "product_id"=>[{"product"=>"6"}, {"product"=>"5"}], "quantity"=>[{"count"=>"1"}, {"count"=>"1"}]
    になりましたが、だめでした。

    他にも、ダメ元で
    product_id.zip(quantity) do |x, y|
    {product_id: "#{x}", quantity: "#{y}"}
    end
    とやってみましたが、product_id.zip(quantity) do |x, y|でエラーとなりました。

    キャンセル

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

  • ただいまの回答率 87.77%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る