Rails sütun tipleri için belgeler var mı?


181

Bu sayfada bulunan basit tip listesinden daha fazlasını arıyorum :

: birincil_anahtarı,: string,: metin,: tamsayı,: kayan nokta,: ondalık,: datetime,: zaman damgası,: zaman,: tarih,: ikili,: boolean

Ancak bu alanları gerçekten tanımlayan herhangi bir belge var mı?

özellikle:

  • Arasındaki fark nedir :stringve :text?
  • Arasında :floatve :decimal?
  • Ayırt edici özellikleri nelerdir :time, :timestampve :datetime?

Bu türlerin nüansları herhangi bir yerde belgeleniyor mu?

EDIT: DB-platform uygulama noktaları sormaya çalıştığım soru ile alakasız. Diyelim ki, :datetimeRails dokümantasyonunda tanımlı bir amaç yoksa, db-adaptor-yazarları karşılık gelen bir sütun tipi seçerken ne yapar?


1
Bu tür sözler nelerdir, sözlerimi, şeyleri seçmem bahane mi? Mesela, bunlar alanlar mı, nitelikler mi? Diğer arıyordu şeylerin dışında :stringve :textben bundan daha başka bulamadık. Bu yüzden, sadece gelecekteki referansı merak ediyordum.
l1zZY

2
@ l1zZY, ​​aradığınız terim "veri türleri" dir.
thatpaintingelephant

Yanıtlar:


397

Kişisel deneyimlerden yola çıkarak hazırlanan yönergeler:

  • Dize :
    • 255 karakterle sınırlıdır (DBMS'ye bağlı olarak)
    • Kısa metin alanları için kullanın (adlar, e-postalar, vb.)
  • Metin :
    • Sınırsız uzunluk (DBMS'ye bağlı olarak)
    • Yorumlar, blog gönderileri, vb. İçin kullanın. Genel kural: textarea ile yakalanmışsa, Metin kullanın. Metin alanlarını kullanarak giriş için dize kullanın.
  • Tamsayı :
    • Bütün sayılar
  • Şamandıra :
    • Kayan nokta hassasiyeti ile saklanan ondalık sayılar
    • Hassaslık sabittir, bu da bazı hesaplamalar için sorun yaratabilir; genellikle yanlış yuvarlama nedeniyle matematik işlemleri için iyi değildir.
  • Ondalık :
    • Hesaplamalarınız için neye ihtiyaç duyduğuna göre değişen, hassasiyetle saklanan ondalık sayılar; bunları doğru olması gereken matematik için kullanın
    • Bkz bu örnekler için yazı ve su baskını ve ondalık arasındaki farklar üzerine derinlemesine bir açıklama.
  • Boole :
    • Doğru / yanlış nitelikleri saklamak için kullanın (örneğin, açık / kapalı gibi yalnızca iki durumu olan şeyler)
  • İkili :
    • Görüntüleri, filmleri ve diğer dosyaları blob adı verilen veri yığınlarında orijinal, ham biçiminde depolamak için kullanın
  • :birincil anahtar
    • Bu veri türü, Rails'in seçtiğiniz veritabanının gerektirdiği birincil anahtar veri türüne (yani serial primary keypostgreSQL'de) dönüştüğü bir yer tutucudur . Kullanımı biraz karmaşıktır ve önerilmez.
    • Kullanım modeli ve (gibi göç kısıtlamaları validates_uniqueness_ofve add_indexbirlikte :unique => trueopsiyon) yerine kendi alanlarından birinde birincil anahtar işlevlerini taklit etmek.
  • Tarih :
    • Yalnızca bir tarihi (yıl, ay, gün) saklar
  • Zaman :
    • Yalnızca bir süre depolar (saat, dakika, saniye)
  • DateTime :
    • Hem tarihi hem de saati depolar
  • Zaman Damgası
    • Hem tarihi hem de saati depolar
    • Not: Rails amaçları için hem Zaman Damgası hem de DateTime aynı anlama gelir (hem tarihi hem de saati saklamak için her iki türü de kullanın). TL; DR neden her ikisinin de var olduğuna dair açıklama için alt paragrafı okuyun.

Bunlar genellikle karışıklığın olduğu türlerdir; Umarım bu yardımcı olur. Bunlar hakkında neden resmi belgeler olmadığını gerçekten bilmiyorum. Ayrıca, bahsettiğiniz bu veritabanı adaptörlerinin Rails yazan aynı kişiler tarafından yazıldığını hayal ediyorum, bu yüzden muhtemelen adaptörleri yazarken gitmek için herhangi bir belgeye ihtiyaç duymadılar. Bu yardımcı olur umarım!

Not: Her ikisinin varlığı :DateTimeve :Timestampbulabildiğim kadarıyla, Rails tarafından çoğunlukla veritabanı sistemleriyle uyumluluk için dahil edilmiştir. Örneğin, MySQL'in TIMESTAMPveri türü unix zaman damgası olarak saklanır. Geçerli aralığı 1970'den 2038'e kadar gider ve zaman, standart olduğu söylenen ancak pratikte sistemden sisteme değişebilen son çağdan bu yana geçen saniye sayısı olarak saklanır . Göreli zamanın veritabanlarında olması iyi bir şey olmadığını kabul eden MySQL daha sonra DATETIMEyıl, ay, gün, saat, dakika ve saniyedeki her rakamı bir boyut artışı pahasına saklayan veri tipini tanıttı . TIMESTAMPveri tipi geriye dönük uyumluluk için korunmuştur. Diğer veritabanı sistemleri de benzer evrim geçirdi. Rails, birden fazla standardın var olduğunu kabul etti ve her ikisine de arayüz sağladı. Ancak, Rails ActiveRecord varsayılan olarak MySql'lerde saklanan UTC tarihlerini :Timestampve :DateTimeUTC tarihlerini kullanır DATETIME, bu nedenle Rails programcıları için işlevsel bir fark oluşturmaz. Bunlar , ikisi arasında ayrım yapmak isteyen kullanıcıların bunu yapabilmesi için mevcuttur. (Daha ayrıntılı bir açıklama için bu SO cevabına bakınız ).


21
Bu harika bir yazı, @aguazales. Rails belgelerinin böyle bir şeye sahip olmadığı büyük bir gözetim gibi görünüyor.
Grant Birchmeier

Teşekkürler :) Ve tamamen katılıyorum, ActiveRecord ve veri türleri Rails için çok önemlidir, idk neden bu standart dokümantasyon değildir.
aguazales

2
Metin her zaman sınırsız uzunluk değildir - MySQL'de yaklaşık 16kb ile sınırlıdır. 16kb'den fazlasına ihtiyacınız varsa MEDIUMTEXT ve LONGTEXT veritabanı türleri vardır.
Haegin

3
Bu aynı zamanda iyi bir kaynaktır Rails Migration Veri Türleri - MySql - Postgresql - SQLite . Ben veritabanına özgü biliyorum ama raylar veritabanı türleri anlaşılırken gerçek uygulama bilmek hala yararlı.
Nate

1
% 100 emin olamıyorum, ama Nate'in kaynağının burada yayınlandığını düşünüyorum .
aguazales

10

Rails ana şube kaynak kodundan buldum:

soyut 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

superiçinde type_to_sqlyöntemi

#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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.