dbrewster
dbrewster

Reputation: 693

ruby on rails undefined method 'valid' when using update

I am using the same commands that I previously used in successful projects but now I suddenly can't validate any updates to the object(in this case, User). Everything else works fine but any attempt to check my validations for an update results in this error-

'undefined method `valid?' for # '

It is finding successfully finding the user and if I skip the .valid? statement then it will update, just without checking any of my model validations. I recently switched from SQLite to PostgreSQL, I am not sure if that's giving me the problem. I am new to Ruby but I couldn't find anything on this specific problem.

Please let me know if I should include the entirety of my controller or any of my model but as my create works fine, I feel like all the relative code is just in this little section-

class UsersController < ApplicationController

def update
    @user = User.find(params[:id])
    puts "#Is this working???!! #{@user}" ///prints #Is this working???!! #<User:0x00000001f24468>
    @user = User.update(user_params)
    if @user.valid?
        redirect_to "/users/#{@user.id}"
    else
        flash[:errors] = @user.errors.full_messages
        redirect_to "/users/#{@user.id}/edit" 
    end
  end
 private
  def user_params
    params.require(:user).permit(:name, :email, :password)
  end

Upvotes: 0

Views: 666

Answers (3)

ActiveRecord update(id, attributes)

Updates an object (or multiple objects) and saves it to the database, if validations pass. The resulting object is returned whether the object was saved successfully to the database or not.

Then, you can do this checking if @user.update(user_params)

def update
  @user = User.find(params[:id]) # Find user
  if @user.update(user_params) # Update user if validations pass
      redirect_to "/users/#{@user.id}"
  else
      flash[:errors] = @user.errors.full_messages
      redirect_to "/users/#{@user.id}/edit" 
  end
end

Or, you can call the update method directly in your model class, but the first argument must be the user ID

User.update(params[:id], user_params)

Upvotes: 0

dbrewster
dbrewster

Reputation: 693

Thank you both for your quick answers. I was replying to tell you that I already tried that and it worked but did not validate. But as two of you told me the same thing, I decided to test it out again and the validations did indeed work this time so thank you (although I definitely have a user with an email of 'asdf' from last time).

Intestering enough, I found another answer although I have no idea why it worked. I added another puts statement after the update and realized my object had been converted to an array so I came up with this other (worse) alternative answer-

def update
    @user = User.find(params[:id])
    puts "#Is this working???!! #{@user}"
    @user = User.update(user_params)
    puts "#Is this working???!! #{@user}" ///prints #Is this working???!! [#<User id: 2, name: "James Dean", etc..>] 
    if @user[0].valid?
        redirect_to "/users/#{@user[0].id}"
    else
        flash[:errors] = @user[0].errors.full_messages
        redirect_to "/users/#{@user[0].id}/edit" 
    end
  end

Upvotes: 0

Mark
Mark

Reputation: 6455

Your problem is here:

@user = User.update(user_params)

If you put in your check after, you would see: #Is this working???!! true, which would ironically enough inform you that it's not working.

That's because User.update(user_params) returns true or false depending on whether it is successful or not. This means your @user object is now simply either true or false, which you can't call valid on.

If you want to handle successfully updating / failing to do so, try:

def update
  @user = User.find(params[:id])
  if @user.update(user_params)
    redirect_to "/users/#{@user.id}"
  else
    flash[:errors] = @user.errors.full_messages
    redirect_to "/users/#{@user.id}/edit" 
  end
end

Upvotes: 1

Related Questions