Reputation: 6684
I have a Rails 4 app where I have two related controllers, potential_client
and location
. I am trying to enable to creation of potential clients through the location controller. I believe there is something wrong with my form because it gets submitted as a PATCH to the location, rather than creating a new potential_client as follows:
class Location < ActiveRecord::Base
validates_presence_of :name, :email, :address, :phone
has_many :potential_clients
accepts_nested_attributes_for :potential_clients
end
and
class PotentialClient < ActiveRecord::Base
validates_presence_of :name, :email, :phone
belongs_to :location
end
I have my routes configured such that:
resources :locations do
resources :potential_clients
end
and in my app/views/locations/show.html.erb I have the following form:
<div class="form-container">
<%= form_for @location do |f| %>
<%= f.fields_for :potential_client do |pc_form| %>
<%= pc_form.label :name %>
<%= pc_form.text_field :name %><br />
<%= pc_form.label :email %>
<%= pc_form.email_field :email %><br />
<%= pc_form.label :phone %>
<%= pc_form.number_field :phone %><br />
<%= pc_form.label :message %>
<%= pc_form.text_field :message %><br />
<%= pc_form.hidden_field :location_id, :value => @location.id %>
<%= pc_form.submit "Submit" %>
<% end %>
<% end %>
</div>
The form loads properly, but when I try to submit something, I get an error in my console that Unpermitted parameter: potential_client
, but in my location_controller
I have:
def location_params
params.require(:location).permit(:name, :email, :address, :phone, :potential_client, potential_client_attributes: [:name, :email, :message, :phone])
end
...and to top it off, when I am trying to CREATE a potential_client, my console says:
Started PATCH "/locations/1" for ::1 at 2016-02-03 13:18:27 -0500
ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations"
Processing by LocationsController#update as HTML
all routes if they are helpful:
location_potential_clients GET /locations/:location_id/potential_clients(.:format) potential_clients#index
POST /locations/:location_id/potential_clients(.:format) potential_clients#create
new_location_potential_client GET /locations/:location_id/potential_clients/new(.:format) potential_clients#new
edit_location_potential_client GET /locations/:location_id/potential_clients/:id/edit(.:format) potential_clients#edit
location_potential_client GET /locations/:location_id/potential_clients/:id(.:format) potential_clients#show
PATCH /locations/:location_id/potential_clients/:id(.:format) potential_clients#update
PUT /locations/:location_id/potential_clients/:id(.:format) potential_clients#update
DELETE /locations/:location_id/potential_clients/:id(.:format) potential_clients#destroy
locations GET /locations(.:format) locations#index
POST /locations(.:format) locations#create
new_location GET /locations/new(.:format) locations#new
edit_location GET /locations/:id/edit(.:format) locations#edit
location GET /locations/:id(.:format) locations#show
PATCH /locations/:id(.:format) locations#update
PUT /locations/:id(.:format) locations#update
DELETE /locations/:id(.:format) locations#destroy
perhaps its because :location_id
and :id
are the same for both routes and Rails is routing to location instead of potential_client
Upvotes: 0
Views: 1447
Reputation: 102036
When you do:
<%= form_for @location do |f| %>
The rails polymorphic route helpers look at @location
and uses @location.new_record?
to see if it should route to update
or create
.
So in your locations#show
action you are passing a persisted record - so it will route to update
.
If you want to have a separate form which posts only a potential client you would do it like this:
<%= form_for [@location, @potential_client] do |f| %>
Which would create a POST locations/1/potential_clients
request if its a new record and PATCH locations/1/potential_clients/1
if it has been persisted.
Its a simple pluralization error. Your model accepts_nested_attributes_for :potential_clients
while your form has <%= f.fields_for :potential_client do |pc_form| %>
.
When you use fields_for
is should use the same name as the relation - so in the case of has_many
it should be the plural form.
<div class="form-container">
<%= form_for @location do |f| %>
<%= f.fields_for :potential_clients do |pc_form| %>
# ...
<% end %>
<% end %>
</div>
Note that the proper param key is potential_clients_attributes
so that what you should be whitelisting.
def location_params
params.require(:location)
.permit(
:name, :email, :address, :phone,
potential_clients_attributes: [:name, :email, :message, :phone]
)
end
Upvotes: 3