2009-04-16 7 views
0

J'ai un modèle qui est généré en analysant un fichier de données. Il y a plusieurs valeurs intéressantes qui ne sont pas présentes dans le fichier de données d'origine mais qui peuvent être dérivées de celles qui le sont.Réglage paresseux des attributs du modèle dans Rails?

Cependant, beaucoup de ces valeurs dérivées sont chères à calculer, donc je voudrais les stocker dans la base de données une fois qu'elles ont été calculées.

J'ai essayé ceci:

def profit 
    if not self[:profit] 
    update_attribute :profit, expensive_computation 
    end 
    self[:profit] 
end 

Malheureusement, cela ne se fait la moitié du travail. La valeur calculée est stockée, mais chaque fois que j'appelle profit, elle calcule à nouveau la valeur.

MISE À JOUR:

Il s'avère que le problème n'a pas été dans la méthode, mais dans une déclaration find_by_sql plus tôt qui avait Rails confus au sujet des id des modèles. Le code j'ai fini avec était le suivant:

def profit 
    unless read_attribute(:profit) 
    update_attribute(:profit, expensive_computation) 
    self.save! 
    end 
    read_attribute(:profit) 
end 

Répondre

2

Vous créez une nouvelle méthode et de supprimer la logique de lecture de celui-ci. Peut-être quelque chose comme ça

def update_profit 
    update_attribute :profit, expensive_computation 
end 

De cette façon, vous pouvez séparer la logique de lecture et il suffit d'utiliser la méthode pour obtenir profit que rails vous donne.

@model.profit 

Où @model est une instance de quelque classe l'attribut profit est.

0

Lorsque le code devrait aller va dépendre du moment où il est possible de calculer le bénéfice (par exemple, dès que le dossier est d'abord sauvé, ou sera-t-il parfois plus tard?), et si le profit peut changer.

En général, il probablement préférable de mettre le calcul dans une sorte de before_create/before_save appel qu'il enregistre uniquement quand il est possible de calculer et/ou a changé

vrish88 est juste que vous devriez probablement quitter la profit seule, sauf si vous avez vraiment besoin de calculer cela à la volée, car les données sont nécessaires. Si c'est vraiment ce dont vous avez besoin, essayez:

def profit 
    update_attribute(:profit, expensive_computation) unless read_attribute(:profit) 

    read_attribute(:profit) 
end 
0

Cela fonctionne très bien pour moi. Ma première pensée est: avez-vous une faute de frappe dans la ligne if not self[:profit]?

0
def profit 
    super || update_attribute(:profit, expensive_computation) 
    return super 
end 

Si la colonne de profit a information, appelez simplement la méthode de profit d'origine de l'objet, ce qui renverrait le contenu de la colonne profit de la base de données.

Sinon, (à savoir la colonne profit a une valeur de nil) utiliser la méthode update_attribute pour calculer la valeur profit et stocker dans la base de données, alors il suffit de retourner de nouveau la valeur de la base de données.

Si vous préférez obtenir la valeur de profit si elle est déjà dans la base de données ou tout simplement true si le calcul coûteux a été exécuté, faites juste ceci (update_attribute renvoie true ou false):

def profit 
    super || update_attribute(:profit, expensive_computation) 
end 
Questions connexes