Jasdeep Singh
Jasdeep Singh

Reputation: 3326

Nested Attributes in Rails 3

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?

Upvotes: 5

Views: 15230

Answers (3)

kgthegreat
kgthegreat

Reputation: 1332

This line

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

should be

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

Upvotes: 6

Srdjan Pejic
Srdjan Pejic

Reputation: 8212

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.

Upvotes: 7

guitsaru
guitsaru

Reputation: 598

With a belongs_to, it should be

@certificate.build_custodian

Upvotes: 9

Related Questions