0

I'm trying to save multiple fields with the same name into the database record

This is what I have for now:

<%= form_for @complaint, url: {action: 'create'}, :html => {:multipart => true} do |f| %>
  <%= f.label :complaint_info, 'Describa lo que sucedió' %>

  <%= f.cktext_area :complaint_info, :class => 'someclass', :ckeditor => {:language => 'us', :toolbar => 'mini'}, tabindex: '-1' %>

  <%= f.fields_for :witnesses do |witnesses_form| %>
        <%= witnesses_form.label :name, '¿Hay testigos?' %>
        <%= witnesses_form.text_field :name, placeholder: 'Escriba el nombre del testigo', tabindex: '-1' %>
        <%= witnesses_form.label :phone, 'Número de teléfono del testigo' %>
        <%= witnesses_form.text_field :phone, placeholder: 'Escriba el número de teléfono' %>

        <%= witnesses_form.label :name, '¿Hay testigos?' %>
        <%= witnesses_form.text_field :name, placeholder: 'Escriba el nombre del testigo', tabindex: '-1' %>
        <%= witnesses_form.label :phone, 'Número de teléfono del testigo' %>
        <%= witnesses_form.text_field :phone, placeholder: 'Escriba el número de teléfono' %>
  <% end %>


<% end %>

In the controller:

  def new
    @complaint = Complaint.new
    @complaint.witnesses.build
  end

  def create
    @complaint = current_user.complaints.build(complaint_params)
    if @complaint.save

      redirect_to dashboard_complaint_path(@complaint)
    else
      render 'new'
    end
  end

  private

  def complaint_params
    params.require(:complaint).permit(:complaint_info, witnesses_attributes: [:name, :phone])
  end

What I want to do is give the user the option to add multiple witnesses and save them each into a new record in the database.

EDIT:

here are the models:

Complaint:

class Complaint < ActiveRecord::Base
  belongs_to :user
  has_many   :witnesses

  accepts_nested_attributes_for :witnesses
end

and Witness:

class Witness < ActiveRecord::Base
  belongs_to :complaint
end

EDIT2:

Heres what the controller returns

Started POST "/dashboard/complaints" for 127.0.0.1 at 2015-06-10 12:14:10 -0400
Processing by Dashboard::ComplaintsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"0ek0KaaYdUR1ktwUOLCeEdAG0fB63WOIJIIXL7ASM1zMbXWDHyCcXce82ijpLJRmneHs39Um9EehL/GWJkPqiw==", "complaint"=>{"complaint_info"=>"<p>This is the description</p>\r\n", "witnesses_attributes"=>{"0"=>{"name"=>"Second witness", "phone"=>"7877877877"}}}, "button"=>""}
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1  ORDER BY "users"."id" ASC LIMIT 1  [["id", 1]]
   (0.3ms)  BEGIN
  SQL (0.8ms)  INSERT INTO "complaints" ("complaint_info", "user_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING "id"  [["complaint_info", "<p>This is the description</p>\r\n"], ["user_id", 1], ["created_at", "2015-06-10 16:14:10.452890"], ["updated_at", "2015-06-10 16:14:10.452890"]]
  SQL (1.3ms)  INSERT INTO "witnesses" ("name", "phone", "complaint_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id"  [["name", "Second witness"], ["phone", "7877877877"], ["complaint_id", 19], ["created_at", "2015-06-10 16:14:10.457497"], ["updated_at", "2015-06-10 16:14:10.457497"]]
   (96.3ms)  COMMIT
Redirected to http://localhost:3000/dashboard/complaints/19
Completed 302 Found in 125ms (ActiveRecord: 98.9ms)

As you can see, it only saves one witness record ["name", "Second witness"] and is the last field (there are two fields, I typed First witness and Second witness in the last one).

4
  • Could you add Complaint/Witness models? Commented Jun 10, 2015 at 15:49
  • And the error you are seeing. Commented Jun 10, 2015 at 16:03
  • @Daiku there is no error, I just can't find a way to save multiple fields with the same name, it just saves a single record with the information typed in the last field/s that are named the same :name :phone Commented Jun 10, 2015 at 16:05
  • Show us the params received by the controller. Commented Jun 10, 2015 at 16:10

1 Answer 1

1

Well, here is the approach. Say you want 2 records to save. Then you need to do :

def new
  @complaint = Complaint.new
  2.times { @complaint.witnesses.build }
end

The change your form as :

<%= form_for @complaint, url: {action: 'create'}, :html => {:multipart => true} do |f| %>
  <%= f.label :complaint_info, 'Describa lo que sucedió' %>

  <%= f.cktext_area :complaint_info, :class => 'someclass', :ckeditor => {:language => 'us', :toolbar => 'mini'}, tabindex: '-1' %>

  <%= f.fields_for :witnesses do |witnesses_form| %>
        <%= witnesses_form.label :name, '¿Hay testigos?' %>
        <%= witnesses_form.text_field :name, placeholder: 'Escriba el nombre del testigo', tabindex: '-1' %>
        <%= witnesses_form.label :phone, 'Número de teléfono del testigo' %>
        <%= witnesses_form.text_field :phone, placeholder: 'Escriba el número de teléfono' %>
  <% end %>
<% end %>

The block given to the nested fields_for call will be repeated for each witnesses instance in the associated with the f object.

Sign up to request clarification or add additional context in comments.

6 Comments

oh wow, never knew that doing x.times would auto duplicate the fields, thank you so much sir!
@Johhan I want to be your friend.. Do you? :)
sure? lol, btw if I only want to show the label once, is there another trick to that?
which label ? inside the fields_for ?
@Johhan that's possible.. But wouldn't it look bad. And really if you want, then use label_tag, and put outside the loop, just top of the fields_for and remove the label_tag out of the block...
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.