web-dev-qa-db-fra.com

Rails Paperclip: mise à jour vs update_attributes

J'ai réalisé quelque chose d'assez étrange en essayant de télécharger une image via le bijou Paperclip pour mon modèle d'utilisateur (sous l'attribut avatar). Pour une raison quelconque, User.update et @ user.update_attributes se comportent différemment. Est-ce que quelqu'un sait pourquoi il en est ainsi?

#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

Et voici mes paramètres forts dans le user_controller.rb

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

MISE À JOUR

Donc, après avoir reçu des réponses rapides et impressionnantes, voici ce que j'ai appris:

User.update Renvoie l'objet résultant, qu'il ait été enregistré avec succès dans la base de données ou non. Par conséquent, User.update(@user.id, user_avatar_params) ne met pas à jour la variable @user si vous n'effectuez pas l'affectation. @user.update_attributes(user_avatar_params) modifie implicitement la variable @user.

La solution pour que cela fonctionne avec la méthode de mise à jour est de faire @user = User.update(@user.id, user_avatar_params)

24
Derrick Mar

ActiveRecord.update a un comportement qui peut vous décourager:

Met à jour un objet (ou plusieurs objets) et l'enregistre dans la base de données, si les validations réussissent. L'objet résultant est renvoyé, que l'objet ait été enregistré avec succès dans la base de données ou non. http://apidock.com/Rails/ActiveRecord/Base/update/class

Cependant, le update_attributes renverra simplement false.

Les deux utilisent des validations au niveau du modèle et les deux doivent donc enregistrer ou ne pas enregistrer de manière égale. Cependant, les valeurs de retour seront différentes.

Comme l'a souligné @RoaringStones, la solution consiste à utiliser

user = User.update(user.id, user_avatar_params)
19
aaron-coding

Pour ce que ça vaut, à partir de Rails 4.0.2, #update renvoie false si la mise à jour a échoué, pas simplement l'objet pour lequel la mise à jour a échoué. De plus, #update_attributes est simplement un alias de #update maintenant.

44
jamesconant

Au fait, #update_attributes va être déconseillé de Rails 6 (bien que ce ne soit pas encore publié)

s'il vous plaît jeter un oeil à

pour plus de détails.

11
itiskj