Je cherche 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 ces champs?
Plus précisément:
:string
et :text
?:float
et :decimal
?:time
, :timestamp
et :datetime
?Les nuances de ces types sont-elles documentées quelque part?
EDIT: Les points d'implémentations de la plate-forme DB ne sont pas pertinents pour la question que j'essaie de poser. Si, par exemple, :datetime
n'a pas une signification voulue dans la documentation Rails, à quoi sert db-adapter-writerers lors du choix du type de colonne correspondant?
Lignes directrices construites à partir de l'expérience personnelle:
serial primary key
dans PostgreSQL). Son utilisation est quelque peu compliquée et non recommandée.validates_uniqueness_of
et add_index
avec l'option :unique => true
) à la place pour simuler la fonctionnalité de clé primaire sur l'un de vos propres champs.Ce sont les types sur lesquels 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 les adaptateurs de base de données que vous avez mentionnés ont été écrits par les mêmes auteurs de Rails. Ils n'ont donc probablement pas besoin de documentation avant de les écrire. J'espère que cela t'aides!
Remarque: la présence de :DateTime
et de :Timestamp
, d'après ce que je peux trouver, est incluse dans Rails principalement pour des raisons de compatibilité avec les systèmes de base de données. Par exemple, le type de données TIMESTAMP
de MySQL est stocké sous la forme d'un horodatage Unix. Sa plage valide va de 1970 à 2038 et le temps est stocké sous forme de nombre de secondes écoulées depuis le dernier Epoch , ce qui est supposé être standard, mais peut en pratique 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 plus tard introduit le type de données DATETIME
, qui stocke chaque chiffre de l’année, du mois, du jour, de l’heure, des minutes et des secondes, au prix d’une augmentation de taille. . Le type de données TIMESTAMP
a été conservé pour des raisons de 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 aux deux. Cependant, Rails ActiveRecord utilise par défaut les dates :Timestamp
et :DateTime
vers les dates UTC stockées dans DATETIME
de MySql, de sorte que les programmeurs Rails ne font aucune différence fonctionnelle. . Celles-ci existent pour que les utilisateurs qui souhaitent différencier les deux puissent le faire. (Pour une explication plus détaillée, voir this SO answer).
De Rails code de la source de branche principale que j'ai trouvé:
#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 super
dans 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