Reputation: 889
I have a little app that has a clients and a sites model. I want to create a new site in a modal from the show page but i get and error.
Please find below schema, controller, models and error.
schema
create_table "clients", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "clients_sites", id: false, force: :cascade do |t|
t.bigint "client_id", null: false
t.bigint "site_id", null: false
end
create_table "sites", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
I want to create a site from my client#show page
<div class="page-header">
<%= link_to clients_path, class: 'btn btn-default' do %>
<span class="glyphicon glyphicon-list-alt"></span>
All Clients
<% end %>
<%= link_to edit_client_path(@client), class: 'btn btn-primary' do %>
<span class="glyphicon glyphicon-pencil"></span>
Edit
<% end %>
<h1>Show client</h1>
</div>
<dl class="dl-horizontal">
<dt>Name:</dt>
<dd><%= @client.name %></dd>
</dl>
<div class="row">
<div class="col-sm-6">
<h1>Sites</h1>
</div>
<div class="col-sm-6 text-right">
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal">
Add New Site
</button>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<%= form_for [@client, @site] do |f| %>
<%= form.label :name %>
<%= form.text_field :name, class: 'form-control' %>
<%= form.submit class: 'btn btn-primary' %>
<% end %>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="table-responsive">
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th>Name</th>
</tr>
</thead>
<tbody>
<% @client.sites.each do |site| %>
<%= content_tag :tr, id: dom_id(site), class: dom_class(site) do %>
<td><%= link_to site.name, site %></td>
<% end %>
<% end %>
</tbody>
</table>
</div>
clients controller
def show
@client = Client.find(params[:id])
@site = Site.new
end
app/models/client.rb
class Client < ApplicationRecord
has_and_belongs_to_many :sites
end
app/models/site.rb
class Site < ApplicationRecord
has_and_belongs_to_many :clients
end
when i hit the page i get the following error
ActionView::Template::Error (undefined method `client_sites_path' for #<#<Class:0x00007f9329282490>:0x00007f9329279890>
Did you mean? clients_path
edit_site_path):
39: </button>
40: </div>
41: <div class="modal-body">
42: <%= form_for [@client, @site] do |f| %>
43: <%= form.label :name %>
44: <%= form.text_field :name, class: 'form-control' %>
45: <%= form.submit class: 'btn btn-primary' %>
app/views/clients/show.html.erb:42:in `_app_views_clients_show_html_erb___1421137287308647677_70135013712680'
edit
routes
sites GET /sites(.:format) sites#index
POST /sites(.:format) sites#create
new_site GET /sites/new(.:format) sites#new
edit_site GET /sites/:id/edit(.:format) sites#edit
site GET /sites/:id(.:format) sites#show
PATCH /sites/:id(.:format) sites#update
PUT /sites/:id(.:format) sites#update
DELETE /sites/:id(.:format) sites#destroy
clients GET /clients(.:format) clients#index
POST /clients(.:format) clients#create
new_client GET /clients/new(.:format) clients#new
edit_client GET /clients/:id/edit(.:format) clients#edit
client GET /clients/:id(.:format) clients#show
PATCH /clients/:id(.:format) clients#update
PUT /clients/:id(.:format) clients#update
DELETE /clients/:id(.:format) clients#destroy
Rails.application.routes.draw do
resources :sites
resources :clients
Upvotes: 1
Views: 3559
Reputation: 33542
ActionView::Template::Error (undefined method `client_sites_path' for Class:0x00007f9329282490>:0x00007f9329279890 Did you mean? clients_path edit_site_path):
The error says there is no such available path helper called client_sites_path
. Indeed its true as you don't have your routes defined such way. As per your comment on @arieljuod post, I understood that you want to save sites
to clients
. The below code will help you to achieve what you want
<%= form_for @site do |f| %>
<%= form.label :name %>
<%= form.text_field :name, class: 'form-control' %>
<%= form.select :client_ids, options_from_collection_for_select(Client.all, :id, :name), :prompt => "Select Clients", :multiple => true %>
<%= form.submit class: 'btn btn-primary' %>
<% end %>
This piece of code snippet
<%= form.select :client_ids, options_from_collection_for_select(Client.all, :id, :name), :prompt => "Select Clients", :multiple => true %>
creates a dropdown where you can select one or more clients to add to the sites which will get submitted along with the params
that goes to the sites#create
action.
Also you should make sure to whitelist client_ids: []
by adding it to the site_params
method. By doing this, Rails under the hood uses this client_ids
values to generate entries for clients_sites
table. Thus completing the creation of sites
to the clients
.
Upvotes: 2
Reputation: 15838
When you pass an array of models as parameter of the form_for helper, rails tries to find a route for that relationship (client_sites_path).
You need to define that route. Check the rails routing guide, the nested resources section and the paths using url_for helpers https://guides.rubyonrails.org/routing.html#creating-paths-and-urls-from-objects
Nest the sites resource inside clients resource:
resources :clients do
resources :sites
end
and check your new routes, now you should see a client_sites route on the output of rake routes
and [@client, @site]
should work.
Upvotes: 0