首页 文章

是否有Rails列类型的文档?

提问于
浏览
168

我正在寻找的不仅仅是简单的类型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 的区别特征是什么?

这些类型的细微差别是否记录在何处?

编辑: Points of DB-platform implementations are irrelevant to the question I'm trying to ask. 如果,例如 :datetime 在Rails文档中没有明确的预期含义,那么db-adapter-writer在选择相应的列类型时会经历什么?

2 回答

  • 383

    根据个人经验 Build 的指南:

    • String

    • 限制为255个字符(取决于DBMS)

    • 用于短文本字段(名称,电子邮件等)

    • Text

    • 无限长度(取决于DBMS)

    • 用于评论,博客文章等 . 一般经验法则:如果通过textarea捕获,请使用文本 . 对于使用文本字段的输入,请使用字符串 .

    • Integer

    • 整数

    • Float

    • 以浮点精度存储的十进制数

    • 精度是固定的,对于某些计算可能会有问题;由于舍入不准确,通常对数学运算没有好处 .

    • Decimal

    • 以精度存储的十进制数,根据计算所需的内容而变化;将这些用于需要准确的数学

    • 请参阅this帖子以获取示例,并深入解释浮点数和小数位之间的差异 .

    • Boolean

    • 用于存储true / false属性(即只有两个状态的东西,如开/关)

    • Binary

    • 用于以原始的原始格式将图像,电影和其他文件存储在称为blob的数据块中

    • :primary_key

    • 此数据类型是占位符,Rails将转换为您选择的数据库所需的任何主键数据类型(即postgreSQL中的 serial primary key ) . 它的使用有点复杂,不推荐 .

    • 使用模型和迁移约束(如带有 :unique => true 选项的 validates_uniqueness_ofadd_index )来模拟您自己的某个字段上的主键功能 .

    • Date

    • 仅存储日期(年,月,日)

    • Time

    • 仅存储一个时间(小时,分钟,秒)

    • DateTime

    • 存储日期和时间

    • Timestamp

    • 存储日期和时间

    • 注意:出于Rails的目的,Timestamp和DateTime的含义相同(使用任一类型来存储日期和时间) . 对于TL; DR描述为什么两者都存在,请阅读底部段落 .

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

    注意:Rails包含 :DateTime:Timestamp 的存在,主要是为了与数据库系统兼容 . 例如,MySQL的 TIMESTAMP 数据类型存储为unix时间戳 . 它的有效范围从1970年到2038年,时间存储为自上次epoch以来经过的秒数,这应该是标准的,但实际上可能因系统而异 . 认识到相对时间在数据库中不是一件好事,MySQL后来引入了 DATETIME 数据类型,它以年度,月,日,小时,分钟和秒为单位存储每个数字,代价是增加了大小 . 保留了 TIMESTAMP 数据类型以实现向后兼容性 . 其他数据库系统经历了类似的演变 . Rails认识到存在多种标准,并为两者提供了接口 . 但是,Rails ActiveRecord默认存储在MySql的_1511558中的 :Timestamp:DateTime 到UTC日期,因此它对Rails程序员没有任何功能差异 . 这些存在使得希望区分两者的用户可以这样做 . (有关更深入的解释,请参阅this SO答案) .

  • 9

    从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 in 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
    

相关问题