0

Situation

I am trying to tie multiple phone numbers to a client with has_and_belongs_to_many. I am able to add a client and phone number. If I pull up a client where I have three phone numbers, it displays each number, but when I click on edit, it displays three input boxes with the same number in all three boxes instead of three unique numbers.

show.html.erb

This displays all three numbers.

<% @client.phones.each do |phone| %>
  <tr>
    <td><%= phone.number %></td>
<% end %>

_form.html.erb

Upon clicking edit, this displays three text input boxes with the same number in all three boxes.

  <% @client.phones.each do |phone| %>    
    <%=f.simple_fields_for @phone do |a| %>  
      <%=a.input :number %>
    <% end %>
  <% end %>

Below (same code as in show.html.erb) this will display all three unique numbers, but they are printed on the screen and obviously not in an input box where they can be changed.

  <% @client.phones.each do |phone| %>
    <tr>
      <td><%= phone.number %></td>
  <% end %>

clients_controller.erb

# GET /clients/1/edit
def edit
  #Find client by id
  @client = Client.find(params[:id])

  @phone = Phone.find(@client.phone_ids)

end


# PATCH/PUT /clients/1
# PATCH/PUT /clients/1.json
def update
  #Same as above, but if anything was changed, save the changes to the database
  @client = Client.find(params[:id])
  @phone = Phone.find(@client.phone_ids)
  @phone = Phone.where(number: params[:client][:phone][:number]).first_or_create
  @client.phones << @phone

  respond_to do |format|
    if @client.update(client_params)
      format.html { redirect_to @client, notice: 'Client was successfully updated.' }
      format.json { render :show, status: :ok, location: @client }
    else
      format.html { render :edit }
      format.json { render json: @client.errors, status: :unprocessable_entity }
    end
  end
end

My belief is that I am replacing my variable with each new number as it is not setup as an array. I started experimenting with map, but I haven't had any luck with it yet.

phone.map do |phone|
  Phone.find(@client.phone_ids)
end

Suggestions or insight if map is the right way to go or if there is something else that I am just not seeing?

1 Answers1

0

This two lines cause the problem, because you add the found or created phone to the user's phones over and over again:

@phone = Phone.where(number: params[:client][:phone][:number]).first_or_create
@client.phones << @phone 

Instead do:

def update
  @client = Client.find(params[:id])
  @phone = @client.phones.where(number: params[:client][:phone][:number]).first_or_create

  respond_to do |format|
    ...
  end
end

That will prevent you from creating new duplicates in the future.

Furthermore you have an typo in your _form.html.erb that leads to displaying the same phone number multiple times: Just remove the @ from <%= f.simple_fields_for @phone do |a| %>, it should be just

<%= f.simple_fields_for phone do |a| %>

To clean up duplicates in your db, you can run something like the following in your rails console:

Client.all.each do |client|
  uniq_numbers = client.phones.map(&:number).uniq

  client.phones = numbers.map do |number|
    Phone.where(number: number).first
  end
end
spickermann
  • 100,941
  • 9
  • 101
  • 131
  • I removed the line that you suggested removing. I also switched the first line for the replacement you provided, and I tried it with and without the `@client.phones << @phone` as I wasn't sure if you meant replace both lines with that one, or just the two lines were causing the problem, but just replace the first. In both cases it still presents me with the same number repeated three times. – Chris Fagerstrom Dec 23 '14 at 01:34
  • @ChrisFagerstrom: I updated my answer to be more clear about what to change. And I added some code that might help you to remove already existing duplicates from your database. – spickermann Dec 23 '14 at 01:53
  • I really appreciate all of your efforts to help me figure this out. I fear I may not be communicating clearly. I do have the first_or_create working properly, and there are no actual duplicates when I view the tables in my database, and the join table doesn't have any duplicate phone_id and client_id combinations. This is also reflected when I click show on a client - it shows three unique phone numbers i.e. 1111111111, 2222222222, 3333333333. But when I click edit, I get three boxes and they say 3333333333, 3333333333, 3333333333. – Chris Fagerstrom Dec 23 '14 at 03:40
  • Eureka! That was what I was missing! Thank you so much for not giving up on me!!! :) – Chris Fagerstrom Dec 23 '14 at 03:54
  • And now for the disappointment...I came back to it this morning to test everything out and when I click create to create a new client, the box doesn't show up to enter a phone number. I realized this is because of removing the `@` as simple_fields_for needs that to access it. I tried writing an if statement `if @phone.number.blank?` and then put in either statement with or without the `@`, which works, but when I go to edit an existing entry I get an undefined method 'number' for # – Chris Fagerstrom Dec 23 '14 at 13:59