Search code examples
ruby-on-railsdevisesimple-form

Trying to POST to database with Simple Form and Rails


Trying to use the simple-form gem with Rails to POST to my database (postgresql). I have followed a few videos but I'm not entirely sure what's going wrong. My form worked before I made the method to post (obviously didn't do anything).

Here's the error I get.

enter image description here

Straight away I was thinking a routes issue. But I've had a crack for a while and can't fix it.

undefined method `client_assets_path' for #<ActionView::Base:0x0000000000ccd8>
Did you mean?  clients_new_path

Here's my repo if it helps with the models.

Here's my form:

<%= simple_form_for @clients do |f| %>
        <div class="form-inputs">
            <%# Home %>
            <%= f.input :ppor %>
            <br>
        </div>

        <div class="form-actions">
            <%= f.button :submit %>
        </div>
    <% end %

Here's my method in Client Controller:

class ClientController < ApplicationController
  def index
    @clients = ClientAsset.all
  end

  def new
    @clients = ClientAsset.new
  end

  def create
    @clients = ClientAsset.new(client_asset_params)
    if @clients.save
      redirect_to @clients
    else
      render :new
    end
  end

  private
  def client_asset_params
    params.require(:id).permit(:ppor)
  end
end

and here's my routes:

Rails.application.routes.draw do

  devise_for :admins
  root to: "planner#index"

  get "/index", to: "planner#index", as: :index

  get "/howto", to: "planner#howto", as: :howto

  get "/products", to: "planner#products", as: :products

  get "/planners", to: "planner#planners", as: :planners

  get "/admins/sign_in", to: "admin#sign_in", as: :sign_in

  get "/admins/sign_up", to: "admin#sign_up", as: :sign_up

  devise_scope :admin do
    get "/admins/sign_out" => "devise/sessions#destroy"
  end

  get "/admins/password/edit", to: "devise/password#edit", as: :edit

  get "/dashboard", to: "client#dashboard", as: :dashboard

  get "clients/new", to: "client#new"

end

Solution

  • Your instinct that you have a routing issue is correct.

    The standard/default behaviour on a form like yours is to POST to the specified resource's 'index path' (/clients in your case). However, you have not defined a POST route.

    The reason you get an undefined method error instead of a 'no route for' error is that simple_form_for assumes that your route has a 'named path helper' of the form 'class_name_path' that will give it the appropriate destination URI. Since you don't have a route defined, simple_form doesn't find the associated method and you get a missing method error.

    So, at a minimum you would need:

    get "/clients/new", to: "client#new"
    post "/clients", to: "client#create", as: 'client_assets'
    

    The as: option is necessary because by default Rails creates the helper using the resource path name (clients) but simple_form_for assumes the that resource path is derived from the model name (client_assets).

    As an aside, Rails works best and easiest when you stick to convention. If you are new to Rails, using things such as resourceful routing and naming conventions for models and controllers (e.g., ClientAsset (model) ClientAssetsController (controller)) can make your experience with Rails quite a bit smoother.