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.