Existe documentação para os tipos de coluna Rails?

181

Estou procurando mais do que a lista de tipos simples encontrada nesta página :

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

Mas existe alguma documentação que realmente defina esses campos?

Especificamente:

  • Qual é a diferença entre :stringe :text?
  • Entre :floate :decimal?
  • Quais são as características distintivas :time, :timestampe :datetime?

As nuances desses tipos estão documentadas em algum lugar?

EDIT: Pontos de implementações da plataforma DB são irrelevantes para a pergunta que estou tentando fazer. Se, por exemplo, :datetimenão tem um significado pretendido definido na documentação do Rails, o que o db-adapter-writers passa ao escolher um tipo de coluna correspondente?

Grant Birchmeier
fonte
1
Como são esses tipos, desculpe minha escolha de palavras, coisas ? Como, são campos ou atributos ou o quê. Eu estava procurando por outras coisas além de :stringe :textnão consegui encontrar outra coisa além disso. Então, eu só estava pensando em referência futura.
L1zZY 12/07/2015
2
@ l1zZY, ​​o termo que você pode estar procurando é "tipos de dados".
thatpaintingelephant

Respostas:

397

Diretrizes criadas a partir da experiência pessoal:

  • String :
    • Limitado a 255 caracteres (dependendo do DBMS)
    • Use para campos de texto curtos (nomes, emails, etc)
  • Texto :
    • Duração ilimitada (dependendo do DBMS)
    • Use para comentários, postagens no blog, etc. Regra geral: se for capturada via área de texto, use Texto. Para entrada usando campos de texto, use string.
  • Inteiro :
    • Números inteiros
  • Flutuador :
    • Números decimais armazenados com precisão de ponto flutuante
    • A precisão é fixa, o que pode ser problemático para alguns cálculos; geralmente não é bom para operações matemáticas devido a arredondamentos imprecisos.
  • Decimal :
    • Números decimais armazenados com precisão que varia de acordo com o que é necessário em seus cálculos; use-os para matemática que precisa ser precisa
    • Veja este post para exemplos e uma explicação detalhada sobre as diferenças entre flutuadores e decimais.
  • Booleano :
    • Use para armazenar atributos verdadeiro / falso (ou seja, coisas que possuem apenas dois estados, como ativado / desativado)
  • Binário :
    • Use para armazenar imagens, filmes e outros arquivos em seu formato original e bruto em pedaços de dados chamados blobs
  • :chave primária
    • Esse tipo de dados é um espaço reservado que o Rails converte em qualquer tipo de dados da chave primária que seu banco de dados de escolha exigir ( serial primary keypor exemplo, no postgreSQL). Seu uso é um pouco complicado e não é recomendado.
    • Use restrições de modelo e migração (como validates_uniqueness_ofe add_indexcom a :unique => trueopção) para simular a funcionalidade da chave primária em um de seus próprios campos.
  • Data :
    • Armazena apenas uma data (ano, mês, dia)
  • Hora :
    • Armazena apenas um tempo (horas, minutos, segundos)
  • DateTime :
    • Armazena data e hora
  • Registro de data e hora
    • Armazena data e hora
    • Nota: Para os propósitos do Rails, Timestamp e DateTime significam a mesma coisa (use um dos tipos para armazenar data e hora). Para a descrição TL; DR de por que ambos existem, leia o parágrafo inferior.

Esses são os tipos sobre os quais freqüentemente existe confusão; Eu espero que isso ajude. Realmente não sei por que não há documentação oficial sobre isso. Além disso, imagino que esses adaptadores de banco de dados aos quais você se referiu foram escritos pelas mesmas pessoas que escreveram o Rails, portanto eles provavelmente não precisavam de nenhuma documentação para escrever quando estavam escrevendo os adaptadores. Espero que isto ajude!

Nota: a presença de ambos :DateTimee :Timestamp, pelo que posso encontrar, é incluída pelo Rails principalmente para compatibilidade com sistemas de banco de dados. Por exemplo, o TIMESTAMPtipo de dados do MySQL é armazenado como um carimbo de data / hora unix. Seu intervalo válido vai de 1970 a 2038 e o tempo é armazenado como o número de segundos decorridos desde a última época , o que é supostamente padrão, mas na prática pode diferir de sistema para sistema. Reconhecendo que o tempo relativo não era bom nos bancos de dados, o MySQL posteriormente introduziu o DATETIMEtipo de dados, que armazena todos os dígitos no ano, mês, dia, hora, minuto e segundo, ao custo de um aumento de tamanho. oTIMESTAMPo tipo de dados foi retido para compatibilidade com versões anteriores. Outros sistemas de banco de dados passaram por evoluções semelhantes. O Rails reconheceu a existência de vários padrões e forneceu interfaces para ambos. No entanto, Rails ActiveRecord padrões tanto :Timestampe :DateTimea UTC datas armazenadas em MySql de DATETIME, por isso não faz diferença funcional para os programadores Rails. Eles existem para que os usuários que desejam diferenciar os dois possam fazê-lo. (Para uma explicação mais aprofundada, consulte esta resposta do SO).

aguazales
fonte
21
Esse é um artigo incrível, @aguazales. Parece uma supervisão enorme que a documentação do Rails não tenha algo assim.
Grant Birchmeier
Obrigado :) E eu concordo plenamente, o ActiveRecord e seus tipos de dados são tão importantes para o Rails, não sei por que essa documentação não é padrão.
Aguazales 13/08/2012
2
O texto nem sempre é de tamanho ilimitado - no MySQL é limitado a cerca de 16kb. Existem tipos de banco de dados MEDIUMTEXT e LONGTEXT, se você precisar de mais de 16kb.
Haegin
3
Essa também é uma boa fonte de tipos de dados de migração do Rails - MySql - Postgresql - SQLite . Eu sei que é específico do banco de dados, mas saber a implementação real ainda é útil ao entender os tipos de banco de dados do Rails.
Nate
1
Não tenho 100% de certeza, mas acho que o recurso de Nate foi republicado aqui .
Aguazales 24/08/19
10

No código-fonte da filial principal do Rails, encontrei:

resumo 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

o superno 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
fonte