It's been a while since my last blog post. Dang, a whole week! Don't worry, though. I never stopped coding.
I'm still having trouble with my Manticore app. Basically, here's what I'm trying to do:
I have two models, Character and Statistic. Each Character will have_one Statistic, and Statistic belongs_to Character. So good so far, right? I want to be able to create the Statistic information from the Character view, then be able to edit that information once there's information to be edited. I want to only be able to create one instance of Statistic per Character, hence the has_one relationship.
One solution I got on Stack Overflow was to simply make a form in the Character view, but since I'll be extrapolating this code (once I finally understand it) to create other models like Equipment, Skills, Spells and so on, it doesn't make sense to load down the Character view with a ton of different forms.
I've been modeling the code for Manticore from this tutorial which has you create a blog. It was easy enough to see that Character could be substituted for the Post model, and Statistic could be substituted for the Comment model.
However, I've hit a wall. Now I get this error:
undefined method `build' for nil:NilClass
And I'm not sure why. I suspect it has something to do with the has_one vs. has_many relationship. Earlier, I'd followed the tutorial more closely, but I need to define the Character/Statistic relationship as has_one vs. has_many because I don't need multiple instances of Statistics per character. Any ideas where this error could be coming from? I'm not defining a build action, but this error never popped up before.
Here's some code, if that helps:
class Character < ActiveRecord::Base
has_one :statistic, :dependent => :destroy
end
class Statistic < ActiveRecord::Base
belongs_to :character
end
As far as I can tell, the model code is fine. But I might be missing something pretty obvious.
Here's code from the Statistics controller.
def create
@character = Character.find(params[:character_id])
@statistic = @character.statistics.create.new(params[:statistic])
redirect_to character_path(@character)
end
I may have something wrong here, but like I said, this has worked in the past and has tied the Statistic to the specific Character (something I was struggling with before this mess!)
This is from the Statistics _form partial:
<%= form_for([@character, @character.statistic.build]) do |f| %>
<div class="field">
<%= f.label :strength %>
<%= f.text_field :strength %>
</div>
...
<%= f.submit %>
</div>
<% end %>
I suspect my troubles may be coming from this code, but I don't get why. I'm following the tutorial and this has worked before, and all I've changed is the has_many relationship to a has_one.
In other less concrete news, I feel pretty dumb for just not getting this. However, in the course of trying to figure it out, both on my own, through people I know and asking and reading questions on Stack Overflow, I've got a much better grip on other things, like the overall MVC hierarchy, how partials work, how views work and so on.
I think part of what's keeping me interested in Ruby and Rails is how difficult it is for me. Coding is not something I have a great natural talent for, so I really have to work to make progress. Still, I'm proud of what I've learned so far and there is no shortage of great, helpful people in addition to a treasure trove of information available, so I'm confident I'll get where I want to be. Sooner or later.
Another problem I've had is describing exactly what I want to do. I think in the future, I'll benefit greatly from mapping projects out better beforehand as well as learning how to describe my ideas better.
Build and create are called differently for has_one relationships than they are for has_many.
ReplyDeleteWith 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
I wasn't even aware of build_*, very cool. Great advice from David and top-notch posting of a test-app.
ReplyDeleteAnother thing, great deduction of where the problem might be(has_one vs has_many). It turned out to be spot on and saved you a ton of time. You're getting good at this awfully fast :)
ReplyDelete@David This definitely helps! I'm still having some problems, though.
ReplyDeleteI want to keep the pages that add or edit a Statistic separate from the Character view. I imagine this as a button or link that will open a new page, allow a user to make changes, then redirect_to the Character view when finished. At this point, I want to show the information the user just added. I thought changing the statistic/show.html.erb file into a partial and rendering it would do this, but no dice.
@Eli Thanks! I'm fairly proud of myself for realizing the problem, though to be fair I have been spending a lot of time reading up on Stack Overflow and pestering people for help. The first step toward fixing a problem is recognizing it, right? I'm getting better at recognizing problems, anyway!
ReplyDelete@Tyler I updated the example app to do what (I think) you are talking about. Let me know if you need any help understanding it. Also, the Indy.rb meeting is tomorrow (http://meetup.com/indyrb). Think about it good sir!
ReplyDelete@David thanks again! I took a look at the updated code last night but haven't done much more than that. I'm planning to get some quality time in with Rails tonight, though.
ReplyDeleteObviously I didn't make it to the meetup last night but I'm definitely planning on going next week. Are you going to re:build in July?
I haven't made up my mind on re:build, I'm actually doing a lot of conference hopping this year as it is. But I may change my mind as the deadline approaches.
ReplyDelete