185

私はこのページにある単純なタイプのリスト以上のものを探しています:

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

しかし、これらのフィールドを実際に定義するドキュメントはありますか?

具体的には:

  • :stringとの違いは何:textですか?
  • :floatとの間:decimal
  • :time、、、:timestampおよびの際立った特徴は何:datetimeですか?

これらのタイプのニュアンスはどこかに文書化されていますか?

編集:DBプラットフォームの実装のポイントは、私が尋ねようとしている質問とは無関係です。 たとえば、:datetimeRailsのドキュメントで意図された意味が定義されていない場合、対応する列タイプを選択するときにdb-adapter-writersは何を実行しますか?

4

2 に答える 2

401

個人的な経験から構築されたガイドライン:

  • 文字列
  • 255文字に制限されています(DBMSによって異なります)
  • 短いテキストフィールド(名前、電子メールなど)に使用します
  • テキスト
  • 無制限の長さ(DBMSによって異なります)
  • コメント、ブログ投稿などに使用します。一般的な経験則:textareaを介してキャプチャされる場合は、Textを使用します。テキストフィールドを使用した入力には、文字列を使用します。
  • 整数
  • 整数
  • フロート
  • 浮動小数点精度で格納された10進数
  • 精度は固定されており、一部の計算では問題になる可能性があります。丸めが不正確であるため、通常、数学演算には適していません。
  • 10進数:
  • 計算に必要なものに応じて変化する精度で格納された10進数。正確である必要がある数学のためにこれらを使用してください
  • 例と浮動小数点数と小数の違いに関する詳細な説明については、この投稿を参照してください。
  • ブール値
  • 真/偽の属性(つまり、オン/オフのように2つの状態しかないもの)を格納するために使用します
  • バイナリ
  • 画像、動画、その他のファイルを元の生の形式でblobと呼ばれるデータのチャンクに保存するために使用します
  • :primary_key
  • このデータ型は、Railsが選択したデータベース(つまりserial primary keypostgreSQL)に必要な主キーデータ型に変換するプレースホルダーです。その使用はやや複雑であり、お勧めできません。
  • 代わりに、モデルと移行の制約(validates_uniqueness_ofおよびオプション付き)を使用して、独自のフィールドの1つで主キー機能をシミュレートします。add_index:unique => true
  • 日付
  • 日付(年、月、日)のみを格納します
  • 時間
  • 時間(時間、分、秒)のみを保存します
  • 日時
  • 日付と時刻の両方を保存します
  • タイムスタンプ
  • 日付と時刻の両方を保存します
  • 注:Railsの目的では、TimestampとDateTimeはどちらも同じ意味です(どちらかのタイプを使用して日付と時刻の両方を格納します)。両方が存在する理由のTL;DRの説明については、下の段落をお読みください。

これらは、混乱がしばしば存在するタイプです。これがお役に立てば幸いです。これらに関する公式のドキュメントがない理由は本当にわかりません。また、あなたが参照したこれらのデータベースアダプターは、R​​ailsを書いたのと同じ人によって書かれたものだと思います。そのため、アダプターを書いているときに、ドキュメントを作成する必要はなかったでしょう。お役に立てれば!

注:との両方の存在は、:DateTime:Timestampが見つけたものから、主にデータベースシステムとの互換性のためにRailsに含まれています。たとえば、MySQLのTIMESTAMPデータ型はUNIXタイムスタンプとして保存されます。その有効な範囲は1970年から2038年までで、時間は最後のエポックから経過した秒数として保存されます。これはおそらく標準ですが、実際にはシステムごとに異なる場合があります。MySQLは後に、サイズの増加DATETIMEを犠牲にして、「1000-01-01 00:00:00」以降、秒として保存されるデータ型(5.6.4ではオプションの小数秒)を導入しました。TheTIMESTAMPデータ型は、下位互換性のために保持されました。他のデータベースシステムも同様の進化を遂げました。Railsは複数の標準が存在することを認識し、両方へのインターフェースを提供しました。ただし、Rails ActiveRecordはデフォルトでMySqlに保存されているUTC日付の両方:Timestampを使用するため、Railsプログラマーにとって機能的な違いはありません。これらは、2つを区別したいユーザーがそうできるようにするために存在します。(より詳細な説明については、このSOの回答を参照してください)。:DateTimeDATETIME

于 2012-08-10T02:17:29.137 に答える
12

私が見つけたRailsマスターブランチのソースコードから:

抽象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

superintype_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
于 2017-06-06T14:13:10.257 に答える