C’è documentazione per i tipi di colonna Rails?

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

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

Ma c’è qualche documentazione che in realtà definisce questi campi?

In particolare:

  • Qual è la differenza tra :string e :text ?
  • Tra :float e :decimal ?
  • Quali sono le caratteristiche distintive di :time :timestamp e :datetime ?

Le sfumature di questi tipi sono documentate ovunque?

EDIT: I punti di implementazione della piattaforma DB sono irrilevanti rispetto alla domanda che sto cercando di porre. Se, ad esempio, :datetime non ha un significato definito nella documentazione di Rails, allora cosa passano i db-adapter-writers quando scelgono un tipo di colonna corrispondente?

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 (in base al DBMS)
    • Usa per commenti, post di blog, ecc. Regola generale: se viene catturato tramite textarea, usa Testo. Per l’inserimento usando i campi di testo, usa la stringa.
  • Intero :
    • Numeri interi
  • Float :
    • 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 quanto richiesto dai calcoli; usa questi 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 true / false (cioè cose che hanno solo due stati, come on / off)
  • Binario :
    • Utilizzare per memorizzare immagini, filmati e altri file nel loro formato originale grezzo in blocchi di dati chiamati blob
  • :chiave primaria
    • Questo tipo di dati è un segnaposto che Rails traduce in qualsiasi tipo di dati di chiave primaria richiesto dal database di scelta (ad es. serial primary key in postgreSQL). Il suo uso è alquanto complicato e non raccomandato.
    • Utilizza i vincoli di modello e migrazione (come validates_uniqueness_of e add_index con :unique => true option) per simulare la funzionalità della chiave primaria in uno dei tuoi campi.
  • Data :
    • Memorizza solo una data (anno, mese, giorno)
  • Tempo :
    • Memorizza solo un tempo (ore, minuti, secondi)
  • DateTime :
    • Memorizza data e ora
  • timestamp
    • Memorizza data e ora
    • Nota: ai fini di Rails, sia Timestamp che DateTime significano la stessa cosa (utilizzare entrambi i tipi per memorizzare sia la data che l’ora). Per la descrizione TL, DR del perché entrambi esistono, leggi il paragrafo in basso.

Questi sono i tipi su cui spesso confusione esiste; Spero che aiuti. Non so davvero perché non ci sia documentazione ufficiale su questi. Inoltre, immagino che questi adattatori di database a cui ti riferivi siano stati scritti dalle stesse persone che hanno scritto Rails, quindi probabilmente non avevano bisogno di alcuna documentazione da seguire quando stavano scrivendo gli adattatori. Spero che questo ti aiuti!

Nota: la presenza di entrambi :DateTime e :Timestamp , da quello che posso trovare, è incluso da Rails principalmente per compatibilità con i sistemi di database. Ad esempio, il datatype TIMESTAMP di MySQL è memorizzato come timestamp unix. Il suo range valido 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 in seguito ha introdotto il tipo di dati DATETIME , che memorizza ogni cifra dell’anno, mese, giorno, ora, minuto e secondo, al costo di un aumento di dimensioni. Il tipo di dati TIMESTAMP stato mantenuto per compatibilità con le versioni precedenti. Altri sistemi di database hanno subito simili evoluzioni. Rails ha riconosciuto l’esistenza di più standard e ha fornito interfacce per entrambi. Tuttavia, Rails ActiveRecord ha come valore predefinito sia :Timestamp e :DateTime alle date UTC memorizzate in MySql DATETIME , quindi non fa alcuna differenza funzionale ai programmatori di Rails. Esiste in modo che gli utenti che desiderano distinguere tra i due possano farlo. (Per una spiegazione più approfondita, vedere questa risposta SO).

Dal codice del ramo principale di Rails ho trovato:

mysql_adapter astratto

 #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 

il super nel metodo type_to_sql

 #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