我正在寻找的不只是简单类型列表that is found on this page:
:primary_key,:string,:text,:integer,:float,:decimal,:datetime,:timestamp,:time,:date,:binary,:boolean
但是有没有文件实际定义这些字段?
具体做法是:
:string
和:text
之间的区别是什么?:float
和:decimal
之间?:time
,:timestamp
和:datetime
的区别特征是什么?这些类型的细微差别是否记录在哪里?
编辑:数据库平台实施的要点与我试图提出的问题无关。如果,:datetime
在Rails文档中没有明确的预期含义,那么db-adapter-writer在选择相应的列类型时会去做什么?
答案 0 :(得分:389)
根据个人经验制定的指南:
serial primary key
)。它的使用有点复杂,不推荐使用。validates_uniqueness_of
和add_index
与:unique => true
选项)来模拟您自己的某个字段上的主键功能。这些是经常存在混淆的类型;我希望这有帮助。我真的不知道为什么没有关于这些的官方文件。另外,我想你提到的这些数据库适配器是由编写Rails的人编写的,因此他们在编写适配器时可能不需要任何文档。希望这有帮助!
注意:Rails包含:DateTime
和:Timestamp
的存在,主要是为了与数据库系统兼容。例如,MySQL的TIMESTAMP
数据类型存储为unix时间戳。其有效范围从1970年到2038年,时间存储为自上一个epoch以来经过的秒数,这应该是标准的,但实际上可能因系统而异。认识到相对时间在数据库中不是一件好事,MySQL后来引入了DATETIME
数据类型,它存储了年,月,日,时,分和秒中的每个数字,代价是增加了数量。保留TIMESTAMP
数据类型是为了向后兼容。其他数据库系统经历了类似的演变。 Rails认识到存在多种标准,并为两者提供了接口。但是,Rails ActiveRecord将:Timestamp
和:DateTime
默认为存储在MySql的DATETIME
中的UTC日期,因此它对Rails程序员没有任何功能差异。这些存在使得希望区分两者的用户可以这样做。 (有关更深入的解释,请参阅this SO回答)。
答案 1 :(得分:9)
从Rails主分支源代码我发现:
#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
super
方法中的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