mochi93kou
@mochi93kou (まるも)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

Railaでカート機能で保存できない

解決したいこと

railsでカート機能で
カートに商品を保存できません。

発生している問題

carts_controllerの
カートに商品を追加する機能を
別のコントローラーである
products_controllerのshowページで
form_withを使って実装しようとしましたが
saveされません。

該当するソースコード

carts_controller
class CartsController < ApplicationController
  before_action :setup_cart_item!, only:[:create]

  def show
    @cart_items = current_cart.cart_item.includes([:product])
    @total = @cart_items.inject(0) { |sum, item| sum + item.sum_of_price }
  end

  def create
    if @cart_item.blank?
      @cart_item = current_cart.cart_items.build(product_id: params[:product_id])
    end

    @cart_item.quantity += params[:quantity].to_i
    @cart_item.save
    redirect_to root_path
  end
  
  private
    def setup_cart_item!
      @cart_item = current_cart.cart_items.find_by(product_id: params[:product_id])
    end
end
cart_helper.html.erb
module CartsHelper
  
  def current_cart
    if current_user
      @current_cart = current_user.cart || current_user.create_cart
    else
      @current_cart = Cart.find(session[:cart_id]) || Cart.create
      session[:cart_id] ||= @current_cart.id
    end
  end
end
class Cart < ApplicationRecord
  has_many :cart_items, dependent: :destroy
end

class CartItem < ApplicationRecord
  belongs_to :product
  belongs_to :cart

  def sum_of_price
    product.price * quantity
  end
end

class Product < ApplicationRecord
  mount_uploaders :images, ProductUploader
  validates :images, presence: true
  validates :introduction, presence: true, length: { maximum: 500 }
  validates :name, presence: true, uniqueness: true, length: { maximum: 100 }
  validates :price, presence: true, numericality: { greater_than_or_equal_to: 1, less_than_or_equal_to: 10000 }
  default_scope -> { order(created_at: :desc) }
end
show.html.erb
<%= provide(:title, "商品詳細") %>
<div class="sp-page">
  <div class="product_show">
    <div class="product_show-detail">
      <div class="product_show-name">
        <%= @product.name%>
      </div>
      <div class="product_show-price">
        <%= @product.price %>円/匹 (税込)
      </div>
      <div class="product_show-slide">
        <% @product.images.each do |img| %>
          <%= image_tag img.to_s, class:"product_show-img" %>
        <% end %>
      </div>

      <div class="product_show-introduction">
        <%= simple_format(@product.introduction) %>
      </div>

      <div class="product_show-cart">
        <div class="product_cart-price">
          <%= @product.price %>円/匹 (税込)
        </div>
        <%= form_with(model: @cart, local: true, url: add_item_url, method: :post) do |f| %>
          <%= f.label :数量 %>
          <%= f.select :quantity, [*1..50] %>
          <%= f.submit "カートへ追加", class:"product_show-btn"%>
        <% end %>
      </div>
    </div>
  </div>
  <div class="link-tab">
    <div class="link">
      <%= link_to "TOPへ戻る", '/' %>
    </div>
    <div class="link">
      <%= link_to "商品一覧へ戻る", '/products' %>
    </div>
  </div>
</div>
products_controller
class ProductsController < ApplicationController
  before_action :admin_user, only:[:new, :create, :update, :destroy]

  def new
    @product = Product.new
  end

  def create
    @product = Product.new(product_params)
    if @product.save
      flash[:notice] = "商品を登録しました"
      redirect_to products_path
    else
      render 'new'
    end
  end

  def index
    @products = Product.all
  end

  def show
    @product = Product.find(params[:id])
    @cart = current_cart
  end
  
  def update

  end

  def destroy

  end

  private
    def product_params
      params.require(:product).permit(:name, :price, :introduction, {images: []})
    end
end

###試したこと
createアクションで

  def create
    if @cart_item.blank?
      @cart_item = current_cart.cart_items.build(product_id: 1)
    end

    @cart_item.quantity += params[:quantity].to_i
    @cart_item.save
    redirect_to root_path
  end

product_idを固定すると保存される

product_idの取得の仕方に問題があるのではないかと勝手に想像しています。
解決方法を教えてください、よろしくお願いします。

0

3Answer

 @cart_item = current_cart.cart_items.build(product_id: params[:product_id])

この一文消したらどうですか?

0Like

Comments

  1. @mochi93kou

    Questioner

    消したときに商品を初めて追加したときにうまく追加できなくなると思うのですが、そんなことないですかね?
<%= form_with(model: @cart, local: true, url: add_item_url, method: :post) do |f| %>
  <%= f.label :数量 %>
  <%= f.select :quantity, [*1..50] %>
  <%= f.submit "カートへ追加", class:"product_show-btn"%>
<% end %>
def create
  if @cart_item.blank?
    @cart_item = current_cart.cart_items.build(product_id: params[:product_id])
  end

CartItemにproduct_idがあるわけですよね?それにしてはform_with(model: @cartとしているので、

  1. modelの対象が違うんじゃないかなというのと
  2. そもそもform_with内でもproductの指定がないような...(add_item_urlの中にある?)

多分ルーティング辺りをよく理解して、カートに追加していくだけなら

POSTの/cart_itemsというパスを持って(cart_itemsのcreateアクション)そこのコントローラーでproduct_id、quantityなりを受け取ってという感じなような気がします。

paramsの内容を知りたいなら

  • rails s実行中のログを見るか
  • p params.to_unsafe_hをコントローラーのアクションメソッドに書いたり

してみてください。

0Like

Comments

  1. @mochi93kou

    Questioner

    回答ありがとございます。
    form_with内に以下のように
    <%= f.hidden_field :product_id, value: @product.id %>
    を追加したらうまく動いたのですがこれでは良くないですか?
<%= form_with(model: @cart, local: true, url: add_item_url, method: :post) do |f| %>
  <%= f.hidden_field :product_id, value: @product.id %>

  <%= f.label :数量 %>
  <%= f.select :quantity, [*1..50] %>
  <%= f.submit "カートへ追加", class:"product_show-btn"%>
<% end %>

こうしたと言うならそれはそれで動きますが、Railsの機能はあまり使ってないので少々勿体ない気はします。
@cartにはproduct_idは無いので、@productをさらに変数として持ってそれを無理やり突っ込んでるだけなので、本来であればCartItemを対象のモデルとしてそのインスタンス変数(@cart_item)を持った上で、@cart_itemにproductの情報を設定しておけばもっとスマートになります。

0Like

Comments

  1. @mochi93kou

    Questioner

    回答ありがとうございます。
    beforeactionで@cart_itemを定義していますが、それでは動きませんか?
  2. 実際やってみたらどうなりますか?
    多分route.rbの設定が合わせて必要な気はしますが... そうすると処理するコントローラーはCartsControllerでは無くなるような気もします。
  3. @mochi93kou

    Questioner

    CartItemを対象のモデルとしてインスタンス変数(@cart_item)を定義するのはCartsControllerのcreateアクションないと言うことですか?
  4. @mochi93kou

    Questioner

    ご丁寧にありがとうございました。
    頑張ってみます。
  5. @mochi93kou

    Questioner

    度々すみません。
    @cart_itemにproductの情報を設定する方法だけ教えてください。

Your answer might help someone💌