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 Creating an Authentication System Migrating Statuses

First Name, Last Name and Profile Name not saving in Database

Hi There

I am using Rails 4 and Devise following this tutorial, I am struggling to get the user's name to show on the posted statuses. After mucking around for hours it's because the First Name, Last Name and Profile Name are not being saved in my database. I have followed the tutorial on here to the word (db migrated successfully etc) and I assume it may be because my version of Rails is different to the one being used here. I read somewhere about Strong Parameters, apparently I don't use attr_attributes anymore? Devise does save the emails and password fields however and I have managed to prompt that in a dropdown when posting a new status (in a future tutorial) but that still doesn't display on my status. Any help will be hugely appreciated Thanks!

10 Answers

Lisa Rossiter
Lisa Rossiter
3,630 Points

You have to permit first name last name and profile name in the controller. attr_attributes are not used anymore you are correct. Its to do with mass assignment and protecting against it, essentially saying yep I would only like to allow these fields to be updated and changed, also with require you can drill down the use of your parameters. Heres a few links to what I have found useful when dealing with the exact same problem.

https://github.com/rails/strong_parameters

http://www.sitepoint.com/rails-4-quick-look-strong-parameters/

Bit out of date but gives more understanding http://blog.sensible.io/2013/08/17/strong-parameters-by-example.html

So devise has its own little system and the fact you don't have the values in the database at all say to me that they was never saved for you in the first place. To check this type the below one by one in your terminal when you are in your treebook directory.

rails console
User.all

And see if it sais nil in the entry

If so updating your application_contoller will do it:

Check devise docs for the code its in there somewhere...

class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception

  before_filter :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:first_name,:last_name,:profile_name,:email, :password) }
    devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:first_name,:last_name,:profile_name,:email, :password) }
  end

end

Now boot up your server go to update your profile and enter those values. Boom.

You may now also have to tweak the permit value in the status controller to bring in those fields.

Let me know how you get on. :)

Massive help Lisa thanks for answering!

I have done all changes proposed by you and when I add a new user the first name, last name and profile name are stored within the db! (checked in console)

Now I am trying to relay these through into the status.rb, in the video it's shown as an attr_accessible again and it's not passing through (aka when I add my user ID into the name field (the number of my user)) it still displays nothing in the name field).

Here are (what I think are) the necessary files:

My _form.html.erb

<%= simple_form_for(@status, html: {class: 'form-horizontal'}) do |f| %>
  <% if @status.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@status.errors.count, "error") %> prohibited this status from being saved:</h2>

      <ul>
      <% @status.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <%= f.input :user_id %>
  <%= f.input :content %>

  <div class="form-actions">
  <%= f.button :submit %>
  </div>
<% end %>

My status.rb

class Status < ActiveRecord::Base
    attr_accessible :content, :user_id
    belongs_to :user
end

And my statuses controller

class StatusesController < ApplicationController
  before_action :set_status, only: [:show, :edit, :update, :destroy]
  # GET /statuses
  # GET /statuses.json
  def index
    @statuses = Status.all
  end
  # GET /statuses/1
  # GET /statuses/1.json
  def show
  end

  # GET /statuses/new
  def new
    @status = Status.new
  end

  # GET /statuses/1/edit
  def edit
  end

  # POST /statuses
  # POST /statuses.json
  def create
    @status = Status.new(status_params)


    respond_to do |format|
      if @status.save
        format.html { redirect_to @status, notice: 'Status was successfully created.' }
        format.json { render :show, status: :created, location: @status }
      else
        format.html { render :new }
        format.json { render json: @status.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /statuses/1
  # PATCH/PUT /statuses/1.json
  def update
    respond_to do |format|
      if @status.update(status_params)
        format.html { redirect_to @status, notice: 'Status was successfully updated.' }
        format.json { render :show, status: :ok, location: @status }
      else
        format.html { render :edit }
        format.json { render json: @status.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /statuses/1
  # DELETE /statuses/1.json
  def destroy
    @status.destroy
    respond_to do |format|
      format.html { redirect_to statuses_url }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_status
      @status = Status.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def status_params
      params.require(:status).permit(:name, :content)
    end
end

Massive help Lisa thanks for answering!

I have done all changes proposed by you and when I add a new user the first name, last name and profile name are stored within the db! (checked in console)

Now I am trying to relay these through into the status.rb, in the video it's shown as an attr_accessible again and it's not passing through (aka when I add my user ID into the name field (the number of my user)) it still displays nothing in the name field).

Here are (what I think are) the necessary files:

My _form.html.erb

<%= simple_form_for(@status, html: {class: 'form-horizontal'}) do |f| %>
  <% if @status.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@status.errors.count, "error") %> prohibited this status from being saved:</h2>

      <ul>
      <% @status.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <%= f.input :user_id %>
  <%= f.input :content %>

  <div class="form-actions">
  <%= f.button :submit %>
  </div>
<% end %>

My status.rb

class Status < ActiveRecord::Base
    attr_accessible :content, :user_id
    belongs_to :user
end

And my statuses controller

class StatusesController < ApplicationController
  before_action :set_status, only: [:show, :edit, :update, :destroy]
  # GET /statuses
  # GET /statuses.json
  def index
    @statuses = Status.all
  end
  # GET /statuses/1
  # GET /statuses/1.json
  def show
  end

  # GET /statuses/new
  def new
    @status = Status.new
  end

  # GET /statuses/1/edit
  def edit
  end

  # POST /statuses
  # POST /statuses.json
  def create
    @status = Status.new(status_params)


    respond_to do |format|
      if @status.save
        format.html { redirect_to @status, notice: 'Status was successfully created.' }
        format.json { render :show, status: :created, location: @status }
      else
        format.html { render :new }
        format.json { render json: @status.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /statuses/1
  # PATCH/PUT /statuses/1.json
  def update
    respond_to do |format|
      if @status.update(status_params)
        format.html { redirect_to @status, notice: 'Status was successfully updated.' }
        format.json { render :show, status: :ok, location: @status }
      else
        format.html { render :edit }
        format.json { render json: @status.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /statuses/1
  # DELETE /statuses/1.json
  def destroy
    @status.destroy
    respond_to do |format|
      format.html { redirect_to statuses_url }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_status
      @status = Status.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def status_params
      params.require(:status).permit(:name, :content)
    end
end

Also, when I add this line to my show.html.erb

<%= @status.user.first_name %>

It comes back with an error saying my method (first_name) is nil, but my db definitely has that field filled?

Lisa Rossiter
Lisa Rossiter
3,630 Points

Thats probably because it needs the user id to find the first name.

Lisa Rossiter
Lisa Rossiter
3,630 Points

Try again but put your user id into the status params as mentioned at the bottom of my comment.

params.require(:status).permit(:user_id, :name, :content)

Also take out of your status.rb

attr_accessible :content, :user_id

EDIT. Fixed!

Lisa Rossiter
Lisa Rossiter
3,630 Points

Also just as a pointer I really recommend watching and completing the ruby foundations course before completing this one it will make a lot of things make sense, lets face it you wouldn't try to build a house without understanding the foundations.

Lisa Rossiter
Lisa Rossiter
3,630 Points

Trust me this is only the beginning of your problems...

But it is good to learn the differences between r3 and r4.

Are you working on a public git if not post in your show page and index page or the part that display statuses. You can take out :name as well if you like not needed anymore.

Lisa Rossiter
Lisa Rossiter
3,630 Points

Is everything fixed buddy?

How did you fix it?

Haha I'm sure, I'm taking a lot from the videos but luckily there is a lot of Rails 4 info I've been using with updated methods of how to use it.

So far so good, got the full_name to display in the show and edit bits of my statuses!

Is it ok if I post back here if I run into any other problems? I'm usually pretty good at working things out on my own but there's nothing like a fresh opinion on a problem!

Thanks a lot for the help so far

Lisa Rossiter
Lisa Rossiter
3,630 Points

Sure no problems, you seem much like myself I spent two weeks on a problem on here before I posted on here. Probably a bit long :)

Andrzej Mega
Andrzej Mega
1,184 Points

Hey. sorry to dig out older thread, but I am exactly in the same boat here. I'm working with rails 4 so above fixes work perfectly...

BUT... I cannot show any <%= @status.user.xxxxxxx %> params on the index page. It DOES show on the "SHOW" page, but just not on the index. I get an error which says : NoMethodError in Statuses#index undefined method `user' for nil:NilClass

Calling any of the User parameters doesn't work.

Any clues ?? :)

Lisa Rossiter
Lisa Rossiter
3,630 Points

Strange, can you post the exact errors you are getting?