代码之家  ›  专栏  ›  技术社区  ›  Grant Birchmeier

有关于Rails列类型的文档吗?

  •  190
  • Grant Birchmeier  · 技术社区  · 14 年前

    我想要的不仅仅是简单的类型列表 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 ?

    这些类型的细微差别有记录吗?

    编辑: DB平台实现的要点与我想问的问题无关。 比如说, :日期时间 在Rails文档中没有定义的预期含义,那么db适配器编写器在选择相应的列类型时会遵循什么?

    3 回复  |  直到 14 年前
        1
  •  408
  •   jake    3 年前

    根据个人经验制定的指导方针:

    • 一串 以下为:
      • 限制为255个字符(取决于DBMS)
      • 用于短文本字段(姓名、电子邮件等)
    • 文本 以下为:
      • 无限制长度(取决于DBMS)
      • 用于评论、博客文章等。一般经验法则:如果是通过文本区域捕获的,请使用文本。对于使用文本字段的输入,请使用字符串。
    • 整数 以下为:
      • 整数
    • 浮动 以下为:
      • 以浮点精度存储的十进制数
      • 精度是固定的,这对于某些计算来说可能是有问题的;由于舍入不准确,通常对数学运算没有好处。
    • 十进制的 以下为:
      • 小数存储的精度根据您的计算需要而变化;用这些来计算需要精确的数学
      • 看见 this 张贴示例并深入解释浮点和小数之间的差异。
    • 布尔值 以下为:
      • 用于存储真/假属性(即只有两种状态的东西,如开/关)
    • 二进制的 以下为:
      • 用于将图像、电影和其他文件以原始原始格式存储在称为 斑点
    • :primary_key
      • 这个数据类型是一个占位符,Rails将其转换为您选择的数据库所需的任何主键数据类型(即。 serial primary key 在postgreSQL中)。它的使用有些复杂,不建议使用。
      • 使用模型和迁移约束(如 validates_uniqueness_of 和 add_index 与 :unique => true 选项),而不是在您自己的字段之一上模拟主键功能。
    • 日期 以下为:
      • 仅存储日期(年、月、日)
    • 时间 以下为:
      • 仅存储一个时间(小时、分钟、秒)
    • 日期时间 以下为:
      • 同时存储日期和时间
    • 时间戳
      • 同时存储日期和时间
      • 注意:就Rails而言,Timestamp和DateTime的含义相同(使用任一类型来存储日期和时间)。对于TL;DR描述为什么两者都存在,阅读底部段落。

    这些都是经常存在混淆的类型。我真的不知道为什么没有关于这些的官方文件。此外,我想您提到的这些数据库适配器是由编写Rails的同一个人编写的,所以他们在编写适配器时可能不需要任何文档。

    注:两者均存在 :DateTime 和 :Timestamp 据我所知,Rails主要是为了与数据库系统兼容而包含的。例如,MySQL的 TIMESTAMP 数据类型存储为unix时间戳。其有效范围从1970年到2038年,时间存储为自上次以来经过的秒数 epoch ,这被认为是标准的,但在实践中可能因系统而异。MySQL后来引入了 DATETIME 数据类型,自“1000-01-01 00:00:00”起以秒形式存储(从5.6.4起可选小数秒),以 size increase 这个 时间戳 为了向后兼容,保留了数据类型。其他数据库系统也经历了类似的演变。Rails认识到存在多种标准,并为这两种标准提供了接口。但是,Rails ActiveRecord默认 :时间戳 和 :日期时间 到存储在MySql中的UTC日期 日期时间 ,所以它对Rails程序员来说没有任何功能上的区别。这些存在使得 希望 要区分两者,可以这样做。(有关更深入的解释,请参阅 this SO回答)。

        2
  •  12
  •   Grant Birchmeier    6 年前

    从Rails主分支的源代码中,我发现:

    abstract 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
    

    这个 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
    
        3
  •  1
  •   Floyd    3 年前

    这些被称为“本机数据库类型”,并有文档记录 here 。要查看可用类型及其内部定义的列表,请单击Github上的 native_database_types method 找到哪里 NATIVE_DATABASE_TYPES 定义为(在撰写时, 本地数据库类型 已定义 here )。

    附言:尽管这个问题有很好的答案,但我还是贡献了我的答案,因为其他答案都没有提供到定期维护的文档的任何链接。虽然我很感激其他答案中的建议和代码片段,但有一个到正式文档的链接是有用的,而且更有可能反映最近的任何更改。