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

Jack McDowell
Jack McDowell
37,797 Points

NoMethodError in Statuses#show

Can someone help me with a NoMethodError in Statuses#show error? I'm using rails 4 and I forgot that this wonderful framework hates backwards compatibility. Anyway, I tried Lee Geertsen and Maciej Czuchnowski 's solutions and I can't get it to work. If anyone can help, here is my broken GitHub repo.

P.S. Does it just get worse from here or are the compatibility issues over? I'm trying to decide if I should just fire up a VM instead and download the program files.

3 Answers

Maciej Czuchnowski
Maciej Czuchnowski
36,441 Points

Jack, I downloaded your project locally.

The error states: undefined method `first_name' for nil:NilClass. Ths means that @status.user is nil. This in turn means that you did not assign any user to the status. If you run rails c and check Status.last you will notice that one of the parameters states user_id: nil - the user was not assigned, so Rails can't do nil.first_name.

If you look closely at the Rails server log, you will notice this line when new status was created: Unpermitted parameters: user_id, content This means that you are passing user_id and content correctly, but because of strong parameters, you have to overtly allow these parameters to be saved in the database.

You need to add this to your statuses_controller file:

private

    def status_params
      params.require(:status).permit(:user_id, :content)
    end

also, your create method has to start like this to use these status_params:

  def create
    @status = Status.new(status_params)

You need to permit parameters this way every time you want to pass them through a form and save in the database.

Jack McDowell
Jack McDowell
37,797 Points

Thank you Maciej Czuchnowski , the problem is with the strong parameters as you mentioned. I tried your fixes and it looks like it is one step closer to working, but I'm going to try finishing the project with rails 3.2 and maybe come back to this when I'm a better rails programmer. Coming from PHP I'm having to get adjusted to the innovation over standardization of Rails!

Juan Ordaz
Juan Ordaz
12,012 Points

In your statuses controller, you need to modified the [:create, :update, :destroy] actions. I don't know if the above answers are the best, because in the console you can see that the statuses.user_id returns nil, when query the Status.first.user_id. This is because, you are creating a status that does not belong to anybody. So when you are trying to render show view, the status has no user_id then you can not have access to the last_name attribute thats why you see and error. So you have to tell you controller who is writing the status. I tried to follow the video but is out of date and is ok( struggle to find an answer is the best way to learn). Devise gives you " current_user helper." In your controllers, use current_user helper like is shown below. This is the most conventional way to fix the bug(I think). The controllers should do this job(to check users credentials), not the model like in the video shows. The video is not wrong, is just that there has been many changes in Rails 4. Struggle == Learn.

def create
    @status = current_user.statuses.new(status_params)

    respond_to do |format|
      if @status.user == current_user
        @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

  def update
    respond_to do |format|
      if@status.user == current_user
        @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

  def destroy
    if @status.user == current_user
      @status.destroy
      respond_to do |format|
      format.html { redirect_to statuses_url, notice: 'Status was successfully destroyed.' }
      format.json { head :no_content }
      end
    else
      redirect_to statuses_path
    end
  end
Maciej Czuchnowski
Maciej Czuchnowski
36,441 Points

Yeah, you can't really do this course using Rails 4 and newest versions of gems unless you really know how and what to do and like experimenting a lot. What is your problem exactly? You show action seems to be empty: https://github.com/jackmcdowell/RubySocialMediaSite/blob/broken_authentication/app/controllers/statuses_controller.rb#L12

Jack McDowell
Jack McDowell
37,797 Points

Hello Maciej Czuchnowski , I changed the statuses controller to what the project files have but I still have the same problem (changes are pushed to GitHub). 1) Run rake db:drop db:create db:migrate 2) Create user (/users/sign_up): works and creates user 3) Post new status: Shows user name under user drop down. 4) Select user and post content: Broken After I click submit, it says on /statuses/1

"NoMethodError in Statuses#show" line 3 highlighted

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

And if I just go to the root it says "NoMethodError in Statuses#index" line 3 highlighted

<% @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 %>