¿Existe documentación para los tipos de columna Rails?

181

Estoy buscando más que la simple lista de tipos que se encuentra en esta página :

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

¿Pero hay alguna documentación que realmente defina estos campos?

Específicamente:

  • ¿Cuál es la diferencia entre :stringy :text?
  • Entre :floaty :decimal?
  • ¿Cuáles son las características distintivas de :time, :timestampy :datetime?

¿Los matices de este tipo están documentados en alguna parte?

EDITAR: Los puntos de las implementaciones de la plataforma DB son irrelevantes para la pregunta que estoy tratando de hacer. Si, por ejemplo, :datetimeno tiene un significado intencionado definido en la documentación de Rails, ¿a qué recurren los escritores de adaptadores db al elegir el tipo de columna correspondiente?

Grant Birchmeier
fuente
1
¿Cuáles son esos tipos de, disculpe mi elección de palabras, cosas , llamadas? Como, ¿son campos o atributos o qué? Yo estaba buscando otras cosas que no sean :stringe :texty no pude encontrar ninguna que no sea esta. Entonces, me preguntaba para futuras referencias.
l1zZY
2
@ l1zZY, ​​el término que puede estar buscando es "tipos de datos".
thatpaintingelephant

Respuestas:

397

Pautas construidas a partir de la experiencia personal:

  • Cadena :
    • Limitado a 255 caracteres (dependiendo del DBMS)
    • Úselo para campos de texto cortos (nombres, correos electrónicos, etc.)
  • Texto :
    • Longitud ilimitada (según DBMS)
    • Úselo para comentarios, publicaciones de blog, etc. Regla general: si se captura a través de textarea, use Text. Para la entrada usando campos de texto, use cadena.
  • Entero :
    • Números enteros
  • Flotador :
    • Números decimales almacenados con precisión de coma flotante
    • La precisión es fija, lo que puede ser problemático para algunos cálculos; generalmente no es bueno para operaciones matemáticas debido al redondeo impreciso.
  • Decimal :
    • Números decimales almacenados con precisión que varía de acuerdo con lo que necesitan sus cálculos; úselos para las matemáticas que necesitan ser precisas
    • Vea esta publicación para ver ejemplos y una explicación detallada sobre las diferencias entre flotadores y decimales.
  • Booleano :
    • Se usa para almacenar atributos verdaderos / falsos (es decir, cosas que solo tienen dos estados, como activar / desactivar)
  • Binario :
    • Úselo para almacenar imágenes, películas y otros archivos en su formato original sin procesar en fragmentos de datos llamados blobs
  • :Clave primaria
    • Este tipo de datos es un marcador de posición que Rails traduce a cualquier tipo de datos de clave principal que requiera su base de datos de elección (es decir, serial primary keyen postgreSQL). Su uso es algo complicado y no recomendado.
    • Use restricciones de modelo y migración (como validates_uniqueness_ofy add_indexcon la :unique => trueopción) en su lugar para simular la funcionalidad de la clave principal en uno de sus propios campos.
  • Fecha :
    • Almacena solo una fecha (año, mes, día)
  • Tiempo :
    • Almacena solo un tiempo (horas, minutos, segundos)
  • DateTime :
    • Almacena tanto la fecha como la hora
  • Marca de tiempo
    • Almacena tanto la fecha como la hora
    • Nota: Para los fines de Rails, tanto la marca de tiempo como la fecha y hora significan lo mismo (use cualquier tipo para almacenar tanto la fecha como la hora). Para la descripción de TL; DR de por qué ambos existen, lea el párrafo inferior.

Estos son los tipos sobre los cuales a menudo existe confusión; Espero que esto ayude. Realmente no sé por qué no hay documentación oficial sobre estos. Además, me imagino que estos adaptadores de bases de datos a los que se refirió fueron escritos por las mismas personas que escribieron Rails, por lo que probablemente no necesitaban ninguna documentación cuando escribieron los adaptadores. ¡Espero que esto ayude!

Nota: la presencia de ambos :DateTimey :Timestamp, por lo que puedo encontrar, está incluida por Rails principalmente por compatibilidad con sistemas de bases de datos. Por ejemplo, el TIMESTAMPtipo de datos de MySQL se almacena como una marca de tiempo de Unix. Su rango válido va desde 1970 hasta 2038, y el tiempo se almacena como el número de segundos transcurridos desde la última época , que supuestamente es estándar, pero en la práctica puede diferir de un sistema a otro. Al reconocer que el tiempo relativo no era bueno para tener en las bases de datos, MySQL luego introdujo el DATETIMEtipo de datos, que almacena cada dígito en el año, mes, día, hora, minuto y segundo, a costa de un aumento de tamaño. losTIMESTAMPel tipo de datos se retuvo por compatibilidad con versiones anteriores. Otros sistemas de bases de datos pasaron por evoluciones similares. Rails reconoció que existían múltiples estándares y proporcionó interfaces para ambos. Sin embargo, los carriles de ActiveRecord por defecto tanto :Timestampy :DateTimehasta fechas UTC almacenados en MySQL DATETIME, por lo que no hace ninguna diferencia funcional a los programadores de Rieles. Estos existen para que los usuarios que deseen diferenciar entre los dos puedan hacerlo. (Para una explicación más detallada, vea esta respuesta SO).

revs aguazales
fuente
21
Esa es una crítica impresionante, @aguazales. Parece una gran omisión que la documentación de Rails no tenga algo como esto.
Grant Birchmeier
Gracias :) Y estoy completamente de acuerdo, ActiveRecord y sus tipos de datos son tan importantes para Rails, no sé por qué esto no es documentación estándar.
aguazales
2
El texto no siempre tiene una longitud ilimitada: en MySQL está limitado a unos 16 kb. Hay tipos de bases de datos MEDIUMTEXT y LONGTEXT si necesita más de 16 kb.
Haegin
3
Esta también es una buena fuente Tipos de datos de migración de Rails - MySql - Postgresql - SQLite . Sé que es específico de la base de datos, pero conocer la implementación real sigue siendo útil para comprender los tipos de bases de datos de rails.
Nate
1
No puedo estar 100% seguro, pero creo que el recurso de Nate se volvió a publicar aquí .
aguazales
10

Del código fuente de la rama maestra de Rails encontré:

resumen 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

el superen el type_to_sqlmétodo

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