Gibt es Dokumentation für die Rails-Spaltentypen?

181

Ich suche mehr als die einfache Typauflistung , die auf dieser Seite zu finden ist :

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

Aber gibt es eine Dokumentation, die diese Felder tatsächlich definiert ?

Speziell:

  • Was ist der Unterschied zwischen :stringund :text?
  • Zwischen :floatund :decimal?
  • Was sind die Unterscheidungsmerkmale von :time, :timestampund :datetime?

Sind die Nuancen dieser Typen irgendwo dokumentiert?

BEARBEITEN: Punkte von DB-Plattform-Implementierungen sind für die Frage, die ich zu stellen versuche, irrelevant. Wenn beispielsweise :datetimein der Rails-Dokumentation keine definierte beabsichtigte Bedeutung vorliegt, wie gehen dann Datenbankadapter-Writer vor, wenn sie einen entsprechenden Spaltentyp auswählen?

Grant Birchmeier
quelle
1
Was sind diese Arten von, entschuldigen Sie meine Wortwahl, Dinge , genannt? Sind sie Felder oder Attribute oder was? Ich suchte nach anderen Dingen als :stringund :textund konnte nichts anderes finden. Also habe ich mich nur gefragt, ob ich später darauf zurückgreifen kann.
l1zZY
2
@ l1zZY, ​​der Begriff, den Sie möglicherweise suchen, ist "Datentypen".
Thatpaintingelephant

Antworten:

397

Richtlinien aus persönlicher Erfahrung:

  • String :
    • Begrenzt auf 255 Zeichen (abhängig von DBMS)
    • Verwendung für kurze Textfelder (Namen, E-Mails usw.)
  • Text :
    • Unbegrenzte Länge (abhängig von DBMS)
    • Verwendung für Kommentare, Blog-Beiträge usw. Allgemeine Faustregel: Wenn es über einen Textbereich erfasst wird, verwenden Sie Text. Verwenden Sie für die Eingabe über Textfelder eine Zeichenfolge.
  • Ganzzahl :
    • Ganze Zahlen
  • Float :
    • Mit Gleitkomma-Genauigkeit gespeicherte Dezimalzahlen
    • Die Präzision ist festgelegt, was für einige Berechnungen problematisch sein kann. Im Allgemeinen nicht gut für mathematische Operationen aufgrund ungenauer Rundungen.
  • Dezimal :
    • Dezimalzahlen werden mit einer Genauigkeit gespeichert, die je nach den Anforderungen Ihrer Berechnungen variiert. Verwenden Sie diese für Mathematik, die genau sein muss
    • In diesem Beitrag finden Sie Beispiele und eine ausführliche Erläuterung der Unterschiede zwischen Gleitkommazahlen und Dezimalstellen.
  • Boolescher Wert :
    • Verwenden Sie diese Option, um True / False-Attribute zu speichern (dh Dinge, die nur zwei Zustände haben, wie Ein / Aus).
  • Binär :
    • Verwenden Sie diese Option, um Bilder, Filme und andere Dateien in ihrem ursprünglichen Rohformat in Datenblöcken zu speichern, die als Blobs bezeichnet werden
  • :Primärschlüssel
    • Dieser Datentyp ist ein Platzhalter, den Rails in den Primärschlüssel-Datentyp übersetzt, den Ihre Datenbank Ihrer Wahl benötigt (dh serial primary keyin postgreSQL). Die Verwendung ist etwas kompliziert und wird nicht empfohlen.
    • Verwenden Sie stattdessen Modell- und Migrationsbeschränkungen (wie validates_uniqueness_ofund add_indexmit der :unique => trueOption), um die Primärschlüsselfunktionalität in einem Ihrer eigenen Felder zu simulieren.
  • Datum :
    • Speichert nur ein Datum (Jahr, Monat, Tag)
  • Zeit :
    • Speichert nur eine Zeit (Stunden, Minuten, Sekunden)
  • DateTime :
    • Speichert Datum und Uhrzeit
  • Zeitstempel
    • Speichert Datum und Uhrzeit
    • Hinweis: Für Rails bedeuten sowohl Timestamp als auch DateTime dasselbe (verwenden Sie einen der beiden Typen, um Datum und Uhrzeit zu speichern). Lesen Sie den unteren Absatz, um zu erfahren, warum beide existieren.

Dies sind die Typen, über die häufig Verwirrung herrscht; Ich hoffe das hilft. Ich weiß wirklich nicht, warum es dazu keine offizielle Dokumentation gibt. Ich stelle mir auch vor, dass diese Datenbankadapter, auf die Sie sich bezogen haben, von denselben Personen geschrieben wurden, die Rails geschrieben haben, sodass sie beim Schreiben der Adapter wahrscheinlich keine Dokumentation benötigten. Hoffe das hilft!

Hinweis: Das Vorhandensein von beiden :DateTimeund :Timestamp, soweit ich das beurteilen kann, wird von Rails hauptsächlich aus Gründen der Kompatibilität mit Datenbanksystemen berücksichtigt. Beispielsweise wird der TIMESTAMPDatentyp von MySQL als Unix-Zeitstempel gespeichert. Sein gültiger Bereich reicht von 1970 bis 2038, und die Zeit wird als die Anzahl der Sekunden gespeichert, die seit der letzten Epoche vergangen sind , was angeblich Standard ist, aber in der Praxis von System zu System unterschiedlich sein kann. MySQL erkannte, dass relative Zeit in Datenbanken nicht gut zu haben war, und führte später den DATETIMEDatentyp ein, der jede Ziffer in Jahr, Monat, Tag, Stunde, Minute und Sekunde auf Kosten einer Vergrößerung speichert. DasTIMESTAMPDer Datentyp wurde aus Gründen der Abwärtskompatibilität beibehalten. Andere Datenbanksysteme haben ähnliche Entwicklungen durchlaufen. Rails erkannte, dass mehrere Standards vorhanden waren, und stellte Schnittstellen zu beiden bereit. Allerdings Rails Activestandardwerte sowohl :Timestampund :DateTimezu UTC Daten in MySQL gespeichert DATETIME, so macht es keinen funktionalen Unterschied zu Rails Programmierer. Diese existieren, damit Benutzer, die zwischen den beiden unterscheiden möchten , dies tun können. (Eine ausführlichere Erklärung finden Sie in dieser SO-Antwort.)

aguazales
quelle
21
Das ist eine großartige Zusammenfassung, @aguazales. Es scheint ein großes Versehen zu sein, dass die Rails-Dokumentation so etwas nicht enthält.
Grant Birchmeier
Danke :) Und ich stimme vollkommen zu, ActiveRecord und seine Datentypen sind für Rails so wichtig, idk, warum dies keine Standarddokumentation ist.
Aguazales
2
Text ist nicht immer unbegrenzt lang - in MySQL ist er auf ungefähr 16 KB begrenzt. Es gibt MEDIUMTEXT- und LONGTEXT-Datenbanktypen, wenn Sie mehr als 16 KB benötigen.
Haegin
3
Dies ist auch eine gute Quelle für Rails-Migrationsdatentypen - MySql - Postgresql - SQLite . Ich weiß, dass es datenbankspezifisch ist, aber die tatsächliche Implementierung zu kennen, ist immer noch hilfreich, wenn Sie die Rails-Datenbanktypen verstehen.
Nate
1
Ich kann nicht 100% sicher sein, aber ich denke, Nates Ressource wurde hier neu veröffentlicht .
Aguazales
10

Aus dem Quellcode des Rails-Hauptzweigs habe ich Folgendes gefunden:

abstrakter 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

die superin- type_to_sqlMethode

#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
quelle