Rails Paperclip: update vs. update_attributes
Asked Answered
T

3

33

I realized something quite strange when attempting to upload an image via the paperclip gem for my user model (under the avatar attribute). For some reason there User.update and @user.update_attributes behaves differently. Does anyone know why this is so?

#using @user.update_attributes(user_avatar_params)
def update_profile_pic
    @user = User.find(params[:id])
    @user.update_attributes(user_avatar_params)
    puts @user.avatar_file_name.nil? # prints false as expected
    respond_to do |format|
      format.html { redirect_to :back }
      format.js
    end
end

#using User.update(@user.id, user_avatar_params)
def update_profile_pic
    @user = User.find(params[:id])
    User.update(@user.id, user_avatar_params)
    puts @user.avatar_file_name.nil? # prints true although successfully saves
    respond_to do |format|
      format.html { redirect_to :back }
      format.js
    end
end

And here is my strong params in the user_controller.rb

def user_avatar_params
  params.require(:user).permit(:avatar)
end
Trost answered 29/12, 2014 at 5:53 Comment(2)
As affinities mentioned User.update returns the object based on the record it updated. So it is basically not the same object in the memory that user var point to. Try: user = User.update(user.id, user_avatar_params) and I believe you will get the same results in both cases. BTW, I think expected value in 'user.avatar_file_name.nil?' should be false, not trueBeaudette
Thanks for the catch @RoaringStones. I have corrected the post. Yes when I use @user = User.update(user.id, user_avatar_params) it prints false as I expected.Trost
H
23

ActiveRecord.update has a behavior that may be throwing you off:

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. http://apidock.com/rails/ActiveRecord/Base/update/class

However the update_attributes will just return false.

Both of these use Model-level validations and so both should save or not save equally. However, the return values will be different.

As @RoaringStones pointed out, the solution is to use

user = User.update(user.id, user_avatar_params)
Horrify answered 29/12, 2014 at 6:22 Comment(1)
Yes I tried testing these in the exact same scenario.Trost
P
55

For what it's worth, as of Rails 4.0.2, #update returns false if the update failed, not simply the object which the update failed for. Of further note, #update_attributes is simply an alias of #update now.

Propeller answered 5/8, 2016 at 14:52 Comment(2)
"For what it's worth" This is worth a lot. I'm glad I scrolled down passed the accepted answer.Calcareous
Glad it helped :)Propeller
H
23

ActiveRecord.update has a behavior that may be throwing you off:

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. http://apidock.com/rails/ActiveRecord/Base/update/class

However the update_attributes will just return false.

Both of these use Model-level validations and so both should save or not save equally. However, the return values will be different.

As @RoaringStones pointed out, the solution is to use

user = User.update(user.id, user_avatar_params)
Horrify answered 29/12, 2014 at 6:22 Comment(1)
Yes I tried testing these in the exact same scenario.Trost
A
19

By the way, #update_attributes gonna be deprecated from Rails 6 (though this is not released yet)

please have a look at

for more details.

Authoritative answered 19/2, 2018 at 5:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.