Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

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

Ryan Trimble
Ryan Trimble
15,559 Points

Ruby Issues

Greetings!

I am running into an issue where it appears first_name, last_name, and profile_name are not getting entered into the database.

When I go into the rails console I see:

  User id: 1, first_name: nil, last_name: nil, profile_name: nil, email: m******2@gmail.com, encrypted_password: $2a$10$DiQMxpa3f2aiaAF58JQNaO9AuhRvSdb4tNjxX9eF78R9..., reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 1, current_sign_in_at: "2014-03-27 02:42:39, last_sign_in_at: 2014-03-27 02:42:39, current_sign_in_ip: 127.0.0.1, last_sign_in_ip: 127.0.0.1, created_at: 2014-03-27 02:42:39, updated_at: 2014-03-27 02:42:39

For the record, I am using Rails 4.0.4 and have run into the issue where attr_accessible is deprecated. I fixed this by adding protected_attributes to the Gemfile. I'm a little unsure why these items are not getting added to the database.

Here is my migrate file:

class DeviseCreateUsers < ActiveRecord::Migration
  def change
    create_table(:users) do |t|

      ## Database authenticatable
      t.string :first_name,
      t.string :last_name,
      t.string :profile_name,
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      t.integer  :sign_in_count, default: 0, null: false
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.string   :current_sign_in_ip
      t.string   :last_sign_in_ip

      ## Confirmable
      # t.string   :confirmation_token
      # t.datetime :confirmed_at
      # t.datetime :confirmation_sent_at
      # t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at


      t.timestamps
    end

    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
  end
end

Here is my views/devise/registration/new.html.erb file:

<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <%= devise_error_messages! %>
  <div class="form-group">
    <%= f.label :first_name %><br />
    <%= f.text_field :first_name, placeholder:"Enter First Name", class:"form_control" %>
  </div>
  <div class="form-group">
    <%= f.label :last_name %><br />
    <%= f.text_field :last_name, placeholder:"Enter Last Name", class:"form_control" %>
  </div>
  <div class="form-group">
    <%= f.label :profile_name %><br />
    <%= f.text_field :profile_name, placeholder:"Enter Profile Name", class:"form_control" %>
  </div>

  <div class="form-group">
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: false, placeholder:"Enter Email", class:"form_control" %>
  </div>

  <div class="form-group">
    <%= f.label :password %><br />
    <%= f.password_field :password, autocomplete: "off", placeholder:"Enter Password", class:"form_control" %>
  </div>

  <div class="form-group">
    <%= f.label :password_confirmation %><br />
    <%= f.password_field :password_confirmation, autocomplete: "off", placeholder:"Retype Password", class:"form_control" %>
  </div>
  <div class="form-group">
    <%= f.submit "Sign up", class:"btn btn-primary" %>
  </div>
<% end %>
<%= render "devise/shared/links" %>

and here is my user.rb model:

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
   attr_accessible :email, :password, :password_confirmation, :remember_me,
                   :first_name, :last_name, :profile_name
    def full_name
        first_name + " " + last_name
    end
end

If you need any further information please let me know, I am really trying to figure this out and make it work!

Also, sorry if I botched the markdown on this post, I tried fixing it several times, but I cannot seem to make it work correctly :-/

4 Answers

Brandon Barrette
Brandon Barrette
20,485 Points

So that error has nothing to do with the user in the database (although it appears that way)

You are getting the error because there is no user_id stored with your status. So what's happening is:

@status.user = nil #no idea, since there is no user_id in the db

Then when you call

@status.user.full_name

You are calling full_name on nil, so it won't work. My guess is in your statuses_controller, you need to add user_id to the protected attributes, much like you just added first_name, last_name etc to the users_controller. This way, when you save a status, the user_id will be permitted through and then be saved in the db.

To check this you can go to rails console in the terminal and type

Status.last

Look and see if the user_id is stored there or not.

Ryan Trimble
Ryan Trimble
15,559 Points

I literally just discovered this after replying to your first comment. The user_id is not getting recorded on the status table! I still wasn't sure how to fix it, but I'm sort of happy that I was able to determine that was the problem.

I'm on my way to dinner right now, but I will be checking out what you suggested when I get back.

Thanks for all your help!!

Brandon Barrette
Brandon Barrette
20,485 Points

This has been answered a few times on the forums. It's an issue with Rails 4 and protected_attributes. Here's one solution. I'd scour the forum a bit more for other solutions.

https://teamtreehouse.com/forum/treebook-app-firstname-lastname-profilename-nat-saving

Ryan Trimble
Ryan Trimble
15,559 Points

OK! I tried that, and I do appear to be getting entries for first_name, last_name, and profile_name in the database now!

I am, however, still getting the NoMethodError that reads

undefined method `first_name' for nil:NilClass

Even after reseting the database and running rake db:migrate. There is only one entry in the DB and it definitely has the First Name, Last Name, etc.

I will continue looking, thanks for your assistance on this one!

Ryan Trimble
Ryan Trimble
15,559 Points

Now, I have it working... but only on the show page, on the index page it does not show the full name!

On the Show page, I have it set up like this:

<p>
  <strong>Name: <%= @status.user.full_name %></strong>
</p>

And on the index page:

<% @statuses.each do |status| %>
  <div class="status">
    <strong><% status.user.full_name %></strong>
    <p><%= status.content %></p>

I now know that I at least have the correct information in the database and it is working... just not everywhere.

Ryan Trimble
Ryan Trimble
15,559 Points

OH WAIT!

I saw it as I was re-reading my comment. I missed and equal's sign in the erb opening on the index page.

<% status.user.full_name %>

should be

<%= status.user.full_name %>

AND NOW IT IS WORKING!

THANKS SO MUCH FOR ALL OF YOUR ASSISTANCE!

Brandon Barrette
Brandon Barrette
20,485 Points

So for sanity sake, here is the difference between <%= and <%

<%= #display the output when between this %>

<% #run this code, don't display the output %>
Ryan Trimble
Ryan Trimble
15,559 Points

That is a very useful tip! Thanks again!