2017-11-24 1 views
3

Ich habe folgendes Accessormethode:Initialisieren beim ersten Zugriff

def self.database : DB::Database 
    if @@database.nil? 
    config = Utils.config["database"].as(Hash) 
    connection = [ 
     "postgres://#{config["user"]}:#{config["password"]}", 
     "@localhost/stats", 
    ].join 

    @@database = DB.open connection 
    else 
    @@database 
    end 
end 

, die eine DB::Database zurückzukehren garantiert. Ich bin nicht sicher, wie die Klassenvariable zu deklarieren:

class Daemon 
    @@database 

    def self.database : DB::Database 
    end 
end 

Ich bin mit ein paar Optionen, die von dem Compiler vorgestellt, aber die meisten Optionen Vorschläge nicht ergeben, die zu kompilieren:

  • @@database = uninitialized DB::Database compiliert, aber erfüllt nicht den nil? Test wie besprochen in this GitHub issue.
  • Es gibt keine Möglichkeit für mich, einen Platzhalter DB::Database einfach zu instanziieren.
  • Ich bin mir auch nicht sicher, wie Sie mit der Accessor-Funktion self.database initialisieren, obwohl das funktionieren würde und geben Sie die Art garantiert.

Wie kann die Klassenvariable richtig initialisiert werden? Jede Hilfe würde sehr geschätzt werden!


Diese Lösung funktioniert:

class Daemon 
    @@database = uninitialized DB::Database 

    def self.database : DB::Database 
    config = Utils.config["database"].as(Hash) 
    connection = [ 
     "postgres://#{config["user"]}:#{config["password"]}", 
     "@localhost/stats", 
    ].join 

    DB.open connection 
    end 

Das einzige Problem mit den Klassen Gutachter schreiben diese Art und Weise ist, dass ich Filedeskriptoren undichten beginnen würde - jedes Mal, wenn ich @@database zugreifen, ich öffne eine neue Verbindung zu dem Datenbank. Ich möchte @@database nur während des ersten Zugriffs initialisieren und einen Weg finden, um den Compiler damit glücklich zu machen, beginnend uninitialized.

Noch ärgerlicher:

class Daemon 
    @@database = uninitialized DB::Database 
    @@database_init = false 

    def self.database : DB::Database 
    if [email protected]@database_init 
     config = Utils.config["database"].as(Hash) 
     connection = [ 
     "postgres://#{config["user"]}:#{config["password"]}", 
     "@localhost/stats", 
     ].join 

     @@database = DB.open connection 
     @@database_init = true 
    end 

    @@database 
    end 
end 

Antwort

3

Sie können eine Klasse var nillable machen und bedingt einen Wert in einer Klassenmethode zuweisen:

class Daemon 
    @@database : DB::Database? 

    def self.database 
    @@database ||= begin 
     config = Utils.config["database"].as(Hash) 
     connection = [ 
     "postgres://#{config["user"]}:#{config["password"]}", 
     "@localhost/stats", 
     ].join 

     DB.open connection 
    end 
    end 
end 

Daemon.database.query "..." # => #<PG::ResultSet:0x103ea2b40 ...> 
+1

Beachten Sie, dass dies entspricht 'class_getter Datenbank tun .. Ende. – RX14

+0

Ich bin immer noch unsicher über die Deklaration der Klassenvariablen. Wenn ich es vollständig weglasse, beschwert sich der Compiler: "Kann den Typ der Klassenvariablen" @@ database "von Daemon nicht ableiten. Wenn ich es "nicht initialisiert" lasse, bekomme ich einen Fehler. Ich habe meinen Beitrag aktualisiert. –

+0

@JamesTaylor Entschuldigung, meine Schuld. Die Antwort wurde aktualisiert –

Verwandte Themen