59912


現在RailsでECサイトを作成中です。  
カート機能を実装したいのですが、「カートに追加」のボタンをクリックすると、以下のエラーが発生します。  
LineItemが判別できないというエラーと認識しております。  
application.controller.rbに  
include CurrentCart  
before_action :set_cart  
の記述を追加しましたが、変化はありませんでした。

また、「カートに追加」のパスにはidも渡しております。  
binding.pryで検証したところ、  
@line_itemの値はnilとなっておりました。  
解決方法の見当がつかず、情けないですが何卒お力添えの程宜しくお願い致します。

## Error message

[code]

    ActiveRecord::RecordNotFound at /line_items/2
    Couldn't find LineItem with 'id'=2
    
[/code]

# line_items.controller

[code]

    class LineItemsController < ApplicationController
     include CurrentCart
     before_action :set_line_item, only: [:show, :edit, :update, :destroy]
     before_action :set_cart, only: [:create]
    
     
     def index
       @line_items = LineItem.all
     end
    
     def show
     end
    
     def new
       @line_item = LineItem.new
     end
    
     def edit
     end
    
      def create
       item = Item.find(params[:item_id])
       @line_item = @cart.add_item(item)
    
       respond_to do |format|
         if @line_item.save
           format.html { redirect_to @line_item.cart, notice: 'カゴに追加されました' }
           format.json { render :show, status: :created, location: @line_item }
         else
           format.html { render :new }
           format.json { render json: @line_item.errors, status: :unprocessable_entity }
         end
       end
     end
    
     def update
       respond_to do |format|
         if @line_item.update(line_item_params)
           format.html { redirect_to @line_item, notice: 'Line item was successfully updated.' }
           format.json { render :show, status: :ok, location: @line_item }
         else
           format.html { render :edit }
           format.json { render json: @line_item.errors, status: :unprocessable_entity }
         end
       end
     end
    
     
     def destroy
       @cart = Cart.find(session[:cart_id])
       @line_item.destroy
       respond_to do |format|
         format.html { redirect_to cart_path(@cart), notice: 'Line item was successfully destroyed.' }
         format.json { head :no_content }
       end
     end
    
     private
       def set_line_item     #it says I have a problem here
         @line_item = LineItem.find(params[:id])
       end
    
       def line_item_params
         params.require(:line_item).permit(:item_id)
       end
    end
    
    
[/code]

# current_cart.rb

[code]

    module CurrentCart
      private
      def set_cart
        @cart = Cart.find(session[:cart_id])
      rescue ActiveRecord::RecoedNotFound
        @cart = Cart.create
        session[:cart_id] = @cart.id
      end
    end
    
    
[/code]

# application.controller

[code]

    class ApplicationController < ActionController::Base
      protect_from_forgery with: :exception
      include CurrentCart
      before_action :set_cart
     
    end
    
    
[/code]

# routes

[code]

    Rails.application.routes.draw do
      resources :line_items
      resources :carts
      resources :items
      devise_for :users, controllers:{
      registrations: 'registrations'
      }
      root 'items#index'
      devise_scope :user do
        get '/users/sign_out' => 'devise/sessions#destroy'
      end
    end
    
    
[/code]

# show.html.rb(長いため省略しています）

[code]

    <div class="column is-3 is-offset-1">
          <div class="bg-white pa4 border-radius-3">
            <h4 class="title is-5 has-text-centered"><%= number_to_currency(@item.price) %></h4>
            <p class="has-text-centered mb4">出品者： <%= @item.user.name %></p>
            <%= button_to '買い物カゴに追加する',line_item_path(item_id:@item), class: 'button is-warning add-to-cart' %>
          </div>
        </div>
    
    
[/code]

# line_item.rb

[code]

    class LineItem < ApplicationRecord
      belongs_to :item
      belongs_to :cart
    end
    
    
[/code]

# item.rb

[code]

    class Item < ApplicationRecord
      before_destroy :not_refereced_by_any_line_item
      belongs_to :user, optional: true
      has_many :line_items
      mount_uploader :image, ImageUploader
    
    validates :title, :brand, :price, :model, presence: true
    validates :description, length: {maximum:1000, too_long: "%{count} 文字以内でお願いします。"}
    validates :title, length: {maximum:100, too_long: "%{count} 文字以内でお願いします。"}
    
      BRAND = %w{ a b c d e }
      FINISH = %w{ 1週間以内 1ヶ月以内 1年以内 それ以前  }
      CONDITION = %w{ 新品 やや傷あり 傷あり かなり傷あり }
    
      private
      def not_refereced_by_any_line_item
        unless line_item.empty?
          errors.add(:base, "line items present")
          throw :abort
        end
      end
    end
    
    
[/code]

# cart.rb

[code]

    class Cart < ApplicationRecord
      has_many :line_items, dependent: :destroy 
    
      def add_item(item)
        current_item = line_items.find_by(item_id: item.id)
          if current_item
            current_item.increment(:quantity)
          else
            current_item = line_items.build(item_id: item.id)
          end
        current_item
      end
    end
    
    
[/code]

# Server Log

[code]

    Started POST "/line_items/2?item_id=2" for ::1 at 2019-10-23 18:04:28 +0900
       (0.4ms)  SET NAMES utf8,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
       (0.3ms)  SELECT `schema_migrations`.`version` FROM `schema_migrations` ORDER BY `schema_migrations`.`version` ASC
      
    ActionController::RoutingError (No route matches [POST] "/line_items/2"):
      
    actionpack (6.0.0) lib/action_dispatch/middleware/debug_exceptions.rb:36:in `call'
    web-console (4.0.1) lib/web_console/middleware.rb:132:in `call_app'
    web-console (4.0.1) lib/web_console/middleware.rb:28:in `block in call'
    web-console (4.0.1) lib/web_console/middleware.rb:17:in `catch'
    web-console (4.0.1) lib/web_console/middleware.rb:17:in `call'
    actionpack (6.0.0) lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
    railties (6.0.0) lib/rails/rack/logger.rb:38:in `call_app'
    railties (6.0.0) lib/rails/rack/logger.rb:26:in `block in call'
    activesupport (6.0.0) lib/active_support/tagged_logging.rb:80:in `block in tagged'
    activesupport (6.0.0) lib/active_support/tagged_logging.rb:28:in `tagged'
    activesupport (6.0.0) lib/active_support/tagged_logging.rb:80:in `tagged'
    railties (6.0.0) lib/rails/rack/logger.rb:26:in `call'
    sprockets-rails (3.2.1) lib/sprockets/rails/quiet_assets.rb:13:in `call'
    actionpack (6.0.0) lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
    actionpack (6.0.0) lib/action_dispatch/middleware/request_id.rb:27:in `call'
    rack (2.0.7) lib/rack/method_override.rb:22:in `call'
    rack (2.0.7) lib/rack/runtime.rb:22:in `call'
    activesupport (6.0.0) lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
    actionpack (6.0.0) lib/action_dispatch/middleware/executor.rb:14:in `call'
    actionpack (6.0.0) lib/action_dispatch/middleware/static.rb:126:in `call'
    rack (2.0.7) lib/rack/sendfile.rb:111:in `call'
    actionpack (6.0.0) lib/action_dispatch/middleware/host_authorization.rb:83:in `call'
    webpacker (4.0.7) lib/webpacker/dev_server_proxy.rb:29:in `perform_request'
    rack-proxy (0.6.5) lib/rack/proxy.rb:57:in `call'
    railties (6.0.0) lib/rails/engine.rb:526:in `call'
    puma (3.12.1) lib/puma/configuration.rb:227:in `call'
    puma (3.12.1) lib/puma/server.rb:660:in `handle_request'
    puma (3.12.1) lib/puma/server.rb:474:in `process_client'
    puma (3.12.1) lib/puma/server.rb:334:in `block in run'
    puma (3.12.1) lib/puma/thread_pool.rb:135:in `block in spawn_thread'
    Started GET "/line_items/2?item_id=2" for ::1 at 2019-10-23 18:04:52 +0900
    Processing by LineItemsController#show as HTML
      Parameters: {"item_id"=>"2", "id"=>"2"}
      LineItem Load (0.4ms)  SELECT `line_items`.* FROM `line_items` WHERE `line_items`.`id` = 2 LIMIT 1
      ↳ app/controllers/line_items_controller.rb:61:in `set_line_item'
    Completed 404 Not Found in 87ms (ActiveRecord: 3.5ms | Allocations: 20765)
    
    
    
    ActiveRecord::RecordNotFound - Couldn't find LineItem with 'id'=2:
      app/controllers/line_items_controller.rb:61:in `set_line_item'
    
    Started POST "/__better_errors/691901ca03d27e6b/variables" for ::1 at 2019-10-23 18:04:53 +0900
    S
    
    
[/code]


CC BY-SA 4.0
2019-10-23T07:04:24.527
59906
2019-10-30T03:44:49.630
2020-06-17T08:14:45.997
-1
36313
question
ruby-on-rails ruby
Couldn't find with 'id'の解決方法（ショッピングカート機能の実装）


`No route matches [POST] "/line_items/2"` と書いてありますね。

そのようなルートはないとのことなので、

`http://localhost:3000/rails/info/routes` を確認してみて欲しいのですが、  
`POST /line_items/:id(.:format)` というルートが多分存在しないと思います。  
GET ではなく POST であることに注意してください。

要するに `routes.rb` の `resources :line_items` だけでは今回のような ID を指定したPOST は出来ません。

そもそも Rails は `LineItemsController#create` に対しては `LineItem` を新規に作ることを想定しています。  
なので、`LineItem` は存在しないはずなのに、IDを指定したURLになるのは設計上何かがおかしいです。

<https://railsguides.jp/routing.html#%E3%83%8D%E3%82%B9%E3%83%88%E3%81%97%E3%81%9F%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9>  
を参照して欲しいのですが、ネストしたモデルの作成ちょっと特殊で

例えばカートにアイテムを追加する場合  
`POST /carts/:cart_id/line_item` のようなルートで、 `LineItem#create` を呼んであげるのが一般的です。

ただ、今回の場合は`Cart#add_item` を呼び出す形にしたいと思うので、

`POST /carts/:cart_id/add_item` というルートで、  
URLとしては `/carts/2/add_item?item_id=2` のような形になり、

コントローラーはに `CartsController#add_item` メソッドを追加し、その中で `Cart#add_item`
メソッドを実行してあげる形になるのかな。と思います。

ネストしたモデルの作成について全てここには書ききれないので、入れ子、ネストなどのワードを組み合わせて調べてみてください。


CC BY-SA 4.0
2019-10-23T10:44:11.243
59912
2019-10-23T10:58:30.723
2019-10-23T10:58:30.723
973
973
59906
answer


@sinzanmono46 さん、こんにちは。

show.html.rb がItemかLineItemか判断できなかったのですが、一般的に「商品ページ」である items#show だとして回答します。

まず、button_toで指定しているpathがroutesに存在しないのは、 @HAZI さんの指摘どおりだとおもいます。

[code]

    <%= button_to '買い物カゴに追加する',line_item_path(item_id:@item), class: 'button is-warning add-to-cart' %>
    
[/code]

ここで`LineItems#create`を呼び出したいのであれば、Rails的には、以下のような感じにすると自然なのかなとおもいました。

**app\controllers\items_controller.rb**

[code]

    def show
      @cart ||= Cart.find_or_create_by!(id:session[:cart_id])
      session[:cart_id] = @cart.id
      @item = Item.find(params[:id])
      @line_item = LineItem.new
    end
    
[/code]

**app\views\items\show.html.erb**

[code]

    <%= form_with url: line_items_path, model: @line_item, local: true do |form| %>
      <%= form.hidden_field :item_id, value: @item.id %>
      <%= form.hidden_field :cart_id, value: @cart.id %>
      <%= form.submit '買い物カゴに追加する' %>
    <% end %>
    
[/code]


CC BY-SA 4.0
2019-10-30T03:44:49.630
60107
2019-10-30T03:44:49.630
32317
59906
answer