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

strong parameters and methods

I keep issue with strong parameters and how to pull the virtual attributes (maybe getter and setters?) from them. Any time I try to get the first_name, last_name, or use the full name method i get something like "undefined method `first_name' for nil:NilClass" which I think means the object is not there. But i know the object has be created and stored in the database.

Here is a copy of User.rb

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  has_many :statuses

  validates :first_name, presence: true
  validates :last_name, presence: true

  def full_name
    first_name + ' ' + last_name

  end
end

Here is the show view

<p id="notice"><%= notice %></p>

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

<p>
  <strong>Content:</strong>
  <%= @status.content %>
</p>

<%= link_to 'Edit', edit_status_path(@status) %> |
<%= link_to 'Back', statuses_path %>

Can you also show the user controller (or a place that defines strong parameters for the user, since it's not that obvious in case of Devise) as well as Status model and controller?

Your view seems to be missing a closing > in the paragraph with name.

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  has_many :statuses

  validates :first_name, presence: true
  validates :last_name, presence: true

  def full_name
    first_name + ' ' + last_name

  end
end
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, notice: 'Status was successfully destroyed.' }
      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
class Status < ActiveRecord::Base
    belongs_to :user



end
module DevisePermittedParameters
  extend ActiveSupport::Concern

  included do
  before_action :configure_permitted_parameters, if: :devise_controller?
    end

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:sign_up) << :first_name << :last_name << :profile_name << :email << :password << :password_confirmation << :user_id
    devise_parameter_sanitizer.for(:account_update) << :first_name << :last_name << :profile_name << :email << :password << :password_confirmation << :user_id
  end

end

DeviseController.send :include, DevisePermittedParameters

i fixed the paragrah but i am still geting the same error

3 Answers

Try using self. in your user model, try various combinations like:

  def full_name
    self.first_name + ' ' + self.last_name

  end

or

  def self.full_name
    first_name + ' ' + last_name

  end

or

  def self.full_name
    self.first_name + ' ' + self.last_name

  end

Maybe one of them will work. Also, make sure that the status you are displaying had a user assigned to it and that that user has all the parameters in a database. Remember that one wrong old entry in the database can cause this error and prevent the whole page from displaying.

But wait...

You are getting error here?

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

This means some status has a user assigned to it that doesn't have the parameter. Or that no user is assigned to one of the statuses.

Go to Rails console, iterate through all the statuses and users and make sure that all statuses have existing users assigned to them and that all users have all parameters present (first name and last name). You can also drop the whole database, migrate it again and create new objects in the database. If that still gives you the error, please publish your code on github and I will run it locally to see if I can help you.

https://github.com/nix12/treebook

here the copy of the code i am working with. Sorry for taking so long to get back to you.

also, i reset and migrated and it still failed. so i checked the console and it shows that the user is created and saved (all the attributes are correct and saved), as well as the statuses are saved as well. I just can seem to access the first_name and last_name attributes.

Your code does not work at all on my machine. I'm unable to migrate the database for some reason and can't access the schema file on github (the whole db folder is locked).

So your migrate folder was outside the db folder...

Your statuses don't have any relation to the users (no user_id field). Make sure you watch all the videos closely.

Also, seems like you did not create any user model, since it's not in the schema at all:

https://github.com/nix12/treebook/blob/master/schema.rb

That migration file was an old that i moved to fix something before learning how to reset the database.

as for the schema, i could not figure out how to unlock the directory for github hub, but here is a copy of the current one.

# encoding: UTF-8
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# Note that this schema.rb definition is the authoritative source for your
# database schema. If you need to create the application database on another
# system, you should be using db:schema:load, not running all the migrations
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 20141126162005) do

  create_table "statuses", force: true do |t|
    t.text     "content"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.integer  "user_id"
  end

  add_index "statuses", ["user_id"], name: "index_statuses_on_user_id"

  create_table "users", force: true do |t|
    t.string   "first_name"
    t.string   "last_name"
    t.string   "profile_name"
    t.string   "email",                  default: "", null: false
    t.string   "encrypted_password",     default: "", null: false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    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"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  add_index "users", ["email"], name: "index_users_on_email", unique: true
  add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true

end

here are the migration files

class DeviseCreateUsers < ActiveRecord::Migration
  def change
    create_table(:users) do |t|
      t.string :first_name
      t.string :last_name
      t.string :profile_name

      ## Database authenticatable
      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
class CreateStatuses < ActiveRecord::Migration
  def change
    create_table :statuses do |t|
      t.string :name
      t.text :content

      t.timestamps
    end
  end
end
class AddUserIdToStatuses < ActiveRecord::Migration
  def change
    add_column :statuses, :user_id, :integer
    add_index :statuses, :user_id
    remove_column :statuses, :name
  end
end

Is there no way to access the first_name and last_name attributes from the strong parameters?

This has nothing to do with strong parameters. They are only used to put data INSIDE the database. Retrieving should work normally. Your users table does not have status_id column, which means there is no relation between statuses and users.