开发者

Cannot bypass validation error 'You need to supply at least one attribute' in ActiveRecord?

I've been following the Michael Hartl Tutorial, but took a shortcut to try and 'improve' on its example, and have create a tough bug...

Basically, this app revolves around a User model coupled with a sign-up feature using a lot of validations around an encrypted password feature; kind of non-trivial for a rails newbie.

Instead of strictly following Hartl's example, I modified the approach to use a scaffold to set up my Users. But somewhere towards the end of his project I started getting this error when attempting to create a User:

ArgumentError in UsersController#new

You need to supply at least one attribute.

This is baffling to me, since I've attempted to turn off all validation except with saving. Below are some code fragments:

my users_controller.rb#new:

class UsersController < ApplicationController
  # GET /users
  # GET /users.xml
  def index
    @users = User.all

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @users }
    end
  end

.....


  def new

    @title = "Sign up"
    @user = User.new

    #(unnecessary?)
    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @user }
    end
  end

from my user.rb:

class User < ActiveRecord::Base

  attr_accessor :password
  attr_accessor :username, :firstname, :lastname, :email, :password, :password_confirmation

  email_regex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i

  # here I am attempting to only validate when saving
  validates :allow_nil => true, :presence => true, :on => :save

  validates :firstname,  :presence => true,
                    :length   => { :maximum => 50 }

  validates :lastname,  :presence => true,
                    :length   => { :maximum => 50 }

  validates :username,  :presence => true,
                    :length   => { :maximum => 20 }

  validates :email, :presence => false,
                    :format   => { :with => email_regex },
                    :uniqueness => { :case_sensitive => false }

  # Automatically create the virtual attribute 'password_confirmation'.
  validates :password, :presence     => true,
                       :confirmation => true,
                       :length       => { :within => 6..40 }

  before_save :encrypt_password

   # Return true if the user's password matches the submitted password.
  def has_password?(submitted_password)
    encrypted_password == encrypt(submitted_password)
  end

  def self.authenticate(email, submitted_password)
    user = find_by_email(email)
    return nil  if user.nil?
    return user if user.has_password?(submitted_password)
  end

  def self.authenticate_with_salt(id, cookie_salt)
    user = find_by_id(id)
    (user && user.salt == cookie_salt) ? user : nil
  end

  def initialize(attributes = {})
    @username  = attributes[:username]
    @firstname  = attributes[:firstname]
    @lastname  = attributes[:lastname]
    @email = attributes[:email]
  end

  def formatted_email
    "#{@firstname} #{@lastname}<#{@email}>"
  end

  private

    def encrypt_password
      self.salt = make_salt unless has_password?(password)
      self.encrypted_password = encrypt(password)
    end

    def encrypt(string)
      secure_hash("#{salt}--#{string}")
    end

    def make_salt
      secure_hash("#{Time.now.utc}--#{password}")
  开发者_C百科  end

    def secure_hash(string)
      Digest::SHA2.hexdigest(string)
    end

end

Any suggestions much appreciated!

--rick

PS -- per request. here is the create method:

def create

    @user = User.new(params[:user])

    respond_to do |format|
      if @user.save
        format.html { redirect_to(@user, :notice => 'User was successfully created.') }
        format.xml  { render :xml => @user, :status => :created, :location => @user }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @user.errors, :status => :unprocessable_entity }
      end
    end
  end

I was able to get the error message to go away by commenting out all validations in my model, but I will be adding them back one by one; so I still need to solve this bug....


This line in your User model:

validates :allow_nil => true, :presence => true, :on => :save

did not supply an attribute for validation. You may have meant to include those options on every validation listed below, but it's not how validates works.


I concur with jimworm. Validation doesn't run on new. It only runs before you attempt to save or call valid?. You need to just remove the line jimworm outlines.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜