有Rails列types的文档吗?

我正在寻找不仅仅是在这个页面上find的简单types列表:

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

但是有没有实际定义这些字段的文档?

特别:

  • 有什么区别:string:text
  • :float:decimal
  • 什么是:time:timestamp ,和:datetime :time的显着特点?

这些types的细微差别logging在任何地方?

编辑: DB平台的实现点与我试图问的问题无关。 如果说:datetime在Rails文档中没有定义的意图的含义,那么在select相应的列types时,db-adapter-writers会怎样?

从个人经验build立的指导方针

  • string
    • 限制为255个字符(取决于DBMS)
    • 用于短文本字段(名称,电子邮件等)
  • 文本
    • 无限长度(取决于DBMS)
    • 用于评论,博客文章等一般经验法则:如果它通过textarea捕获,使用文本。 对于使用文本字段的input,请使用string。
  • 整数
    • 整数
  • 浮动
    • 以浮点精度存储的十进制数字
    • 精确度是固定的,对于一些计算可能是有问题的; 由于四舍五入不准确,一般对math运算没有好处。
  • 十进制
    • 以精确度存储的十进制数字根据您的计算需要而变化; 使用这些math需要是准确的
    • 看到这个post的例子,并深入解释了浮动和小数之间的差异。
  • 布尔
    • 用来存储真/假的属性(即只有两个状态,如开/关)
  • 二进制
    • 用于将图像,电影和其他文件以其原始原始格式存储在称为斑点的数据块中
  • :首要的关键
    • 这个数据types是一个占位符,Rails可以转换成你select的数据库所需的任何主键数据types(即在PostgreSQL中的serial primary key )。 它的使用有些复杂,不推荐。
    • 使用模型和迁移约束(如validates_uniqueness_ofadd_index :unique => true选项),而不是在您自己的字段之一上模拟主键function。
  • date
    • 仅存储date(年,月,日)
  • 时间
    • 只存储一个时间(小时,分钟,秒)
  • date时间
    • 存储date和时间
  • 时间戳
    • 存储date和时间
    • 注意:出于Rails的目的,Timestamp和DateTime意味着相同的事情(使用两种types来存储date和时间)。 对于TL; DR描述为什么两者都存在,请阅读下面的段落。

这些是经常存在混淆的types; 我希望这有帮助。 我真的不知道为什么没有这些官方文件。 另外,我想这些数据库适配器是由编写Rails的人编写的,所以他们在编写适配器时可能不需要任何文档。 希望这可以帮助!

注意:我所能find的:DateTime:Timestamp都包含在Rails中,主要是为了与数据库系统兼容。 例如,MySQL的TIMESTAMP数据types被存储为一个unix时间戳。 它的有效范围从1970年到2038年,时间被存储为自上个纪元以来已经过去的秒数,这被认为是标准的,但实际上可能因系统而异。 认识到相对时间对于数据库来说不是一件好事,MySQL后来引入了DATETIME数据types,它以年增加的代价存储年,月,日,时,分和秒的每个数字。 为保持向后兼容,保留了TIMESTAMP数据types。 其他数据库系统也经历了类似的变化。 Rails认识到存在多种标准,并为两者提供接口。 但是,Rails ActiveRecord默认存储在MySql的DATETIME :Timestamp:DateTime到UTCdate,所以它对Rails程序员没有任何function上的区别。 这些存在使得希望区分两者的用户可以这样做。 (有关更深入的解释,请参阅此答案)。

从rails5.01源代码我发现:

  #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 

type_to_sql方法中的super

 #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