I've seen some similar questions to this but nothing relating to using the Cocoon gem with the Wicked multi step form Gem in with Rails. The form saves fine when I have a has_many association but when there is a has_one association (Client has_one doctor) the record seems to save and then delete. Spent so long trying to figure this out but just can't see why it's happening.
class QuotesController < ApplicationController
include Wicked::Wizard
before_action :set_client, only: [:show, :update, :quote_success]
steps :profile, :employment, :general_questions, :indemnity_details, :declarations
def show
@client.build_doctor
@client.old_insurers.build
@client.practice_addresses.build
render_wizard
end
def update
@client.update(client_params)
render_wizard @client
end
def quote_success; end
private
def set_client
current_user = Client.find_by_id(session[:current_user_id])
@client = current_user
end
def finish_wizard_path
if @client.valid?
ClientMailer.new_quote(@client).deliver
ClientMailer.new_quote_user_message(@client).deliver
end
quote_success_path
end
end
def client_params
params.require(:client).permit(:name, :email, :email_confirmation, :phone, :date_required,
:title, :first_name, :last_name, :date_of_birth, :nationality, :reg_body,
practice_addresses_attributes: [:id, :pa_line1, :pa_line2, :pa_line3, :pa_town, :pa_county, :pa_postcode, :other_practices, :_destroy],
old_insurers_attributes: [:id, :insurer, :oi_to, :oi_from, :oi_limit, :oi_excess, :oi_premium, :_destroy],
doctor_attributes: [:id, :gp_locum, :gp_locum_sessions, :gp_locum_locations])
end
end
Client Model:
class Client < ActiveRecord::Base
has_one :doctor, dependent: :destroy
has_many :practice_addresses, dependent: :destroy
has_many :callbks, inverse_of: :client
has_many :old_insurers, dependent: :destroy
accepts_nested_attributes_for :doctor
accepts_nested_attributes_for :old_insurers, reject_if: :all_blank, allow_destroy: true
accepts_nested_attributes_for :callbks
accepts_nested_attributes_for :practice_addresses, reject_if: :all_blank, allow_destroy: true
end
Doctor Model:
class Doctor < ActiveRecord::Base
belongs_to :client
end
View part in question:
<%= simple_form_for @client, url: wizard_path do |f| %>
<%= yield f %>
....
<div id="doctors">
<%= f.simple_fields_for :doctor do |gp| %>
<%= render 'doctor_fields', f: gp %>
<% end %>
</div>
Doctor_fields:
<div class="nested-fields">
<div class="panel panel-default">
<div class="panel-heading">
<strong>General Questions - GP</strong>
</div>
<div class="panel-body">
<div class="table-responsive">
<div class=bs-example data-example-id=striped-table>
<table class="table table-striped">
<thead>
<tr>
<th>Are you a:</th>
<th>Yes / No</th>
<th>Number of Sessions per week</th>
<th>Number of Locations</th>
</tr>
<tr>
<td>Locum</td>
<td><%= f.input :gp_locum, as: :radio_buttons, checked: false, label: false %></td>
<td><%= f.input :gp_locum_sessions, label: false, required: false %></td>
<td><%= f.input :gp_locum_locations, label: false, required: false %></td>
</tr>
</div>
</table>
</div>
</div>
Log:
Started GET "/quotes/employment" for ::1 at 2017-03-13 10:27:07 -0300
Processing by QuotesController#show as HTML
Parameters: {"id"=>"employment"}
Client Load (1.6ms) SELECT "clients".* FROM "clients" WHERE "clients"."id" = $1 LIMIT 1 [["id", 47]]
Doctor Load (1.1ms) SELECT "doctors".* FROM "doctors" WHERE "doctors"."client_id" = $1 LIMIT 1 [["client_id", 47]]
Rendered layouts/_quote_page_start.html.erb (2.0ms)
Rendered quotes/_doctor_fields.html.erb (234.4ms)
Rendered quotes/_form.html.erb (364.0ms)
Rendered layouts/_quote_page_mobile.html.erb (0.2ms)
Rendered quotes/employment.html.erb within layouts/application (423.2ms)
Rendered layouts/_shim.html.erb (0.1ms)
Profession Load (1.7ms) SELECT "professions".* FROM "professions" ORDER BY name ASC
Rendered layouts/_header.html.erb (8.6ms)
Rendered layouts/_footer.html.erb (11.4ms)
Completed 200 OK in 1920ms (Views: 1845.1ms | ActiveRecord: 13.7ms)
Started PATCH "/quotes/employment" for ::1 at 2017-03-13 10:27:21 -0300
Processing by QuotesController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"7xvqW6SpbBgKy62zfdPclexYD9cxqNR/F8p+twW87F/vSz/5kmpRMCE59 LcL4taIclWj4ZeVQ6CRasqqy38iNw==", "client"=>{"profession_area"=>"General Practicioner", "profession_area_other"=>"das", "doctor_attributes"=> {"gp_locum"=>"false", "gp_locum_sessions"=>"212", "gp_locum_locations"=>"21"}, "commit"=>"Next", "id"=>"employment"}
Client Load (2.0ms) SELECT "clients".* FROM "clients" WHERE "clients"."id" = $1 LIMIT 1 [["id", 47]]
(0.2ms) BEGIN
Doctor Load (0.5ms) SELECT "doctors".* FROM "doctors" WHERE "doctors"."client_id" = $1 LIMIT 1 [["client_id", 47]]
SQL (0.6ms) INSERT INTO "doctors" ("gp_locum", "gp_locum_sessions", "gp_locum_locations", "client_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31, $32, $33, $34, $35) RETURNING "id" [["gp_locum", "f"], ["gp_locum_sessions", 212], ["gp_locum_locations", 21], ["client_id", 47], ["created_at", "2017-03-13 13:27:21.111656"], ["updated_at", "2017-03-13 13:27:21.111656"]]
(0.7ms) COMMIT
(0.7ms) BEGIN
(0.4ms) COMMIT
Redirected to http://localhost:3000/quotes/general_questions
Completed 302 Found in 38ms (ActiveRecord: 5.1ms)
Started GET "/quotes/general_questions" for ::1 at 2017-03-13 10:27:21 -0300
Processing by QuotesController#show as HTML
Parameters: {"id"=>"general_questions"}
Client Load (0.9ms) SELECT "clients".* FROM "clients" WHERE "clients"."id" = $1 LIMIT 1 [["id", 47]]
Doctor Load (0.4ms) SELECT "doctors".* FROM "doctors" WHERE "doctors"."client_id" = $1 LIMIT 1 [["client_id", 47]]
(0.1ms) BEGIN
SQL (0.8ms) DELETE FROM "doctors" WHERE "doctors"."id" = $1 [["id", 29]]
(0.5ms) COMMIT
Any help would be great thanks!! Please let me know if you need anything else.
[NOTE: general remark about link_to_add_association and has_one]
The link_to_add_association
will try to build a new item on the association. If you have a has_one
relation, this effectively means it will replace the existing, if there is one.
If you really need to link_to_add_association
you can try the following:
= link_to_add_association 'add doctor', @form_obj, :doctor, force_non_association_create: true
(this will build a new doctor, but not using the association, this might mean some defaults defined on the association are not copied, BUT the existing doctor will not be overwritten unless chosen so after save of the form)
[UPDATE: in your case]
Just remove the @client.build_doctor
from the show
method. This re-initialises the doctor every time it is called. I assume you would only want this in the new
method.
Or, if I seem to read correctly, you only have a show
and no edit/new
do something like
@client.build_doctor unless @client.doctor.present?