user5914341
user5914341

Reputation:

Ruby on Rails: wrong number of arguments (given 0, expected 1)

I have an issue with my add_item method and have trouble to understand why.

Here is my carts_controller.rb

class CartsController < ApplicationController
  def index
    @cart_items = CartItem.all
  end

  def add_item
    @cart_item = CartItem.new
    produit_id = params[:produit_id]
    @cart_item = CartItem.find_or_create_by(params[:produit][:produit_id])
    @cart_item.save

    binding.pry
  end
end

Here is produits/index.html.erb (where the issue comes from)

<div id="produits-column-container">
  <% if @produits %>
    <% @produits.in_groups_of(4, false).each do |g| %>
      <% g.each do |produit| %>
      <div id="produits-row-container">
        <div id="fiche-produit-container">
            <div id="produit-img">
              <%= image_tag produit.photo %>
            </div>
            <div id="produit-nom">
              <%= produit.nom %>
            </div>
            <div id="produit-prix">
              <%= number_to_currency(produit.prix, unit: '€', format: "%n%u") %>
            </div>
            <div id="produit-au-panier">
              <%= image_tag('icon/icon-panier') %>
              <%= link_to 'Ajouter au panier', carts_add_item_path, method: :post %>
            </div>
         </div>
       </div>
      <% end %>
    <% end %>
  <% end %>
</div>

The error i'm given is :

ArgumentError in CartsController#add_item
wrong number of arguments (given 0, expected 1)

in def add_item(produit_id)

add_item(produit_id) is related to carts_add_item_path

I also give you the routes :

Rails.application.routes.draw do

  match "/mon-panier" => 'carts#index', via: :get

  post 'carts/add_item' => 'carts#add_item'

  resources :categories do
    resources :produits
  end

  resources :order_abonnements, only: [:create, :update, :delete]

  get 'livraisons_type/index'

  match "/recapitulatif" => 'recapitulatif#index', via: :get

  match "/confirmation-carte-cadeau" => 'recapitulatif#confirmation', via: :get

  match "/livraison-carte-cadeau" => 'livraison_carte#index', via: :get

  match '/activation-carte' => 'code_carte_cadeau#index', via: :get

  match "/offrir-une-box-bretonne" => 'cadeau#index', via: :get

  resources :order_items, only: [:create, :update, :destroy]

  match "/nos-box" => 'nos_box#index', via: :get

  get 'categories/index'

  devise_for :admin_users, ActiveAdmin::Devise.config
  ActiveAdmin.routes(self)

  match '/informations-penn-ar-box' => 'informations_penn_ar_box#index', via: :get

  match '/livraison-box-bretonne' => 'livraison_box_bretonne#index', via: :get

  match '/abonnements' => 'abonnements#index', via: :get

  devise_for :users, path: '', path_names: { sign_in: 'connexion', sign_out: 'déconnexion'}

  resources :users do
    delete 'déconnexion' => 'devise/sessions#destroy'
  end

  match '/mon-marche-breton' => 'marche_breton#index', via: :get

  root 'home#home'
end

And the logs :

Started POST "/carts/add_item" for ::1 at 2017-05-30 09:48:52 +0200
Processing by CartsController#add_item as HTML
  Parameters: {"authenticity_token"=>"QrToQUHVxjuV5cUvZYHd7tj457htfZohOkmsvNDnKv79P413xjsSfR/8RVXtdIU7/wcmhcxjkU85N13CqJkG2w=="}
  Cart Load (0.3ms)  SELECT  `carts`.* FROM `carts` WHERE `carts`.`id` = 1 LIMIT 1
Completed 500 Internal Server Error in 27ms (ActiveRecord: 14.9ms)

ArgumentError (wrong number of arguments (given 0, expected 1)):
  app/controllers/carts_controller.rb:6:in `add_item'

Upvotes: 2

Views: 15566

Answers (2)

Alexander Popov
Alexander Popov

Reputation: 24875

There are a lot of things that are wrong with this code, but the simplest thing you could do in order to suppress the error is to change the method signature to:

def add_item

instead of

def add_item(produit_id)

P.S. The controller is not RESTful. It's called CartsController, but in your index action you list the CartItems, not the Carts. The correct name should be CartItemsController. If you rename the controller to CartItemsController, than the index action can stay the same, but the add_item action should better be renamed to simply create. Thus, in your routes you can have:

resources :cart_items, only: [:index, :create]

Also, I am not exactly sure, what is going on in the add_item method - at first you assign a new CartItem to @cart_item, but then you override this assignment with find_or_create_by.... Also, the call to save at the end of the method is redundant, as create will save the record and otherwise no modifications have been made between the find_or_create_by line and the save line.

Upvotes: 0

SteveTurczyn
SteveTurczyn

Reputation: 36860

You need to pass produit_id as a parameter.

So change this line as so...

<%= link_to 'Ajouter au panier', 
            carts_add_item_path(produit_id: produit.id), method: :post %>

And change your controller method as so...

def add_item
  produit_id = params[:produit_id]
  ...

And change the find_or_create to

@cart_item = CartItem.find_or_create_by(produit_id: produit_id)

This does mean that you can only have one CartItem in your entire application that points to a product... strange design.

Upvotes: 1

Related Questions