Rails: modèle de mise à Jour de l'attribut, sans invoquer des rappels
J'ai un modèle Utilisateur qui a un :les crédits de l'attribut. Je veux un simple bouton qui va ajouter 5 pour l'utilisateur de crédits, à travers un parcours appelé "ajouter" et /utilisateurs/3/add voudrais ajouter 5 pour les crédits de l'utilisateur id = 3.
def add
@user = User.find(params[:id])
@user.credits += 5
redirect_to root_path
end
Qui est la partie pertinente de mon contrôleur. Le problème est, je ne veux pas appeler @user.enregistrer parce que j'ai un before_save rappel qui re-crypte de l'utilisateur mot de passe basé sur l'heure UTC actuelle. Je veux juste simplement ajouter 5 à l'attribut et d'éviter le rappel, je n'ai jamais cru une chose si simple peut être si dur.
EDIT:
J'ai changé le rappel :before_create,
voici mon nouveau code de contrôleur (partie):
def add
@user = User.find(params[:id])
@user.add_credits(5)
@user.save
flash[:success] = "Credits added!"
redirect_to root_path
end
et voici mon code dans le modèle:
def add_credits(num)
self.credits = num
end
EDIT 2:
Ok c'était un problème de validation qui a fait les modifications dans la section "MODIFIER" pas de travail, mais j'aurais quand même aimer une réponse à la question initiale de la mise à jour sans les rappels!
- J'ai fourni un lien avec une liste de méthodes qui ne déclenchent pas de rappels, et les deux Finbarr et j'ai suggéré à l'aide d'un conditionnel de rappel--quelles sont les autres solutions que vous recherchez?
Vous devez vous connecter pour publier un commentaire.
Rails 3.1 introduit
update_column
, qui est le même queupdate_attribute
, mais sans déclencher des validations ou des rappels:http://apidock.com/rails/ActiveRecord/Persistence/update_column
De mettre à jour plusieurs attributs sans rappels, vous pouvez utiliser update_all dans votre modèle de la manière suivante:
Si vous voulez vraiment vous pouvez même essayer même une update_columns méthode et mixin à votre enregistrement actif de la classe de base.
Pour mettre à jour un attribut, vous pouvez utiliser update_column. En outre, il ya quelques méthodes spécifiques que l'on peut trouver dans les rails guides http://guides.rubyonrails.org/active_record_callbacks.html#skipping-callbacks
Comme une réponse générale, dans les Rails 4 c'est une manière simple de mettre à jour les attributs sans déclencher les rappels:
Si vous avez besoin de mettre à jour plusieurs attributs sans déclenche les rappels:
Il y a d'autres options ici dans les Rails Guides si vous préférez, mais j'ai trouvé cette façon d'être le plus facile.
UPDATE "users" SET "credits" = $1, "updated_at" = $2 WHERE "users"."id" = $3 [["credits", 5], ["updated_at", "2017-04-01 21:34:52.746626"], ["id", 1]]
Je pense que vous devriez utiliser la méthode update_counters dans ce cas. L'utiliser comme ceci dans votre contrôleur de l'action:
Vous devriez être en mesure d'utiliser update_all pour éviter le déclenchement de rappels.
Je préfère mettre cette logique dans le modèle, mais cela devrait fonctionner pour résoudre votre problème d'origine comme spécifié dans le contrôleur.
Quelques options pour la façon de faire dans rails4 http://edgeguides.rubyonrails.org/active_record_callbacks.html#skipping-callbacks
Pour mongoid, j'ai fini par utiliser http://mongoid.org/en/mongoid/docs/persistence.html
Plus précisément, vous pouvez utiliser:
et pas de rappel sera émis. Tellement cool.
Peut-être que vos before_save crochet doit vérifier si le mot de passe utilisateur a effectivement changé avant de le chiffrer de nouveau.
Vous avez un certain nombre d'options, y compris la modification de rappel que vous utilisez, par exemple,
after_create
.Vous pouvez mettre à jour les colonnes sans déclencher des rappels, voir Sauter Des Rappels dans l'AR du guide. Par exemple,
update_column
ne déclenche pour les rappels. Le lien précédent, les listes de non-déclenchement de fonctions.Vous pouvez également utiliser les Conditionnelle De Rappel formes (ou même un observateur) lorsque le mot de passe est modifié. Voir Activerecord::Sale, par exemple,
@user.password_changed?
.save!
pour voir si il y a une exception (et/ou vérifier les journaux, et/ou supprimer les traces silencieux).Vous pouvez mettre à jour une colonne faisant cela