Search code examples
ruby-on-railsrubymodelhas-one

Accessing a has_one associations' attributes


I'm still quite new to Rails so hopefully this isn't a silly question.

I have two models: User and Chore. User has_one chore, and Chore belongs to User

class User < ActiveRecord::Base
  attr_accessible :chore_done, :email, :name, :phone
  has_one :chore

class Chore < ActiveRecord::Base
  attr_accessible :name, :user_id
  belongs_to :user

In my user index, I'm trying to show all users and display the chore that is associated with him or her. I'm doing this by passing User.all to the view and using a .each to iterate through each user:

<% @users.each do |user| %>
  <tr>
    <td><%= user.name %></td>
    <td><%= user.chore.name %></td>
    <td><%= user.chore_done? %></td>
    <td><%= link_to 'Edit', edit_user_path(user) %></td>
    <td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %></td>
  </tr>
<% end %>

Unfortunately, I cannot access the name attribute of the Chore. I get this error:

undefined method `name' for nil:NilClass

If I remove the .name attribute, it just returns a pointer to the Chore object.

I have a feeling this has something to do with passing the User.all object to the view and then iterating over that. Just accessing a specific User object (e.g. User.find(1)) in the console, and then accessing user.chore.name works fine.

1.9.3-p194 :045 > user = User.find(4)
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", 4]]
 => #<User id: 4, name: "Example User", email: "[email protected]", phone: 8675309, chore_done: false, created_at: "2012-11-05 01:53:33", updated_at: "2012-11-05 01:53:33"> 
1.9.3-p194 :046 > user.chore.name
  Chore Load (0.3ms)  SELECT "chores".* FROM "chores" WHERE "chores"."user_id" = 4 LIMIT 1
 => "Living room" 

I read a bit about AssociationProxy in the APIDock, but I don't think I understand it completely nor do I know how to work with it. From what I gathered, accessing all objects in a model returns an Array of objects but doesn't return a complete set of attributes for its dependencies? So, in this case, I get a pointer to the Chore object but no access to any of its attributes.

I could certainly just add Chore as another column in my user table, but I may add to that model in the future + I just want to figure out how the has_one association works anyway.

Any help is appreciated!


Solution

  • undefined method `name' for nil:NilClass

    This says that you are trying to call some method name() on an an instance of Nil. Within your code's context, that says that chore on this line is nil

    <td><%= user.chore.name %></td>
    

    Simply put, one of the User instances in @user has no associated Chore. One simple way to accomodate this in your view is by checking if user.chore exists.

    <td><%= user.chore.nil? ?  "some default name" : user.chore.name %></td>