Reputation: 470
I have two models, Character and Statistic. Their relationship is Character has_one Statistic and Statistic belongs_to Character.
I've generated scaffolds for both models and what I want to do is be able to create a new Statistic if there isn't one present, display the Statistic model and edit the Statistic model, all from the Character view. I'm unsure how to edit the controllers or write the code in the view to make this happen.
Here's some code. From the Character view:
<h2>Statistics</h2>
<%= render "statistics/form" %>
However, this gives me this error:
undefined method `build' for nil:NilClass
Extracted source (around line #1):
1: <%= form_for ([@character, @character.statistic.build]) do |f| %>
2: <% if @statistic.errors.any? %>
3: <div id="error_explanation">
4: <h2><%= pluralize(@statistic.errors.count, "error") %> prohibited this statistic from being saved:</h2>
So I'm assuming I don't have the first line written correctly? I thought this would work, since I want each instance of Statistic to belong to one Character and this would create that relationship.
Here's the code from Statistics/form:
<%= form_for ([@character, @character.statistic.build]) do |f| %>
<% if @statistic.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@statistic.errors.count, "error") %> prohibited this statistic from
being saved:</h2>
<ul>
<% @statistic.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :strength %><br />
<%= f.text_field :strength %>
...
<div class="field">
<%= f.label :charisma %><br />
<%= f.text_field :charisma %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Thanks in advance for any help. I've been wrestling with associating models in this way for about a week now and I'm pretty frustrated that I'm still not understanding.
Upvotes: 2
Views: 984
Reputation: 18784
Build and create are called differently for has_one relationships than they are for has_many.
With has_many @character.statistic.build works, but with has_one, it needs to be done like this:
@character.build_statistic and .create_statistic
I whipped up an app to test it, and threw it up on Github for you. I hope it helps.
https://github.com/unixmonkey/Manticore_example
Upvotes: 0
Reputation: 7714
You can include the statistic fields in your character form and have the association created automatically, but the process is different.
First use accepts_nested_attributes_for in your Character
model:
has_one :statistic
accepts_nested_attributes_for :statistic
And use fields_for in your character form:
<%= form_for @character do |f| %>
... all your character fields as generated in your scaffold
<%= f.fields_for :statistic do |statistic_fields| %>
... all your statistic fields using statistic_fields as form object, ie:
<%= statistic_fields.label :strength %><br />
<%= statistic_fields.text_field :strength %>
...
<% end %>
<%= f.submit %>
<% end %>
Edit: You can still use a partial if you want to separate the forms:
Change to statistic form to something like this:
<%= form_for @statistics do |f| %>
<%= render :partial => "statistics/fields", locals => {:f => f} %>
<% end %>
Create a statistic fields partial app/views/statistic/_fields.html.erb
containing all the fields that were previously in the above form:
<div class="field">
<%= f.label :strength %><br />
<%= f.text_field :strength %>
...
And then you can reuse the statistic fields in your character form like this:
<%= form_for @character do |f| %>
...
<%= f.fields_for :statistic do |statistic_fields| %>
<%= render :partial => "statistics/fields", locals => {:f => statistic_fields} %>
<% end %>
<%= f.submit %>
<% end %>
Upvotes: 1