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
<
Another option:
<td><%= user.chore.try(:name) %></td>
This will return nil
if there is no user.chore
.
It's because not every user has a chore associated with it.
There are a few ways you can deal with this; I'm partial to the iteration pattern using Array()
to coerce a collection. You can do this in your view:
<% Array(user.chore).each do |chore| %>
<td><%= chore.name %></td>
<td><%= chore.done? %></td>
<% end %>
Array()
will instantiate an empty array if chore
is nil, meaning nothing happens when you try to iterate over it. If a chore is present, it will iterate over [chore]
.
The benefit of this pattern is that it doesn't violate Tell don't ask. Asking an object if it is nil?
is also possible, but it's more of a procedural technique that doesn't take advantage of Ruby's strong object-oriented features.
Edit
As Deefour points out, this will result in a table with mismatched columns. You should probably use his solution for this case.
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>
Here's another option that uses Rails' Delegate module:
class User < ActiveRecord::Base
has_one :chore
delegate :name, to: :chore, prefix: true, allow_nil: true
end
This will allow you to call <%= user.chore_name %>
, which will pass the name
call onto chore, returning nil
if there is none.