Esiste documentazione per i tipi di colonna Rails?


181

Sto cercando qualcosa di più del semplice elenco di tipi che si trova in questa pagina :

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

Ma c'è qualche documentazione che definisce effettivamente questi campi?

In particolare:

  • Qual è la differenza tra :stringe :text?
  • Tra :floate :decimal?
  • Quali sono le caratteristiche distintive di :time, :timestampe :datetime?

Le sfumature di questi tipi sono documentate ovunque?

EDIT: i punti delle implementazioni della piattaforma DB sono irrilevanti per la domanda che sto cercando di porre. Se, diciamo, :datetimenon ha un significato definito definito nella documentazione di Rails, allora cosa devono fare i writer-db quando scelgono un tipo di colonna corrispondente?


1
Quali sono questi tipi di, scusa la mia scelta di parole, cose , chiamate? Ad esempio, sono campi o attributi o cosa. Ero alla ricerca di altre cose diverse :stringe :textnon sono riuscito a trovare un altro che questo. Quindi, mi chiedevo solo riferimenti futuri.
1ZZY

2
@ l1zZY, ​​il termine che potresti cercare è "tipi di dati".
thatpaintingelephant

Risposte:


397

Linee guida basate sull'esperienza personale:

  • Stringa :
    • Limitato a 255 caratteri (a seconda del DBMS)
    • Utilizzare per campi di testo brevi (nomi, e-mail, ecc.)
  • Testo :
    • Lunghezza illimitata (a seconda del DBMS)
    • Utilizzare per commenti, post di blog, ecc. Regola generale: se viene acquisito tramite textarea, utilizzare Testo. Per l'input utilizzando i campi di testo, utilizzare string.
  • Intero :
    • Numeri interi
  • Galleggiante :
    • Numeri decimali memorizzati con precisione in virgola mobile
    • La precisione è fissa, il che può essere problematico per alcuni calcoli; generalmente non va bene per le operazioni matematiche a causa di arrotondamenti imprecisi.
  • Decimale :
    • Numeri decimali memorizzati con precisione che varia in base a ciò che è necessario per i tuoi calcoli; usali per la matematica che deve essere accurata
    • Vedi questo post per esempi e una spiegazione approfondita sulle differenze tra float e decimali.
  • Booleano :
    • Utilizzare per memorizzare gli attributi vero / falso (cioè cose che hanno solo due stati, come on / off)
  • Binario :
    • Utilizzare per archiviare immagini, filmati e altri file nel loro formato originale non elaborato in blocchi di dati chiamati BLOB
  • :chiave primaria
    • Questo tipo di dati è un segnaposto che Rails si traduce in qualsiasi tipo di dati chiave principale richiesto dal database preferito (ad esempio serial primary keyin postgreSQL). Il suo utilizzo è alquanto complicato e sconsigliato.
    • Utilizzare i vincoli di modello e migrazione (come validates_uniqueness_ofe add_indexcon l' :unique => trueopzione) invece di simulare la funzionalità della chiave primaria su uno dei propri campi.
  • Data :
    • Memorizza solo una data (anno, mese, giorno)
  • Tempo :
    • Memorizza solo un tempo (ore, minuti, secondi)
  • DateTime :
    • Memorizza sia la data che l'ora
  • timestamp
    • Memorizza sia la data che l'ora
    • Nota: ai fini di Rails, sia Timestamp che DateTime significano la stessa cosa (utilizzare uno dei due tipi per memorizzare sia la data che l'ora). Per la descrizione TL; DR del perché entrambi esistono, leggere il paragrafo in basso.

Questi sono i tipi su cui spesso esiste confusione; Spero che aiuti. Non so davvero perché non ci sia documentazione ufficiale su questi. Inoltre, immagino che questi adattatori di database a cui hai fatto riferimento siano stati scritti dalle stesse persone che hanno scritto Rails, quindi probabilmente non avevano bisogno di alcuna documentazione per passare mentre scrivevano gli adattatori. Spero che questo ti aiuti!

Nota: la presenza di entrambi :DateTimee :Timestamp, da quello che posso trovare, è inclusa da Rails principalmente per la compatibilità con i sistemi di database. Ad esempio, il TIMESTAMPtipo di dati di MySQL è memorizzato come un timestamp unix. La sua gamma valida va dal 1970 al 2038 e il tempo viene memorizzato come il numero di secondi trascorsi dall'ultima epoca , che è presumibilmente standard, ma in pratica può differire da sistema a sistema. Riconoscendo che il tempo relativo non era una buona cosa da avere nei database, MySQL ha successivamente introdotto il DATETIMEtipo di dati, che memorizza ogni cifra dell'anno, mese, giorno, ora, minuto e secondo, al costo di un aumento delle dimensioni. IlTIMESTAMPil tipo di dati è stato mantenuto per compatibilità con le versioni precedenti. Altri sistemi di database hanno subito evoluzioni simili. Rails ha riconosciuto l'esistenza di più standard e ha fornito interfacce per entrambi. Tuttavia, Rails ActiveRecord imposta automaticamente entrambe le date UTC memorizzate in MySql , quindi non fa alcuna differenza funzionale per i programmatori Rails. Esistono in modo che gli utenti che desiderano distinguere tra i due possano farlo. (Per una spiegazione più approfondita, vedere questa risposta SO).:Timestamp e:DateTimeDATETIME


21
Questo è un fantastico commento, @aguazales. Sembra una grande svista che la documentazione di Rails non abbia qualcosa del genere.
Concedi Birchmeier il

Grazie :) E sono completamente d'accordo, ActiveRecord e i suoi tipi di dati sono così importanti per Rails, anche perché non è una documentazione standard.
aguazales,

2
Il testo non è sempre di lunghezza illimitata - in MySQL è limitato a circa 16kb. Esistono tipi di database MEDIUMTEXT e LONGTEXT se hai bisogno di più di 16kb.
Haegin,

3
Questa è anche una buona fonte di tipi di dati di migrazione di Rails - MySql - Postgresql - SQLite . So che è specifico del database ma conoscere l'implementazione effettiva è ancora utile per comprendere i tipi di database di rails.
Nate,

1
Non posso esserne sicuro al 100%, ma penso che la risorsa di Nate sia stata ripubblicata qui .
aguazales,

10

Dal codice sorgente del ramo principale di Rails ho trovato:

abstract 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

la supera type_to_sqlmetodo

#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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.