Saya memiliki metode pengakses berikut:

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

Yang dijamin akan mengembalikan DB::Database. Saya tidak yakin bagaimana mendeklarasikan variabel kelas:

class Daemon
  @@database

  def self.database : DB::Database
  end
end

Saya disajikan dengan beberapa opsi oleh kompiler, tetapi sebagian besar opsi tidak menghasilkan saran yang dikompilasi:

  • @@database = uninitialized DB::Database dikompilasi, tetapi tidak lulus uji nil? seperti yang dibahas dalam masalah GitHub ini.
  • Tidak ada cara bagi saya untuk membuat instance placeholder DB::Database dengan mudah.
  • Saya juga tidak yakin bagaimana menginisialisasi menggunakan fungsi pengakses self.database, meskipun itu akan berhasil dan memberikan jaminan jenis.

Bagaimana cara menginisialisasi variabel kelas dengan benar? Bantuan apa pun akan sangat dihargai!


Solusi ini berfungsi:

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

Satu-satunya masalah dengan menulis penilai kelas dengan cara ini adalah bahwa saya akan mulai membocorkan deskriptor file — setiap kali saya mengakses @@database, saya membuka koneksi baru ke database. Saya ingin menginisialisasi @@database hanya selama akses pertama dan mencari cara untuk membuat kompiler senang dengan memulai uninitialized.

Lebih menyebalkan lagi:

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

  def self.database : DB::Database
    if !@@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
4
James Taylor 24 November 2017, 08:26

1 menjawab

Jawaban Terbaik

You can make a class var nillable and conditionally assign a value in a class method:

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 ...>
3
Vitalii Elenhaupt 26 November 2017, 18:25