Ceci est probablement l'une des choses que tous les nouveaux utilisateurs découvrent les rails plus tôt ou ultérieurs. Je viens de réaliser que les rails mettent à jour tous les champs avec le mot-clé Serialize, sans vérifier si quelque chose a vraiment changé à l'intérieur. D'une manière qui est la chose sensible à faire pour le cadre générique. P>
mais y a-t-il un moyen de remplacer ce comportement? Si je peux garder une trace si les valeurs dans un champs sérialisées ont changé ou non, est-il un moyen de l'empêcher d'être poussé dans la déclaration de mise à jour? J'ai essayé d'utiliser "update_attributes" et limiter le hachage dans les domaines d'intérêt, mais les rails mettent toujours à jour tous les champs sérialisés. P>
suggestions? P>
6 Réponses :
Oui, ça me dérangeait aussi. C'est ce que j'ai fait pour les rails 2.3.14 (ou plus bas): puis dans votre contrôleur utilisez: p> ou définissez-le Dans votre modèle si vous n'attendez pas de modifications au champ sérialisé une fois créé (mais update_attribute (: Serialized_field => "Mettez à jour moi" fonctionne toujours!) P> class Model < ActiveRecord::Base
serialize :serialized_field
def no_serialize_update
true
end
end
Cela semble assez prometteur. Merci! Maintenant que je sais quoi remplacer, je pourrais faire cela (en conjonction avec Super) au lieu d'utiliser la méthode enchaînant, sauf indication contraire de prendre cette approche. Faites-moi savoir si vous voyez des problèmes si j'utilise simplement le remplacement + super.
J'ai essayé ça aussi, mais remarqué que cela n'a pas fonctionné. Le problème est que update_with_dirty est déjà chargé (via la chaîne d'origine) avant d'avoir la chance de le remplacer et d'utiliser super.
@TABrez: AVERTISSEMENT: J'avais un insecte étrange dans mon application que les gemmes ACTS-AS-VERHEED et ALLICK_ID NE ont créé un enregistrement dans ma base de données lorsqu'un modèle a été mis à jour. Il semblait que le rappel avant_update a cessé de fonctionner dans mes modèles. Cela m'a pris beaucoup de temps avant que je puisse le lier au code ci-dessus dans ma demande. Je l'ai supprimé maintenant. Pas sûr (encore) pourquoi cela s'est passé.
@Joris je viens d'ajouter une réponse qui explique votre problème
Voici une solution similaire pour les rails 3.1.3.
Mettez le code suivant dans Config / Initialiseurs / P>
ActiveRecord::Base.class_eval do class_attribute :no_serialize_update self.no_serialize_update = false end ActiveRecord::AttributeMethods::Dirty.class_eval do def update(*) if partial_updates? if self.no_serialize_update super(changed) else super(changed | (attributes.keys & self.class.serialized_attributes.keys)) end else super end end end
Cela fonctionne (essayé sur ROR 3.2.18). Avez-vous ajouté: def no_serialize_update true Terminez le modèle contenant le Serialize code> Vous souhaitez que vous ne soyez pas mis à jour par défaut?
J'ai couru dans ce problème aujourd'hui et j'ai fini par pirater mon propre sérieliseur avec un getter et un setter. D'abord, j'ai renommé le champ sur # {colonne} _raw code>, puis utilisé le code suivant dans le modèle (pour l'attribut
multimédia code> dans mon cas).
require 'json'
...
def media=(media)
self.media_raw = JSON.dump(media)
end
def media
JSON.parse(media_raw) if media_raw.present?
end
Solution géniale! Je serais intéressé d'entendre s'il y a des inconvénients, peut-être la performance? avoir à analyser le RAW à chaque fois?
Le problème avec la réponse de Joris est qu'il accroche à la chaîne Vous pouvez commencer par une chaîne comme celle-ci p> remarque que puisque vous ne pouvez pas modifier directement Malheureusement, cela vous permettra la chaîne suivante: p> SO update_with_foo est parti! p> Donc, sachant que alias_mesthod_chain code>, désactivant toutes les chaînes effectuées après (comme
update_with_callbacks code> qui explique les problèmes des déclencheurs non appelé). Je vais essayer de faire un diagramme pour faciliter la compréhension.
update_without_foo code> points sur
update_with_bar code> et
et
et
et
update_without_bar code> à
update_with_baz code> p>
update_with_bar code> par les travaux internes de
alias_method_chain code> vous Peut essayer de raccrocher dans la chaîne en ajoutant un nouveau lien (bar2) et appeler update_without_bar, donc: p>
alias_method_chain code> ne vous laissera pas redéfinir
_with code> méthodes Ma solution a été jusqu'à redéfinir
update_without_dirty code> et faire la sélection d'attribut là-bas. p> p>
Pas tout à fait une solution, mais une bonne solution de contournement dans de nombreux cas pour moi était simplement de déplacer la ou les colonnes sérialisées à un modèle associé - souvent, cela était en fait une bonne coupe sémantique de toute façon. P>