Apakah ada dokumentasi untuk jenis kolom Rails?

181

Saya mencari lebih dari sekadar daftar jenis sederhana yang ditemukan di halaman ini :

: primary_key,: string,: text,: integer,: float,: desimal,: datetime,: timestamp,: time,: date,: binary,: boolean

Tetapi apakah ada dokumentasi yang benar-benar mendefinisikan bidang-bidang ini?

Secara khusus:

  • Apa perbedaan antara :stringdan :text?
  • Antara :floatdan :decimal?
  • Apa saja fitur yang membedakan :time, :timestampdan :datetime?

Apakah nuansa jenis ini didokumentasikan di mana saja?

EDIT: Poin implementasi platform DB tidak relevan dengan pertanyaan yang saya coba tanyakan. Jika, katakanlah, :datetimetidak memiliki arti yang dimaksudkan dalam dokumentasi Rails, lalu apa yang penulis-penulis db lewati ketika memilih jenis kolom yang sesuai?

Berikan Birchmeier
sumber
1
Apa saja jenisnya, maafkan pilihan kata-kata, hal-hal yang saya sebut? Seperti, apakah bidang atau atribut atau apa. Saya mencari hal - hal lain selain :stringdan :textdan saya tidak dapat menemukan selain ini. Jadi, saya hanya ingin referensi di masa depan.
l1zZY
2
@ l1zZY, ​​istilah yang mungkin Anda cari adalah "tipe data."
thatpaintingelephant

Jawaban:

397

Pedoman yang dibangun dari pengalaman pribadi:

  • String :
    • Terbatas hingga 255 karakter (tergantung pada DBMS)
    • Gunakan untuk bidang teks pendek (nama, email, dll)
  • Teks :
    • Panjang tidak terbatas (tergantung pada DBMS)
    • Gunakan untuk komentar, posting blog, dll. Aturan umum: jika itu ditangkap melalui textarea, gunakan Teks. Untuk input menggunakan bidang teks, gunakan string.
  • Integer :
    • Angka keseluruhan
  • Mengapung :
    • Angka desimal disimpan dengan presisi titik mengambang
    • Presisi sudah diperbaiki, yang bisa menjadi masalah untuk beberapa perhitungan; umumnya tidak baik untuk operasi matematika karena pembulatan yang tidak akurat.
  • Desimal :
    • Angka desimal disimpan dengan presisi yang bervariasi sesuai dengan yang dibutuhkan oleh perhitungan Anda; gunakan ini untuk matematika yang perlu akurat
    • Lihat posting ini untuk contoh dan penjelasan mendalam tentang perbedaan antara mengapung dan desimal.
  • Boolean :
    • Gunakan untuk menyimpan atribut true / false (yaitu hal-hal yang hanya memiliki dua status, seperti hidup / mati)
  • Biner :
    • Gunakan untuk menyimpan gambar, film, dan file lain dalam format aslinya, dalam potongan data yang disebut gumpalan
  • :kunci utama
    • Datatype ini adalah placeholder yang diterjemahkan oleh Rails menjadi datatype kunci primer apa pun yang dibutuhkan oleh database pilihan Anda (yaitu serial primary keydalam postgreSQL). Penggunaannya agak rumit dan tidak dianjurkan.
    • Gunakan kendala model dan migrasi (suka validates_uniqueness_ofdan add_indexdengan :unique => trueopsi) sebagai gantinya untuk mensimulasikan fungsionalitas kunci utama pada salah satu bidang Anda sendiri.
  • Tanggal :
    • Hanya menyimpan tanggal (tahun, bulan, hari)
  • Waktu :
    • Hanya menyimpan waktu (jam, menit, detik)
  • DateTime :
    • Menyimpan tanggal dan waktu
  • Stempel waktu
    • Menyimpan tanggal dan waktu
    • Catatan: Untuk keperluan Rails, baik Timestamp dan DateTime memiliki arti yang sama (gunakan tipe apa pun untuk menyimpan tanggal dan waktu). Untuk deskripsi TL; DR mengapa keduanya ada, baca paragraf bawah.

Ini adalah tipe-tipe yang sering membingungkan; Saya harap ini membantu. Saya benar-benar tidak tahu mengapa tidak ada dokumentasi resmi tentang ini. Juga, saya bayangkan adaptor basis data yang Anda rujuk ini ditulis oleh orang yang sama yang menulis Rails, jadi mereka mungkin tidak memerlukan dokumentasi apa pun untuk digunakan ketika mereka menulis adaptor. Semoga ini membantu!

Catatan: keberadaan keduanya :DateTimedan :Timestamp, dari apa yang dapat saya temukan, disertakan oleh Rails sebagian besar untuk kompatibilitas dengan sistem basis data. Misalnya, TIMESTAMPtipe data MySQL disimpan sebagai cap waktu unix. Rentang validnya berlangsung dari 1970 hingga 2038, dan waktu disimpan sebagai jumlah detik yang telah berlalu sejak zaman terakhir , yang seharusnya standar, tetapi dalam praktiknya dapat berbeda dari satu sistem ke sistem lainnya. Menyadari bahwa waktu relatif bukan hal yang baik untuk dimiliki dalam basis data, MySQL kemudian memperkenalkan DATETIMEdatatype, yang menyimpan setiap digit pada tahun, bulan, hari, jam, menit dan detik, dengan biaya peningkatan ukuran. ItuTIMESTAMPdatatype dipertahankan untuk kompatibilitas ke belakang. Sistem basis data lainnya mengalami evolusi serupa. Rails mengakui bahwa ada beberapa standar, dan menyediakan antarmuka untuk keduanya. Namun, Rails ActiveRecord default baik :Timestampdan :DateTimeuntuk tanggal UTC disimpan dalam MySql ini DATETIME, sehingga tidak ada bedanya fungsional untuk Rails programmer. Ini ada sehingga pengguna yang ingin membedakan antara keduanya dapat melakukannya. (Untuk penjelasan yang lebih mendalam, lihat jawaban SO ini ).

rev aguazales
sumber
21
Itu adalah artikel yang bagus, @aguazales. Sepertinya pengawasan besar bahwa dokumentasi Rails tidak memiliki sesuatu seperti ini.
Berikan Birchmeier
Terima kasih :) Dan saya sepenuhnya setuju, ActiveRecord dan datatypes-nya sangat penting untuk Rails, idk mengapa ini bukan dokumentasi standar.
aguazales
2
Panjang teks tidak selalu tidak terbatas - di MySQL terbatas pada sekitar 16kb. Ada tipe database MEDIUMTEXT dan LONGTEXT jika Anda membutuhkan lebih dari 16kb.
Haegin
3
Ini juga merupakan sumber yang bagus Jenis Data Migrasi Rails - MySql - Postgresql - SQLite . Saya tahu itu basis data khusus tetapi mengetahui implementasi sebenarnya masih membantu ketika memahami jenis basis data rel.
Nate
1
Saya tidak bisa 100% yakin, tapi saya pikir sumber daya Nate diposkan ulang di sini .
aguazales
10

Dari kode sumber cabang master Rails saya menemukan:

abstrak mysql_adapter

#activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb

  NATIVE_DATABASE_TYPES = {
    primary_key: "bigint auto_increment PRIMARY KEY",
    string:      { name: "varchar", limit: 255 },
    text:        { name: "text", limit: 65535 },
    integer:     { name: "int", limit: 4 },
    float:       { name: "float" },
    decimal:     { name: "decimal" },
    datetime:    { name: "datetime" },
    timestamp:   { name: "timestamp" },
    time:        { name: "time" },
    date:        { name: "date" },
    binary:      { name: "blob", limit: 65535 },
    boolean:     { name: "tinyint", limit: 1 },
    json:        { name: "json" },
  }

  # Maps logical Rails types to MySQL-specific data types.
  def type_to_sql(type, limit = nil, precision = nil, scale = nil, unsigned = nil)
    sql = case type.to_s
    when 'integer'
      integer_to_sql(limit)
    when 'text'
      text_to_sql(limit)
    when 'blob'
      binary_to_sql(limit)
    when 'binary'
      if (0..0xfff) === limit
        "varbinary(#{limit})"
      else
        binary_to_sql(limit)
      end
    else
      super(type, limit, precision, scale)
    end

    sql << ' unsigned' if unsigned && type != :primary_key
    sql
  end    

# and integer ...

  def integer_to_sql(limit) # :nodoc:
    case limit
    when 1; 'tinyint'
    when 2; 'smallint'
    when 3; 'mediumint'
    when nil, 4; 'int'
    when 5..8; 'bigint'
    else raise(ActiveRecordError, "No integer type has byte size #{limit}")
    end
  end

 # and text ..

  def text_to_sql(limit) # :nodoc:
    case limit
    when 0..0xff;               'tinytext'
    when nil, 0x100..0xffff;    'text'
    when 0x10000..0xffffff;     'mediumtext'
    when 0x1000000..0xffffffff; 'longtext'
    else raise(ActiveRecordError, "No text type has byte length #{limit}")
    end
  end

# and binary ...

    def binary_to_sql(limit) # :nodoc:
      case limit
      when 0..0xff;               "tinyblob"
      when nil, 0x100..0xffff;    "blob"
      when 0x10000..0xffffff;     "mediumblob"
      when 0x1000000..0xffffffff; "longblob"
      else raise(ActiveRecordError, "No binary type has byte length #{limit}")
      end
    end

yang superdi type_to_sqlmetode

#activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
  def type_to_sql(type, limit = nil, precision = nil, scale = nil) #:nodoc:
    type = type.to_sym if type
    if native = native_database_types[type]
      column_type_sql = (native.is_a?(Hash) ? native[:name] : native).dup

      if type == :decimal # ignore limit, use precision and scale
        scale ||= native[:scale]

        if precision ||= native[:precision]
          if scale
            column_type_sql << "(#{precision},#{scale})"
          else
            column_type_sql << "(#{precision})"
          end
        elsif scale
          raise ArgumentError, "Error adding decimal column: precision cannot be empty if scale is specified"
        end

      elsif [:datetime, :time].include?(type) && precision ||= native[:precision]
        if (0..6) === precision
          column_type_sql << "(#{precision})"
        else
          raise(ActiveRecordError, "No #{native[:name]} type has precision of #{precision}. The allowed range of precision is from 0 to 6")
        end
      elsif (type != :primary_key) && (limit ||= native.is_a?(Hash) && native[:limit])
        column_type_sql << "(#{limit})"
      end

      column_type_sql
    else
      type.to_s
    end
  end
Fangxing
sumber