bdx
bdx

Reputation: 3516

Rails - Nested form fields_for not rendering

I have two models which are linked in a has_one / belongs_to association; Computer and Ipv6Address respectively.

I have pre-populated the Ipv6Address table with all the entries that I want it to have, and I now need to have a drop-down list on the Computer new/edit forms to select an item from Ipv6 to associate it with. The reason for needing to pre-populate this is that there is a predefined range of IPv6's that computers can have associated to them, and I want it to be as easy as possible for an end user to just pick something blindly from a list without having to understand why they're doing it; but give anyone who does know what it is the opportunity to pick one they want.

Everything I've seen so far on this only seems to work when you are creating both objects at the same time on the new form and then subsequently editing them.

I've tried to set up my MVC's as per the examples I've found online, and by checkout out other stackoverflow questions on a similar topic.

Computer model:

class Computer < ActiveRecord::Base
  has_one :ipv6_address
  accepts_nested_attributes_for :ipv6_address
  ...

Ipv6Address model:

class Ipv6Address < ActiveRecord::Base
  attr_accessible :computer_id, :ip_address
  belongs_to :computer
  ...

Computer controller:

class ComputersController < ApplicationController
  def new
    @computer = Computer.new
    @ipv6s = Ipv6Address.where('computer_id IS NULL').limit(5)
  end

  def edit
    @computer = Computer.find(params[:id])
    @ipv6s = Ipv6Address.where('computer_id = #{@computer.id} OR computer_id IS NULL').order('computer_id DESC').limit(5)
  end

Computer new form:

<%= simple_form_for( @computer ) do |f| %>
  <%= f.fields_for :ipv6_address do |v6| %>
    <%= v6.input :ipv6_address, :collection => @ipv6s %>
  <% end %>
  <% f.button :submit %>
<% end %>

When this new form renders, there are no input fields for ipv6_address included, though no errors are thrown. I've checked the source of the rendered page and nothing references "ipv6".

If I change the fields_for to:

<%= f.fields_for :ipv6_address, @ipv6s do |v6| %>

Then I get multiple dropdown selection fields appearing on the page, one for every object in @ipv6s, each containing a full list of objects in @ipv6s.

Upvotes: 0

Views: 651

Answers (1)

rocket scientist
rocket scientist

Reputation: 2447

It seems you do not want to be creating new ivp6_addresses, all you want to do is build the association between computer and address when the computer is created. You can either do this with a third table to define all the computer/ivp6 relationships or you can tweak your model definitions a little bit. Below is how to do it without adding a third table.

The relationship may seem a little backwards in the wording but rails will find the ipv6 association by finding the ivp6_address_id in the computers table. If it was the other way around you would need a new ivp6_address for every computer created which is not what you said you wanted. Make sure you have the appropriate id column in the computers table for the ivp6_address_id or whatever foreign key you want to use.

Computer model:

class Computer < ActiveRecord::Base
  belongs_to :ipv6_address
  ...

Ipv6Address model:

class Ipv6Address < ActiveRecord::Base
  attr_accessible :ip_address
  has_many :computers
  ...

Then get rid of the nested fields in your computer form and add the line below to build the association when the form is submitted.

<%= form_for( @computer ) do |f| %>
   <!--All the computer fields you need-->
  <%= collection_select(:computer, :ipv6_address_ids, Ipv6Address.all, :id, :ip_address, {}, { :multiple => true } )%>
  <% f.button :submit %>
<% end %>

Upvotes: 1

Related Questions