Saturday, July 30, 2011

Models, forms and view pages in Rails

I'm back to working on Manticore after a couple months away doing tutorials. I've made some progress this afternoon, but now I've run into a snag.

Here's what's going on: I have two models, Character and Item. I've created a form_for new Items that belong to a Character. The form works fine when displayed in the Character view, but what I want to do is move the form and Item listing out of the Character view and into the Index page of Item, so I can link to it from the Character view. I've got a _menu partial that I'll be using to display other views relating to Character, such as Skills, Spells, Items and so on. I'm not sure what the issue is, but simply transplanting the code as is gives me this error:

undefined method 'items' for nil:NilClass

Here's the exact code I'm using:

<h2>Add an item:</h2>

<%= form_for ([@character, @character.items.build]) do |f| %>
  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :type %><br />
    <%= f.text_field :type %>
  </div>
  <div class="field">
    <%= f.label :location %><br />
    <%= f.text_field :location %>
  </div>
  <div class="field">
    <%= f.label :description %><br />
    <%= f.text_area :description %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

<table>
<% @character.items.each do |item| %>
  <tr>
    <td><%= item.name %></td>
    <td><%= item.type %></td>
    <td><%= item.location %></td>
    <td><%= item.description %></td>
  </tr>
  <table>
<% end %>

Like I said, this works just fine in the character/show page, but does not work when placed in item/index and linked to from my _menu partial. Any ideas?

Here's a link to my git repository:

6 comments:

  1. "undefined method 'items' for nil:NilClass"

    What this is telling you is that you called .items on something that was nil.

    In the code you posted, .items is being called on "@character"

    Likely you didn't set up @character in your controller to make it available to the view.

    ReplyDelete
  2. I'm still not getting this. Firstly, do I need to define this as items or item? I'm guessing items, since a character has_many items. Secondly, which controller do I need to edit? I'm guessing I need to mention @character in the items controller, but I'm unsure how do do that. How do I define items (or item, if that's correct) in this case, and where?

    ReplyDelete
  3. It sounds like you want to go to manticore.com/characters/1/items/ and see (as well as edit) items your character (with id of 1) has.

    Is that about right?

    if so, your items_controller should have a bit something like this:

    def index
    @character = Character.find(params[:character_id])
    end

    Then you have made @character available to your view and that view should work.

    ReplyDelete
  4. @David yeah, that's exactly what I wanted. This code did the trick! I had originally defined the index as such:

    def index
    @items = Item.all
    end

    Which is why I was confused. I thought items needed to be defined, since the error was that it was an undefined term.

    ReplyDelete
  5. Ok, now I've got the ability to create, view and destroy items in the items view. But I can't get an edit action to work.

    I get a routing error, saying "No route matches /characters/9/items/9" and I haven't been able to figure out how to fix it.

    ReplyDelete