Existe-t-il une documentation pour les types de colonnes Rails?

183

Je recherche plus que la simple liste de types qui se trouve sur cette page :

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

Mais existe-t-il une documentation qui définit réellement ces champs?

Plus précisément:

  • Quelle est la différence entre :stringet :text?
  • Entre :floatet :decimal?
  • Quelles sont les caractéristiques distinctives de :time, :timestampet :datetime?

Les nuances de ces types sont-elles documentées quelque part?

EDIT: Les points des implémentations de la plate-forme DB ne sont pas pertinents pour la question que j'essaie de poser. Si, par exemple, :datetimen'a pas de signification définie dans la documentation de Rails, que se passe-t-il par db-adapter-writers lors du choix d'un type de colonne correspondant?

Grant Birchmeier
la source
1
Quels sont ces types de, excusez mon choix de mots, de choses , appelés? Comme, sont-ils des champs ou des attributs ou quoi. Je cherchais autre chose que :stringet :textet je ne pouvais pas trouver autre chose que cela. Donc, je me demandais juste pour référence future.
l1zZY
2
@ l1zZY, ​​le terme que vous recherchez peut-être est "types de données".
thatpaintingelephant

Réponses:

399

Lignes directrices fondées sur l'expérience personnelle:

  • Chaîne :
    • Limité à 255 caractères (selon le SGBD)
    • Utiliser pour les champs de texte courts (noms, e-mails, etc.)
  • Texte :
    • Longueur illimitée (selon le SGBD)
    • Utilisez pour les commentaires, les articles de blog, etc. Pour la saisie à l'aide de champs de texte, utilisez une chaîne.
  • Entier :
    • Nombres entiers
  • Flotteur :
    • Nombres décimaux stockés avec une précision en virgule flottante
    • La précision est fixe, ce qui peut être problématique pour certains calculs; généralement pas bon pour les opérations mathématiques en raison d'un arrondi inexact.
  • Décimal :
    • Nombres décimaux stockés avec une précision qui varie en fonction de ce dont vos calculs ont besoin; utilisez-les pour les mathématiques qui doivent être précises
    • Voir cet article pour des exemples et une explication approfondie sur les différences entre les flottants et les décimales.
  • Booléen :
    • Utilisez pour stocker des attributs vrai / faux (c'est-à-dire des choses qui n'ont que deux états, comme on / off)
  • Binaire :
    • Permet de stocker des images, des films et d'autres fichiers dans leur format brut d'origine en blocs de données appelés blobs
  • :clé primaire
    • Ce type de données est un espace réservé que Rails traduit dans le type de données de clé primaire requis par votre base de données de choix (c'est- serial primary keyà- dire dans PostgreSQL). Son utilisation est quelque peu compliquée et déconseillée.
    • Utilisez plutôt des contraintes de modèle et de migration (comme validates_uniqueness_ofet add_indexavec l' :unique => trueoption) pour simuler la fonctionnalité de clé primaire sur l'un de vos propres champs.
  • Date :
    • Stocke uniquement une date (année, mois, jour)
  • Heure :
    • Stocke seulement une heure (heures, minutes, secondes)
  • DateHeure :
    • Stocke la date et l'heure
  • Horodatage
    • Stocke la date et l'heure
    • Remarque: pour les besoins de Rails, Timestamp et DateTime signifient la même chose (utilisez l'un ou l'autre type pour stocker la date et l'heure). Pour la description TL; DR des raisons pour lesquelles les deux existent, lisez le paragraphe du bas.

Ce sont les types au sujet desquels la confusion existe souvent; J'espère que ça aide. Je ne sais vraiment pas pourquoi il n'y a pas de documentation officielle à ce sujet. De plus, j'imagine que ces adaptateurs de base de données auxquels vous avez fait allusion ont été écrits par les mêmes personnes qui ont écrit Rails, donc ils n'avaient probablement pas besoin de documentation lorsqu'ils écrivaient les adaptateurs. J'espère que cela t'aides!

Remarque: la présence des deux :DateTimeet :Timestamp, d'après ce que je peux trouver, est incluse par Rails principalement pour la compatibilité avec les systèmes de base de données. Par exemple, le type de données de MySQL a été conservé pour une compatibilité ascendante. D'autres systèmes de bases de données ont connu des évolutions similaires. Rails a reconnu l'existence de plusieurs normes et a fourni des interfaces pour les deux. Cependant, Rails ActiveRecord utilise par défaut les deux et les dates UTC stockées dans MySql's , donc cela ne fait aucune différence fonctionnelle pour les programmeurs Rails. Celles-ci existent pour que les utilisateurs qui souhaitent différencier les deux puissent le faire. (Pour une explication plus approfondie, voir cette réponse SO).TIMESTAMP type données est stocké sous la forme d'un horodatage unix. Sa plage valide va de 1970 à 2038, et le temps est stocké comme le nombre de secondes qui se sont écoulées depuis la dernière époque , ce qui est censé être standard, mais en pratique peut différer d'un système à l'autre. Reconnaissant que le temps relatif n'était pas une bonne chose à avoir dans les bases de données, MySQL a ensuite introduit le DATETIMEtype de données, qui stocke chaque chiffre de l'année, du mois, du jour, de l'heure, de la minute et de la seconde, au prix d'une augmentation de taille. leTIMESTAMP:Timestamp:DateTimeDATETIME

aguazales
la source
21
C'est un article génial, @aguazales. Cela semble être un énorme oubli que la documentation Rails n'ait pas quelque chose comme ça.
Grant Birchmeier
Merci :) Et je suis tout à fait d'accord, ActiveRecord et ses types de données sont si importants pour Rails, idk pourquoi ce n'est pas une documentation standard.
jake
2
Le texte n'est pas toujours de longueur illimitée - dans MySQL, il est limité à environ 16 Ko. Il existe des types de base de données MEDIUMTEXT et LONGTEXT si vous avez besoin de plus de 16 Ko.
Haegin
3
C'est également une bonne source Types de données de migration Rails - MySql - Postgresql - SQLite . Je sais que c'est spécifique à la base de données, mais connaître la mise en œuvre réelle est toujours utile pour comprendre les types de bases de données de rails.
Nate
1
Je ne peux pas être sûr à 100%, mais je pense que la ressource de Nate a été republiée ici .
jake
11

À partir du code source de la branche principale de Rails, j'ai trouvé:

résumé 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 méthode superintype_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
crocs
la source