Multi-Step Form debugging Rails - ActionController::ParameterMissing

127 Views Asked by At

I understand that this issue has been raised several times, but I can't find to find a way around..

I am using this solution to create a multi-step form without the Wicked gem: Best way to make Multi-Steps form in Rails 5

It seems that I am able to create a product when I use binding.pry and enter the needed commands inside my rails console.

However, the app in itself does not function and I can't manage to work around it..

Two issues throw the ActionController::ParameterMissing error:

1) First, anytime I intend to press the back_button it raises ParameterMissing error (see at the end for exact error message).

2) When I get to the last_step of the form, it displays all the needed information, but will neither create nor save new products (also ParameterMissing).

Here is my code:

Routes


  get 'products/new', to: 'products#new', as: 'new_product'
  post 'products', to: 'products#create', as: 'create_new_product'

  resources :categories, only: [:index, :show, :new, :edit, :destroy] do
    resources :sub_categories, only: [:index, :show, :new, :edit, :destroy]
    resources :products, only: [:index, :show, :destroy]
  end

Products Controller

class ProductsController < ApplicationController
  skip_after_action :verify_authorized, except: :index, unless: :skip_pundit?
  skip_after_action :verify_policy_scoped, only: :index, unless: :skip_pundit?
  before_action :set_category, only: [:index, :show]

  def new
    session[:product_params] ||= {}
    authorize @product = Product.new(session[:product_params])
    @product.current_step = session[:product_step]
    @product.user = current_user
  end

  def create

    session[:product_params].deep_merge!(params_product) if params_product
    authorize @product = Product.new(session[:product_params])
    @product.current_step = session[:product_step]

    @product.user = current_user

    if @product.valid?

      if params[:back_button]
        @product.previous_step

      elsif @product.last_step?
        if @product.all_valid?
          @product.save!
          flash[:notice] = 'Your product was created successfully'
          redirect_to newest_products_path && return
        end

      else
        @product.next_step
      end

    end
    session[:product_step] = @product.current_step

    if @product.new_record?
      return render :new

    else
      session[:product_step] = session[:product_params] = nil
    end
  end

  private

  def set_category
    authorize @category = Category.find(params[:category_id])
  end

  def params_product
    params.require(:product).permit(:name, :price, :description, :category, :category_id,
                                    :sub_category, :sub_category_id, :user, :user_id, :id)
  end
end

Product Model

class Product < ApplicationRecord
  attr_writer :current_step

  belongs_to :user, optional: true
  belongs_to :sub_category
  belongs_to :category, inverse_of: :products

  validates :category, presence: true

  validates_presence_of :name, :category_id, if: lambda { |e| e.current_step == "card" }
  validates_presence_of :sub_category_id, :description, :price, if: lambda { |e| e.current_step == "details" }

  def current_step
    @current_step || steps.first
  end

  def steps
    %w[card details confirmation]
  end

  def next_step
    self.current_step = steps[steps.index(current_step) + 1]
  end

  def previous_step
    self.current_step = steps[steps.index(current_step) - 1]
  end

  def first_step?
    current_step == steps.first
  end

  def last_step?
    current_step == steps.last
  end

  def all_valid?
    steps.all? do |step|
      self.current_step = step
      valid?
    end
  end
end

New Products View

      <%= form_for @product, url: create_new_product_path do |f| %>
        <%= render "#{@product.current_step}_step", :f => f  %>
        <div class="bottom-signup">
          <%= f.submit "Continue" unless @product.last_step? %>
          <%= f.submit "Submit Product" if @product.last_step? %>
          <%= f.submit "Back", :name => "back_button" unless @product.first_step? %>
        </div>
      <% end %>

Here is the exact error that is thrown by ActionController:

ActionController::ParameterMissing in ProductsController#create

param is missing or the value is empty: product

#around ligne (96)

95  def params_product
96    params.require(:product).permit(:name, :price, :description, :category, :category_id,
97                                    :sub_category, :sub_category_id, :user, :user_id, :id)
98  end

And finally, here is what appears if I raise params.inspect:

params.inspect

=> "<ActionController::Parameters {\"utf8\"=>\"✓\", \"authenticity_token\"=>\"AHfNwkeFOWBeEup+fCCvfZv1RowuP/YULHjo8kTnzer5YNCY7lMYAKzrrWJBVMcfOO+P1GmZGgi9PDpa/09rzw==\", \"commit\"=>\"Submit Product\", \"controller\"=>\"products\", \"action\"=>\"create\"} permitted: false>"

If someone understands where I'm wrong, I'd be more than glad to discuss it!

Thanks in advance.

Best, Ist

0

There are 0 best solutions below