2016-08-05 13 views
0

Ich habe eine Anwendung, die die Verwendung der Verschlüsselung für einige Felder in der Datenbank erfordert. Dies wird derzeit mit einem Problem implementiert, das die Feinheiten der Verschlüsselung und Verwaltung von Feldern in enthaltenen Klassen behandelt. Es ist wichtig, dass das System in der Lage ist, programmatisch zu bestimmen, welche Klassen dieses Problem beinhalten, aber noch spezifischer muss programmatisch ein guter Weg gefunden werden, um zu bestimmen, welche Felder verschlüsselt sind.Ruby Alternative zur Verwendung von Klassenvariablen in ActiveSupport :: Concern

Heute ist dies implementiert, arbeiten, Klassenvariablen wie folgt aus:

module EncryptedFields 

    extend ActiveSupport::Concern 

    included do 
     @@encrypted_attributes ||= {} 
     @@encrypted_attributes[self.to_s] ||= [] 

     def self.encrypted attribute, options={} 

      @@encrypted_attributes[self.to_s] << attribute 

      ### Other stuff 
     end 
    end 
end 

in einer Klasse enthalten sind, wie folgt aus:

class SomeEcryptedModel 

    include EncryptedFields 

    encrypted :field_name, options 
    encrypted :other_field_name, options 

    #etc 
end 

Die Klassenvariable @@encrypted_attributes korrekt einen Hash Schlüssel erfassen -Wert pairs mit dem einschließenden Klassennamen als Schlüssel und dem Array der verschlüsselten Attribute als Wert. Ich habe überlegt, ein Registrierungssystem für verschlüsselte Modelle zu verwenden, um sich selbst und ihre Attribute zu verwenden und zu "registrieren", aber es ist viel mehr Aufwand damit verbunden und auf meiner Zeitachse möchte ich mit etwas einfacherem beginnen, wenn es nicht zu unsicher ist .

Dies funktioniert eigentlich in meiner aktuellen Anwendung, aber ich habe nicht viel Erfahrung mit Bedenken oder Klassenvariablen, so bin ich besorgt darüber, ob ich eine ernsthafte Fehleinschätzung vorgenommen habe, wie dies sich verhalten wird. Wo sind die Fallstricke? Ich bin programmiert worden, seit ich angefangen habe, mit Ruby zu arbeiten (vor nicht allzu langer Zeit), dass Klassenvariablen im Allgemeinen vermieden werden sollten.

Ich wurde schon einmal davon gebissen, weil ich anfangs dachte, dass die Klassenvariable @@encrypted_attributes eine Klassenvariable auf der enthaltenen Klasse wäre; das war anscheinend nicht so. Jedes neue Modell, das es enthielt, würde es überschreiben, so dass ich zu der Schlussfolgerung kam, dass diese Klassenvariable offensichtlich auf der Sorge selbst lag. Zumindest ist dies das Verhalten, das ich zu beobachten scheint. Dies erwies sich am Ende als wünschenswertes Verhalten, da ich jetzt die vollständige Liste der verschlüsselten Modelle abrufen kann. Dies hat die offensichtliche Einschränkung, dass nur die Liste der verschlüsselten Modelle und Attribute für geladene Modelle zurückgegeben werden kann.

Also, meine Frage:

Ist dies ein richtiger Anwendungsfall für Klassenvariablen, oder gibt es eine Alternative (besser?) Weg, um diese gleichen Informationen zu erfassen? Wenn dies ein akzeptabler Klassenvariablen-Anwendungsfall ist, was sind einige der Fallstricke und/oder Schutzmaßnahmen, die ich hinzufügen sollte, um sicherzustellen, dass der Code so funktioniert, wie ich es beabsichtige?

Vielleicht versuche ich einfach zu clever zu sein und ich sollte einfach meine Liste hart codieren? Danke für die Hilfe!

Antwort

2

können Sie diesen Weg gehen alternativ zur Besorgnis Ansatz:

module EncryptedFields 
    @encrypted_attributes ||= {} 

    def self.included(klass) 
    @encrypted_attributes[klass.name] ||= [] 
    klass.extend(ClassMethods) 
    end 

    def self.add(class_name, attribute) 
    @encrypted_attributes[class_name] << attribute 
    end 

    module ClassMethods 
    def encrypted(attribute, options={}) 
     EncryptedFields.add(name, attribute) 
     # Other stuff 
    end 
    end 
end 

class Stuff 
    include EncryptedFields 

    encrypted :ololo 
    encrypted :new_name 
end 

EncryptedFields.instance_variable_get(:@encrypted_attributes) 
=> {"Stuff"=>[:ololo, :new_name]} 

Sie brauchen keine Klassenvariablen hier. Die Modulinstanzvariable ist ausreichend. Sie haben keine Vererbung, und Sie können keine Instanz des Moduls erstellen, so dass Sie immer nur einen einzigen Platz haben, an dem @encripted_attributes Variable definiert wird, und es wird Ihr EncriptedFields Modul sein.

Guter Artikel, den Unterschied zwischen Klassenvariablen und Klasseninstanzvariablen zu: http://www.railstips.org/blog/archives/2006/11/18/class-and-instance-variables-in-ruby/

+0

Dank. Dies war eine pädagogische Antwort. Ich habe meinen Code für die Frage vereinfacht, also funktioniert das vielleicht nicht genau, aber es hat mich dazu gebracht, in eine neue Richtung zu denken. – BoringJangles

Verwandte Themen