简体   繁体   中英

Rails - Save client model into the database

Hey here. I'm kinda new to Rails and I've been trying to find some answers but no luck yet so here we go.

I've set up a basic Rails app and just trying to save a Client to my database with a validation but nothing seems to be coming together. Anyone could point me to the right direction please or let me know what I've been doing wrong in my code.

I keep getting errors like this:

NoMethodError in Clients#new
Showing /Users/******/Documents/******/*****/app/views/clients/_form.html.erb where line #1 raised:

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

Even if I remove @client = Client.new from the new method I can view the page but nothing gets saved.

I'm stuck really now so any help much appreciated! Thanks!

My Routes.rb file:

Rails.application.routes.draw do
  mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
  get 'dashboard/index'
  root to: "home#index"

  devise_for :users, controllers: {
    sessions: 'users/sessions',
    passwords: 'users/passwords',
    registrations: 'users/registrations'
  }

  get '/clients/index'
  get '/clients/new'
  get '/clients/edit'
  get '/clients/delete'

  get '/clients/:id', to: 'clients#show'

  post '/clients/new', to: 'clients#create'
end

My Dashboard file:

<% if user_signed_in? %>
    <nav class="subnav">
        <ul>
            <li><%= link_to('My Clients', clients_index_path) %></li>
            <li><%= link_to('Add Client', clients_new_path) %></li>
            <li><%= link_to('Edit registration', edit_user_registration_path) %></li>
            <li><%= link_to('Logout', destroy_user_session_path, :method => :delete) %></li>
        </ul>
    </nav>
<% else %>

  <%= link_to('Register', new_user_registration_path)  %>
  <%= link_to('Login', new_user_session_path)  %>

<% end %>

My ClientsController file:

class ClientsController < ApplicationController
  def index
    @clients = Client.all
  end

  def new
    @client = Client.new
  end

  def show
    @client = Client.find(params[:id])
  end

  def create
    @client = Client.new(client_params)

    if @client.save
      redirect_to @client
    else
      render :new
    end
  end

  def edit
  end

  def delete
  end

  private
    def client_params
      params.require(:client).permit(:name, :provider)
    end
end

My form :

<%= form_with model: @client do |form| %>
  <div>
    <%= form.label :name %><br>
    <%= form.text_field :name %>
    <% client.errors.full_messages_for(:name).each do |message| %>
      <div><%= message %></div>
    <% end %>
  </div>

  <div>
    <%= form.label :provider %><br>
    <%= form.text_field :provider %>
  </div>

  <div>
    <%= form.label :business_type %><br>
    <%= form.select :business_type, ["Partnership", "Sole Trader", "Limited Company"] %>
  </div>

  <div>
    <%= form.submit %>
  </div>
<% end %>

Finally my new.html.erb file:

<h1>Clients#new</h1>

<%= render 'form', client: @client %>

clients_path is generated by resources:clients, only: :index or you probably need to give your route the name you want. Try this

get '/clients/index', as: :clients

or, if you want to specify non default paths as you're doing, your index is probably called clients_index_path , but you can check that with a rake routes or rails routes , because I'm not sure.

That said, I suggest you to go with the resources method in your routes file and use the default paths as you're trying to do. Something like

resources :clients

but now you don't have a path like /clients/index no more, just /clients for the index action.

If you're in doubts with routes try to read the guide about routing

The Rails way to declare the routes to Create, Update, Read and Destroy (CRUD) a resource is just:

Rails.application.routes.draw do
  mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
  get 'dashboard/index'
  root to: "home#index"

  devise_for :users, controllers: {
    sessions: 'users/sessions',
    passwords: 'users/passwords',
    registrations: 'users/registrations'
  }

  resources :clients
end

As you can see by the annotions above each method Rails does not add the "action" to the path except for the new and edit routes:

class ClientsController < ApplicationController
  before_action :set_client, only: [:show, :edit, :update, :destroy]

  # GET /clients
  def index
    @clients = Client.all
  end

  # GET /clients/1
  def show
  end
  
  # GET /clients/new
  def new
    @client = Client.new
  end

  # POST /clients
  def create
    @client = Client.new(client_params)

    if @client.save
      redirect_to @client
    else
      render :new
    end
  end

  # GET /clients/edit
  def edit
  end

  # PATCH /clients/1
  def update
    if @client.update(client_params)
      redirect_to @client
    else
      render :edit
    end
  end

  # DELETE /clients/1
  def delete
    @client.destroy
    redirect_to action: :index, 
                notice: 'Client deleted'
  end

  private
    def set_client
      @client = Client.find(params[:id])
    end

    def client_params
      params.require(:client).permit(:name, :provider)
    end
end

Thus you don't create resources with post '/clients/new' - You use POST /clients . Also when you use the "bare-bones" routing methods such as match , get , post etc Rails does not automatically add routing helper. If you actually wanted to generate the equivilent routes you would need to use:

post '/clients', 
  to: 'clients#create',
  as: :clients

But you're much better off embracing the conventions and learning to use them to be productive.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM