Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Ruby Build a Simple Ruby on Rails Application Customizing Forms Creating Relationships

Luke Thomas
Luke Thomas
9,077 Points

undefined method `user' for nil:NilClass

I get an error when I try to add the name back into the status.

NoMethodError in Statuses#index Showing /Users/ryan/Projects/treebook/app/views/statuses/index.html.erb where line #9 raised:

undefined method `user' for nil:NilClass Extracted source (around line #9):

   <% @statuses.each do |status| %>
     <div class="status">
       <strong><%= @status.user.full_name %></strong>
       <p><%= status.content %></p>
       <div class="meta">
         <%= link_to time_ago_in_words(status.created_at) + " ago", status %>  

Any help?

3 Answers

You made a typo. On the third line you made the variable status as an instance variable with the @ sign. Rails assumes you are referring to @status that is not present in your controller.

<% @statuses.each do |status| %>
     <div class="status">
       <strong><%= status.user.full_name %></strong>
       <p><%= status.content %></p>
       <div class="meta">
         <%= link_to time_ago_in_words(status.created_at) + " ago", status %> 

EDIT: To be more clear. Since you are referring to the instance variable @status that does not exist it cannot find any association with the User model. Ruby will accept a new instance variable even if its nil, because a nil variable is still an object and nil itself is an object (thats why everything is an object in Ruby). However Rails will return an error if the association is nil.

Maciej Czuchnowski
Maciej Czuchnowski
36,441 Points

Luke Thomas did this answer help you or do you still have problems with this error?

Luke Thomas
Luke Thomas
9,077 Points

Thanks Aurelien, now I get this:

Showing /Users/ryan/Projects/treebook/app/views/statuses/index.html.erb where line #9 raised:

undefined method `full_name' for nil:NilClass Extracted source (around line #9):

   <% @statuses.each do |status| %>
     <div class="status">
       <strong><%= status.user.full_name %></strong>
       <p><%= status.content %></p>
       <div class="meta">
         <%= link_to time_ago_in_words(status.created_at) + " ago", status %>  

Here's all my instances of full_name:

/Users/ryan/Projects/treebook/app/models/user.rb:
    7    has_many :statuses
    8  
    9:   def full_name
   10                  first_name + " " + last_name
   11    end

/Users/ryan/Projects/treebook/app/views/statuses/index.html.erb:
    7  <% @statuses.each do |status| %>
    8    <div class="status">
    9:     <strong><%= status.user.full_name %></strong>
   10      <p><%= status.content %></p>
   11      <div class="meta">

/Users/ryan/Projects/treebook/app/views/statuses/show.html.erb:
    3  <p>
    4    <strong>Name:</strong>
    5:   <%= @status.user.full_name %>
    6  </p>

Edit: Had a friend look at it and fix it up.

We changed from Status.new to current_user.statuses.new to automatically assign the status to the current user, because otherwise the status didn't get assigned to a user.

Yes, if you want to create a new post and programmatically input data of the current user, then its better to use the method current_user. A user has many status relationship, so the status it can fetch information about the given user and vice-versa. current_user will provide all of his info if he/she has a session going on.

I think I am missing something with your full_name error. You can also try prepend self in front of your properties first_name and last_name. But I think the problem is somewhere else. Also in your user model, did you add attr_accessible? Also make sure that you belongs_to :user in your Status model.

def full_name
    self.first_name + " " + self.last_name
end
Justin Black
Justin Black
24,793 Points

Going through this right now... I've already done odot course (painfully).. and now doing this ( 'cause why not complete all the ruby videos? )...

Been on the same video for about 30 minutes now.. 3 sub-tutorials, and still got an error on the index... for me, I was a moron and added the @ before status like the OP did.. Removing that fixed my errors beautifully... Now I feel dumb lol

Luke Thomas
Luke Thomas
9,077 Points

RE make sure that you belongs_to :user in your Status model [done] RE did you add attr_accessible? [yes]

Hmm I think you're right, I think the problem I'm having with full_name is because first_name and last_name aren't working properly... so the problem is somewhere else.

My full_name variable wasn't returning anything, so I changed it to

  def full_name
    if first_name and last_name
            first_name + " " + last_name
    else
        "Has no name"
    end
  end

And now "Has no name" is returning as all my user name - so that's why I think my first_name & last_name variables aren't working properly. Any ideas on this one Aurelien?

Well that makes sense. If the user is missing the first_name AND last_name your original full_name method returns nil + " " + nil. If one of the two property is nil, the method cannot return a string. In ruby you cannot concatenate different data type, nil being a data type different than a string.

So make sure your users have a first_name and a last_name.

You can adapt your full_name method however you want it so it doesn't break. How about the following?

1) Make sure that default in your database that the properties first_name and last_name have a default value of type string "" if you want to use the following method. You can also use .present? method instead of .blank? to make sure that the properties are not blank ("") or nil, but beware that present can return a different boolean than blank.

2) Add conditions to check if the properties are not blank and return the string that you want. I added extra conditions so that it only adds the whitespace when needed.

def fullname
   if self.first_name.blank? && self.last_name.blank?
        return "has no name"
   else
        if self.first_name.blank?
            return self.last_name
        elsif self.last_name.blank?
            return self.first_name
        else
             return self.first_name + " " + self.last_name
        end
   end
end

3) I usually prepend self when I try to access a property of a given user from a method stored in my model

def my_first_name
    self.first_name if self.first_name.present?
end

4) You can refactor the code in step 2 by using ternary operators to make the code shorter. I made it more verbose to explain the problem.

5) There are other tricks out there such as creating a method that automatically converts nil to an empty string "".

Let me know what you think and if this works out for you :)

Below is the code in action in Rails Console (rails c)

1.9.3-p484 :001 > first_name = ""
 => "" 
1.9.3-p484 :002 > last_name = ""
 => "" 
1.9.3-p484 :003 > def new_fullname(first_name, last_name)
1.9.3-p484 :004?>   if first_name.blank? && last_name.blank?
1.9.3-p484 :005?>     return "has no name"
1.9.3-p484 :006?>     else
1.9.3-p484 :007 >       if first_name.blank?
1.9.3-p484 :008?>       return last_name
1.9.3-p484 :009?>       elsif last_name.blank?
1.9.3-p484 :010?>       return first_name
1.9.3-p484 :011?>       else
1.9.3-p484 :012 >         return first_name + " " + last_name
1.9.3-p484 :013?>       end
1.9.3-p484 :014?>     end
1.9.3-p484 :015?>   end
 => nil 
1.9.3-p484 :016 > new_fullname(first_name, last_name)
 => "has no name" 
1.9.3-p484 :017 > first_name = "Aurelien"
 => "Aurelien" 
1.9.3-p484 :018 > new_fullname(first_name, last_name)
 => "Aurelien" 
1.9.3-p484 :019 > first_name = ""
 => "" 
1.9.3-p484 :020 > last_name = "Schlumberger"
 => "Schlumberger" 
1.9.3-p484 :021 > new_fullname(first_name, last_name)
 => "Schlumberger" 
1.9.3-p484 :022 > first_name = "Aurelien"
 => "Aurelien" 
1.9.3-p484 :023 > new_fullname(first_name, last_name)
 => "Aurelien Schlumberger"

With this in mind, you can do a lot of cool things.

For example if you want to preserve the privacy of the user, you could display the last_name with only an initial.

If the user has a Chinese name 金山星, the first name and last name are in reverse order 山星 being the first name, and 金 the last name.

You can also add a link to the profile of the user if the user has a name.

and so on...

Luke Thomas
Luke Thomas
9,077 Points

I tried your method for full_name to be

def fullname
   if self.first_name.blank? && self.last_name.blank?
        return "has no name"
   else
        if self.first_name.blank?
            return self.last_name
        elsif self.last_name.blank?
            return self.first_name
        else
             return self.first_name + " " + self.last_name
        end
   end
end

I signed up as a new user and double checked that i had a first and last name. Still returns "has no name".

So neither names are being stored :(

Where should I look to see why this is happening?

P.s. Never seen Rails C before but just tried it and ran your code, very helpful.