Question

I get the following error with the supplied code.

undefined method `password' for #<User:0x00000002e66980>

User Model

class User < ActiveRecord::Base

  validates_presence_of     :username
  validates_presence_of     :first_name
  validates_presence_of     :last_name
  validates_presence_of     :email

  validates_uniqueness_of   :username
  validates_uniqueness_of   :email

  attr_accessor             :password_confirmation
  validates_confirmation_of :password

  validate                  :password_non_blank

  # password is a virtual attribute
  def password=(pwd)
    @password = pwd

    return if pwd.blank?
    create_new_salt
    self.hashed_password = self.class.encrypt_password(pwd, self.password_salt)
  end

  def self.authenticate(username, password)
    if user = self.find_by_username(username)
      if user.hashed_password == encrypt_password(password, user.password_salt)
        user
      end
    end
  end

  def User.encrypt_password(password, password_salt)
    string_to_hash = password + "woozlewozzle" + password_salt
    Digest::SHA1.hexdigest(string_to_hash)
  end

private

  def password_non_blank
    errors.add(:password, "Password cannot be blank.") if hashed_password.blank?
  end

  def create_new_salt
    self.password_salt = self.object_id.to_s + rand.to_s
  end

end

Users Controller

class Admin::UsersController < Admin::AdminController

  skip_before_filter :authorize

  # GET /users
  # GET /users.xml
  def index
    @users = User.find(:all, :order => :username)

    respond_to do |format|
      format.html # index.html.erb
    end
      end

  # GET /users/1
  # GET /users/1.xml
  def show
    @user = User.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
    end
  end

  # GET /users/new
  # GET /users/new.xml
  def new
    @user = User.new

    respond_to do |format|
      format.html # new.html.erb
    end
  end

  # GET /users/1/edit
  def edit
    @user = User.find(params[:id])
  end

  # POST /users
  # POST /users.xml
  def create
    @user = User.new(params[:user])

    respond_to do |format|
      if @user.save
        flash[:notice] = "User #{@user.first_name} #{@user.last_name} was created successfully."
        format.html { redirect_to(:action => 'index') }
      else
        format.html { render :action => 'new' }
      end
    end
  end

  # PUT /users/1
  # PUT /users/1.xml
  def update
    @user = User.find(params[:id])

    respond_to do |format|
      if @user.update_attributes(params[:user])
        flash[:notice] = "User #{@user.first_name} #{@user.last_name} was updated successfully."
        format.html { redirect_to(:action => 'index') }
      else
        format.html { render :action => "edit" }
      end
    end
  end

  # DELETE /users/1
  # DELETE /users/1.xml
  def destroy
    @user = User.find(params[:id])
    @user.destroy

    respond_to do |format|
      format.html { redirect_to(admin_users_url) }
    end
  end
end

Namespace Routes

  namespace 'admin' do
    get 'admin' => 'manage#index'
    resources :users
  end

User Form

<%= form_for(@user, :url => admin_users_path(@user)) do |f| %>
  <% if @user.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>

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

  <div class="field">
    <%= f.label :username %><br />
    <%= f.text_field :username %>
  </div>
  <div class="field">
    <%= f.label :first_name %><br />
    <%= f.text_field :first_name %>
  </div>
  <div class="field">
    <%= f.label :last_name %><br />
    <%= f.text_field :last_name %>
  </div>
  <div class="field">
    <%= f.label :salutation %><br />
    <%= f.text_field :salutation %>
  </div>
  <div class="field">
    <%= f.label :email %><br />
    <%= f.text_field :email %>
  </div>
  <div class="field">
    <%= f.label :password %><br />
    <%= f.password_field :password %>
  </div>
  <div class="field">
    <%= f.label :password_confirmation, 'Confirm Password' %><br />
    <%= f.password_field :password_confirmation %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>
Was it helpful?

Solution

Yes, you need attr_accessor :password and you don't need attr_accessor :password_confirmation as validates_confirmation_of :password will create it for you.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top