5

can anyone please walk me through Nested Attributes in Rails 3?

I have two Models: Certificates and Custodians, related as follows:

Certificate Model:

class Certificate < ActiveRecord::Base
  belongs_to :shareholder
  belongs_to :custodian
  belongs_to :issuer

  accepts_nested_attributes_for :custodian, :shareholder, :issuer 
end

Certificate Controller:

class CertificateController < ApplicationController
  def issue
    @certificate = Certificate.new
    @certificate.custodian.build
  end
end

My View:

<% form_for(:certificate, :url => {:action => 'testing'}) do |f| -%>

<div id="error">
    <%= f.error_messages %>
</div>

  <%= f.label :number, "Certificate Number" %>
  <%= f.text_field :number %>   <br/>

    <%= f.label :num_of_shares, "Number Of Shares" %>
    <%= f.text_field :num_of_shares %> <br/>

    <% f.fields_for :custodian do |custodian| -%>
        <%= custodian.label :name, "Custodian Name" %>
        <%= custodian.text_field :name %>
    <% end -%>

    <%= f.submit "Issue Certificate", :disable_with => 'Working....' %>

<% end -%>

Now, for some reason, in my controller on line 4: @certificate.custodian.build

I'm getting this error: undefined method 'build' for nil:NilClass

Can any one please help?

Jasdeep Singh
  • 3,276
  • 4
  • 28
  • 47

3 Answers3

9

With a belongs_to, it should be

@certificate.build_custodian
guitsaru
  • 598
  • 6
  • 8
  • 1
    Thanks `guitsaru` that worked. But, my view is not rendering the `fields_for` part at all. Rest of the form is being rendered properly. – Jasdeep Singh Feb 01 '11 at 21:08
7

accepts_nested_attributes_for should go on the side of one in the one-to-many relationship.

class Custodian < ActiveRecord::Base
  has_many :certificates
  accepts_nested_attributes_for :certificates
end

So, in your view, there should be no fields_for :custodian, it's on the wrong side. If you have to build a certificate from that view, you have to list custodians available, probably in a select box.

Srdjan Pejic
  • 8,152
  • 2
  • 28
  • 24
  • Thanks `Pejic` thats exactly what i'm trying to achieve. But rather than a select box, i plan on using Ajax to create an autocomplete field. But for now, i'm interested to get this done the way you described. – Jasdeep Singh Feb 01 '11 at 21:38
  • i can create a new instance variable with the Custodians listed and display a select box, but then how do i go back saving the association in the model? – Jasdeep Singh Feb 01 '11 at 21:39
  • Populate the select box with ID/Name option pairs. Here's a good guide as to how to do it, http://guides.rubyonrails.org/form_helpers.html#making-select-boxes-with-ease This should get your basic form up and running. To do autocomplete, you need to build the JSON so that it passes something unique to the Custodians controller, like an ID or a name if the name is unique. – Srdjan Pejic Feb 01 '11 at 21:45
6

This line

<% f.fields_for :custodian do |custodian| -%>

should be

<%= f.fields_for :custodian do |custodian| -%>
kgthegreat
  • 1,172
  • 9
  • 10