2011-10-13 5 views
0

Je veux implémenter une méthode qui vérifie si l'instance d'un modèle n'a que des attributs nuls ou vides, sauf de son id ou de ses horodatages.Quelle est la meilleure façon de tester si une instance de modèle est "vide" dans Ruby on Rails?

J'ai fait usage d'une méthode auxiliaire qui supprime une clé de hachage et retourner le hachage restant (question 6227600)

class ActiveRecord::Base 
    def blank? 
     self.attributes.remove("id","created_at","updated_at").reject{|attr| self[attr].blank?}.empty? 
    end 
end 

je suppose qu'il peut y avoir beaucoup plus simple, efficace ou plus sûr de faire . Toute suggestion?

+0

Pourquoi vous voulez créer une instance vide? Créez simplement une instance lorsque vous avez des informations à renseigner. – megas

+0

Voulez-vous vérifier si un objet de modèle a été modifié? Par exemple, si un utilisateur n'a saisi aucun contenu, il n'aura pas changé. –

Répondre

1
def blank? 
    self.attributes.all?{|k,v| v.blank? || %w(id created_at updated_at).include?(k)} 
end 

Ma réponse est presque le même que Tadman a donné, mais exprimé de façon plus concise. Soyez prudent avec deux situations:

- ** blanc? ** n'est pas un bon choix comme nom, puisque si vous appelez ** object_a.object_b.blank? ** en essayant de savoir s'il y a ou non un object_b À l'intérieur de object_a, vous obtiendrez un vrai événement si l'objet existe. ** empty? ** semble un meilleur nom

- Si les bases de données définissent des valeurs par défaut, cela peut être difficile.

EDIT: Depuis construire un tableau chaque itération est lent (grâce Tadman), une solution Beter est:

def empty? 
    ignored_attrs = {'id' => 1, 'created_at' => 1, 'updated_at' => 1} 
    self.attributes.all?{|k,v| v.blank? || ignored_attrs[k]} 
end 
+0

Merci également pour l'observation sur le nom de la méthode. Je n'ai jamais trouvé l'objet # vide? très utile, mais en tout cas vous avez raison, il est préférable de ne pas surcharger les méthodes par défaut. –

+1

Déclarer le tableau en ligne à chaque fois dans la boucle crée une pénalité de performance significative. Vous devriez envisager de créer une constante contenant les attributs que vous préféreriez ignorer, ou mieux, de la transformer en un hachage de sorte que le test soit 'IGNORED_ATTRIBUTES [k]' au lieu de 'ARRAY.include? (K)' – tadman

+0

mais la performance n'était pas le point. Je vais éditer la réponse: D –

0

Vous pouvez simplement vérifier que toutes les propriétés du hachage attributes ne sont pas présents, ou l'inverse:

class ActiveRecord::Base 
    def blank? 
    !self.attributes.find do |key, value| 
     case (key) 
     when 'id', 'created_at', 'updated_at' 
     false 
     else 
     value.present? 
     end 
    end 
    end 
end 

Malheureusement, cela ne compte que les choses qui sont définies avec une default dans votre base de données, le cas échéant les clés de relation sont attribuées, entre autres choses. Vous devrez les ajouter en tant qu'exceptions ou comparer les valeurs à un état par défaut connu.

Ce genre de chose est probablement mieux implémenté au cas par cas.

+0

Merci tadman. Je ne peux accepter qu'une seule réponse et je choisis celle de Cibernox principalement parce que je préfère éviter les constats de cas. Cependant vous avez le crédit pour la première bonne réponse! –

+1

Vous devriez reconsidérer votre position, alors. 'case' est presque O (1) temps, où' Array # include? 'est O (N) temps. Même avec seulement quelques éléments dans la liste, 'case' surpasse d'un facteur cinq. – tadman

Questions connexes