Reputation: 41
As a novice to RoR I am making a site that allows clients to fill out a large form online. The form includes some nested models, but my issue is with the client not being saved to the database on the form submit.
From looking at my server it seems that params is picking up on the client information, but when sql action starts it doesn't insert any of the information into the database. Although it says it commits the transaction, my client in rails console have all nil attributes.
Started POST "/clients" for 192.168.1.114 at 2014-08-16 23:40:14 -0700
Processing by ClientsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"2tPnVc7Aj5mMdd9ZnXVuFHHs3CprND6QZ8qyCxSC674=", "client"=>{"name"=>"Jon", "birthdate"=>"August 2 1990", "has_guardian"=>"0", "guardian"=>{"name"=>"", "phone_number"=>"", "relationship"=>"", "address"=>"", "birthdate"=>""}, "gender"=>"male", "relationship"=>"single", "address"=>"25 Oak Road, LA, CA, 90003", "home_phone"=>"3105636778", "home_phone_manner"=>"leave_message_with_info", "preferred_home_phone"=>"false", "confidential_home_phone"=>"false", "cell_work_phone"=>"3104556721", "cell_work_phone_manner"=>"leave_message_with_info", "preferred_cell_work_phone"=>"true", "confidential_cell_work_phone"=>"true", "email"=>"[email protected]", "confidential_email"=>"true", "written_communication"=>"use_email", "family_contact"=>{"name"=>"Lily Mod", "phone_number"=>"3109776663"}, "additional_info"=>"Test", "created_at(1i)"=>"2014", "created_at(2i)"=>"8", "created_at(3i)"=>"17", "employer"=>"Polly", "occupation"=>"Sales", "prescriptions"=>"None", "medicines"=>"None", "allergies"=>"None", "conditions"=>"None"}, "commit"=>"Create Client"}
Unpermitted parameters: has_guardian, guardian, family_contact, created_at(1i), created_at(2i), created_at(3i)
(0.1ms) begin transaction
SQL (0.4ms) INSERT INTO "clients" ("additional_info", "created_at", "updated_at") VALUES (?, ?, ?) [["additional_info", "Test"], ["created_at", Sun, 17 Aug 2014 06:40:14 UTC +00:00], ["updated_at", Sun, 17 Aug 2014 06:40:14 UTC +00:00]]
(0.6ms) commit transaction
Redirected to http://192.168.1.114:3000/
Completed 302 Found in 59ms (ActiveRecord: 1.5ms)
When I pry inside my clients#create it shows at @client with all nil attributes, but when I call a method like name on @client it returns the value that is in the params.
26: def create
27: @client = Client.new(client_params)
=> 28: binding.pry
29: respond_to do |format|
30: if @client.save
31: format.html { redirect_to root_path, notice: 'Client was successfully created.' }
32: format.json { render controller: :static_pages, action: 'home', status: :created, location: root_path }
33: else
34: format.html { render action: 'new' }
35: format.json { render json: @client.errors, status: :unprocessable_entity }
36: end
37: end
38: end
[1] pry(#<ClientsController>)> @client
=> #<Client id: nil, name: nil, email: nil, home_phone: nil, home_phone_manner: nil, cell_work_phone: nil, cell_work_phone_manner: nil, written_communication: nil, confidential_email: nil, additional_info: "test", birthdate: nil, gender: nil, relationship: nil, employer: nil, occupation: nil, medicines: nil, allergies: nil, conditions: nil, created_at: nil, updated_at: nil, preferred_home_phone: nil, confidential_home_phone: nil, preferred_cell_work_phone: nil, confidential_cell_work_phone: nil, prescriptions: nil, address: nil>
[2] pry(#<ClientsController>)> @client.name
=> "Jon"
My relevant Clients Controller:
def new
@client = Client.new
end
def create
@client = Client.new(client_params)
respond_to do |format|
if @client.save
format.html { redirect_to root_path, notice: 'Client was successfully created.' }
format.json { render controller: :static_pages, action: 'home', status: :created, location: root_path }
else
format.html { render action: 'new' }
format.json { render json: @client.errors, status: :unprocessable_entity }
end
end
end
def client_params
params.require(:client).permit(:name, :email, :address, :home_phone, :home_phone_manner,
:cell_work_phone, :cell_work_phone_manner,
:written_communication, :confidential_email,
:additional_info, :birthdate, :gender, :relationship,
:prescriptions, :employer, :occupation, :medicines,
:allergies, :conditions, :preferred_home_phone,
:confidential_home_phone, :preferred_cell_work_phone,
:confidential_cell_work_phone)
end
My routes file:
match '/contact', to: 'static_pages#contact', via: :get
match '/about', to: 'static_pages#about', via: :get
match '/contact', to: 'static_pages#about', via: :get
match '/forms', to: 'clients#new', via: [:get, :post]
resources :clients
resources :family_contacts
resources :guardians
My Client model, I realize I haven't completed everything to get the associations working but I am concerned with just saving a client for now:
class Client < ActiveRecord::Base
has_one :guardian
has_many :family_contacts
accepts_nested_attributes_for :family_contacts
accepts_nested_attributes_for :guardian
attr_accessor :name, :email, :birthdate, :gender, :address
attr_accessor :home_phone, :home_phone_manner, :confidential_home_phone, :preferred_home_phone
attr_accessor :cell_work_phone, :cell_work_phone_manner, :confidential_cell_work_phone, :preferred_cell_work_phone
attr_accessor :written_communication, :confidential_email
attr_accessor :relationship, :employer, :occupation
attr_accessor :prescriptions, :medicines, :allergies, :conditions
def has_guardian?
self.guardian.present?
end
end
My form is very long, but Iv'e tried to simplify it by taking out a lot of the styling and labels:
<%= simple_form_for(@client, defaults: { required: false }, html: { class: 'form-inline' }) do |f| %>
<%= f.input :name, label: "Patient's Name:", placeholder: "First & Last" %>
<%= f.input :birthdate, label: "Birthdate:", placeholder: "January 1 2000" %>
<%= f.input :has_guardian?, label: "Are you under the age of 18?", as: :boolean %>
<%= f.simple_fields_for Guardian.new do |g| %>
<%= g.input :name, label: "Name of Gaurdian", placeholder: "First & Last" %>
<%= g.input :phone_number, label: "Phone # of Guardian", as: :tel %>
<%= g.input :relationship, label: "Relationship to Patient" %>
<%= g.input :address, label: "Guardian's Address" %>
<% end %>
<%= f.collection_radio_buttons :gender, [['male', 'Male'], ['female', 'Female']], :first, :last %>
<%= f.collection_radio_buttons :relationship, [['single', 'Single'], ['married', 'Married'], ['widowed', 'Widowed'], ['seperated', 'Seperated'], ['domestic_relationship', 'Domestic Relationship']], :first, :last %>
<%= f.input :address, lable: "Home Address:", placeholder: '25 Oak Road, Los Angeles, CA, 90003' %>
<%= f.input :home_phone, label: "Home Phone #", as: :tel %>
<%= f.collection_radio_buttons :home_phone_manner, [['leave_message_with_info', 'Leave message with detailed information.'], ['leave_message_with_callback', 'Leave message with call-back number only.']], :first, :last %>
<%= f.collection_radio_buttons :preferred_home_phone, [[true, 'Yes'], [false, 'No']], :first, :last %>
<%= f.collection_radio_buttons :confidential_home_phone, [[true, 'Yes'], [false, 'No']], :first, :last %>
<%= f.input :cell_work_phone, label: "Cell/Work Phone #", as: :tel %>
<%= f.collection_radio_buttons :cell_work_phone_manner, [['leave_message_with_info', 'Leave message with detailed information.'], ['leave_message_with_callback', 'Leave message with call-back number only.']], :first, :last %>
<%= f.collection_radio_buttons :preferred_cell_work_phone, [[true, 'Yes'], [false, 'No']], :first, :last %>
<%= f.collection_radio_buttons :confidential_cell_work_phone, [[true, 'Yes'], [false, 'No']], :first, :last %>
<%= f.input :email, label: "Email:", as: :email %>
<%= f.collection_radio_buttons :confidential_email, [[true, 'Yes'], [false, 'No']], :first, :last %>
<%= f.collection_radio_buttons :written_communication, [['mail_home', 'Mail to my home address (above).'], ['mail_work', 'Mail to my work address.'], ['fax_to_home', 'Fax to me home phone (above).'], ['use_email', 'Email me to the above email address.']], :first, :last %>
<%= f.simple_fields_for FamilyContact.new do |c| %>
<%= c.input :name, label: "Name:", placeholder: "First & Last" %>
<%= c.input :phone_number, label: "Phone #", as: :tel %>
<%= c.input :name, label: "Name:", placeholder: "First & Last" %>
<%= c.input :phone_number, label: "Phone #", as: :tel %>
<% end %>
<%= f.input :additional_info, label: "Additional Information:", as: :text %>
<%= f.input :created_at, label: "Date", as: :date %>
<%= f.input :employer, label: "Employer:" %>
<%= f.input :occupation, label: "Occupation:" %>
<%= f.input :prescriptions, label: "Current Prescription Medications:" %>
<%= f.input :medicines, label: "Over the Counter Medications:" %>
<%= f.input :allergies, label: "Allergies to Medications" %>
<%= f.input :conditions, label: "Other Medical Conidtions" %>
<%= f.input :created_at, label: "Date", as: :date %>
<%= f.simple_fields_for Guardian.new do |g| %>
<%= g.input :name, label: "Name of Gaurdian", placeholder: "First & Last" %>
<%= g.input :birthdate, label: "Birthdate of Guardian", placeholder: "January 1 2000" %>
<% end %>
<%= f.input :name, label: "Patient's Name:", placeholder: "First & Last" %>
<%= f.input :birthdate, label: "Birthdate:", placeholder: "January 1 2000" %>
<%= f.submit %>
Sorry for the length of the files, but I really appreciate any help. Thanks
Upvotes: 1
Views: 1637
Reputation: 76774
Here's the error:
Unpermitted parameters: has_guardian, guardian, family_contact, created_at(1i), created_at(2i), created_at(3i)
Although the error above is for strong_params
, I think it's a deeper issue which we need to resolve. As you're new, let me detail how this works for you...
Attributes
The model you have are heavily populated with attr_accessor
. attr_accessor
is a way to create "virtual attributes" in Ruby / Rails, as it defines a custom getter
and setter
method, which will essentially define the "attributes" for use on the system
The problem you have is attr_accessor
, in the simplest of terms, will not permit your data to be saved in the database. This will be one of the bigger issues you have - you need to get rid of any attr_accessors
which override your database attributes
This is demonstrated here:
INSERT INTO "clients" ("additional_info", "created_at", "updated_at") VALUES (?, ?, ?) [["additional_info", "Test"], ["created_at", Sun, 17 Aug 2014 06:40:14 UTC +00:00], ["updated_at", Sun, 17 Aug 2014 06:40:14 UTC +00:00]]
This basically shows that only additional_info
, created_at
and updated_at
are populating the database.
You should remove the attr_accessor
methods from your Client
model:
#app/models/client.rb
class Client < ActiveRecord::Base
has_one :guardian
has_many :family_contacts
accepts_nested_attributes_for :family_contacts
accepts_nested_attributes_for :guardian
end
Unpermitted
The unpermitted parameters issue is caused mainly by your non-permission of these in your strong params hash. You'll need to add them here:
#app/controllers/clients_controller.rb
Class ClientsController < ApplicationController
private
def client_params
params.require(:client).permit(..., :has_guardian, :guardian, :family_contact, :created_at(1i), :created_at(2i), :created_at(3i))
end
end
Although this is definitely the case, I feel there is a massive problem with the number of attributes you're trying to pass through. It's not against convention or anything, but validating all of those attributes each submit is surely going to cause a problem?
I'd say its unworkable - you'd be better splitting it up into manageable associated models / objects, though I'll leave that up to you to work out
Upvotes: 1