ActiveRecord # save_only_valid_attributes
-
09-06-2019 - |
Question
Je cherche une variante de la méthode #save
qui ne fera que sauvegarder
attributs qui ne sont pas associés à des erreurs.
Ainsi, un modèle peut être mis à jour sans être valide dans son ensemble, ce qui
empêche toujours l'enregistrement de données non valides dans la base de données.
Par "attributs valides", j'entends les attributs qui donnent nil lors de l'appel de @ model_instance.errors.on (: attribut)
Quelqu'un a-t-il une idée de la manière de procéder?
Jusqu'à présent, j'ai les informations suivantes:
def save_valid_attributes
valid?
update_atrtibutes attributes.inject({}){|k, v, m| m[k] = v unless errors_on(k.to_sym); m}
end
Cela fonctionne s'il n'y a pas de traitement effectué sur l'affectation, ce qui est le cas dans mon cas. Par exemple, j'ai une colonne de base de données "start_date", et deux méthodes définies:
def nice_start_date=(startdate)
self.start_date = Chronic.parse(startdate) || startdate
end
def nice_start_date
self.start_date.to_s
end
Ces deux méthodes me permettent d'analyser correctement les dates saisies par l'utilisateur à l'aide de Chronic avant de sauvegarder. Donc, deuxième manière de faire ceci, un attribut à la fois:
def save_valid_attributes(attrib)
valid?
attrib.each{|(k,v)| send("${k}=", v); save; reload)
end
Le modèle doit être rechargé à chaque fois car, si l'une des dates est invalide et n'enregistre pas, cela empêchera l'enregistrement de tous les autres attributs.
Y a-t-il une meilleure façon de faire cela? Je suis sûr que ce n'est pas un problème rare dans le monde Rails, je n'arrive pas à trouver quoi que ce soit dans l'univers des connaissances de Google.
La solution
Je ne suis pas sûr de la chance que vous aurez avec cela sans beaucoup de déconner.
Peu importe la façon dont DRY et OO et votre infrastructure facilitent les choses (ce qui est dans ce cas - beaucoup =), vous devez toujours vous rappeler qu'elle s'exécute devant une base de données relationnelle standard, qui comporte des commits atomiques. définit les fonctionnalités . Il est conçu dès le départ pour vous assurer que toutes vos modifications sont validées ou aucune.
Vous allez effectivement utiliser cette fonctionnalité standard avec une fonctionnalité allant à 100% à l’encontre de la façon dont rails + a été conçu pour fonctionner. Ceci est susceptible de conduire (comme déjà dit) à des données incohérentes.
Cela dit. . . c'est toujours possible. Je regarderais dans les lignes de la validation manuelle des attributs qui vous intéressent, puis de la méthode intégrée object.update_attribute_with_validation_skipping.
Bonne chance!
Autres conseils
Vous pouvez écraser #save
comme ceci:
def save
errors.each do |attr, msg|
send("#{attr}=", send("#{attr}_was"))
end
super
end
Ceci réinitialisera tous les attributs avec des erreurs attachées à leur valeur d'origine.