2008-09-17 14 views
0

Je recherche une variante de la méthode #save qui ne sauvegarde que les attributs auxquels aucune erreur n'est associée. Ainsi, un modèle peut être mis à jour sans être globalement valide, et cela permettra d'éviter l'enregistrement de données invalides dans la base de données.ActiveRecord # save_only_valid_attributes

Par « attributs valides », je veux dire les attributs qui donnent nul lors de l'appel @ model_instance.errors.on (: attribut)

Quelqu'un a une idée de comment y parvenir?

, j'ai Jusqu'à présent, les éléments suivants:

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 fait en mission, qui dans mon cas il y a. Par exemple, j'ai une colonne de base de données « date_début », 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 permettent de me analyser correctement l'utilisateur dates entrés à l'aide chronique avant d'enregistrer. Ainsi, la deuxième façon de le faire, 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 puisque, si l'une des dates est invalide et ne sauve pas, il empêchera tous les autres attributs de sauver.

Y a-t-il une meilleure façon de procéder? Je suis sûr que ce n'est pas un problème rare dans le monde de Rails, je n'arrive pas à trouver quelque chose dans l'univers de la connaissance de Google.

Répondre

0

Je ne sais pas quelle chance vous aurez avec ceci sans beaucoup de déconner.

Peu importe comment DRY et OO et facile votre cadre rend les choses (ce qui est dans ce cas - alot =), vous devez toujours vous rappeler qu'il fonctionne en face d'une base de données relationnelle bog-standard, qui a atomique commits l'un de ses définitcaractéristiques. Il est conçu à partir de zéro pour s'assurer que tous vos changements sont validés, ou aucun.

Vous allez effectivement dépasser cette fonctionnalité standard avec quelque chose qui va à l'encontre de la façon dont les rails + ont été conçus pour fonctionner. Ceci est susceptible de conduire (comme déjà dit) à des données incohérentes.

Cela dit. . . c'est toujours possible. Je chercherais à faire la validation manuelle des attributs qui vous intéressent, puis en utilisant la méthode intégrée object.update_attribute_with_validation_skipping.

Bonne chance!

0

Vous pouvez écraser #save comme ceci:

def save 
    errors.each do |attr, msg| 
    send("#{attr}=", send("#{attr}_was")) 
    end 
    super 
end 

Ceci permet de réinitialiser tous les attributs avec des erreurs attachées à leur valeur d'origine.