Rails Paperclip:更新 vs. update_attributes

33
当我尝试使用paperclip gem为我的用户模型(在avatar属性下)上传图像时,我意识到一件非常奇怪的事情。出于某种原因,User.update和@user.update_attributes表现不同。是否有人知道为什么?
#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

这是我的user_controller.rb中的强参数

def user_avatar_params
  params.require(:user).permit(:avatar)
end

1
正如affinities所提到的,User.update返回基于其更新的记录的对象。因此,它基本上不是内存中用户变量指向的同一对象。 尝试:user = User.update(user.id,user_avatar_params),我相信在两种情况下你会得到相同的结果。顺便说一句,我认为'user.avatar_file_name.nil?'中的预期值应该是false,而不是true。 - Roaring Stones
感谢@RoaringStones的指出,我已经更正了这篇文章。是的,当我使用@user = User.update(user.id, user_avatar_params)时,它会打印false,正如我所预期的那样。 - Derrick Mar
3个回答

55

就目前而言,在Rails 4.0.2中,#update在更新失败时返回的不仅是更新失败的对象,而是返回false。值得进一步注意的是,#update_attributes现在只是#update的别名。


1
"就算只是这样",这个很有价值。我很高兴我继续往下滚动看到了更好的答案。 - Joshua Pinter
很高兴能帮到你 :) - jamesconant

23

ActiveRecord.update的行为可能会让您感到困惑:

更新一个对象(或多个对象)并将其保存到数据库中,如果验证通过。无论对象是否成功保存到数据库中,都将返回结果对象。 http://apidock.com/rails/ActiveRecord/Base/update/class

然而,update_attributes只会返回false

这两者都使用模型级别的验证,因此应该同等地保存或不保存。但是,它们的返回值将不同。

正如@RoaringStones所指出的那样,解决方法是使用:

user = User.update(user.id, user_avatar_params)

是的,我尝试在完全相同的情况下测试了这些。 - Derrick Mar

19

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接