[ruby-on-rails] Rails 열 유형에 대한 설명서가 있습니까?

이 페이지에 있는 간단한 유형 목록보다 더 많은 것을 찾고 있습니다 .

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

그러나 실제로 이러한 필드를 정의 하는 문서가 있습니까?

구체적으로 특별히:

  • 차이 무엇 :string:text?
  • 사이 :float:decimal?
  • 의 구별 특징은 무엇입니까 :time, :timestamp그리고는 :datetime?

이러한 유형의 뉘앙스는 어디에나 문서화되어 있습니까?

편집 : DB 플랫폼 구현의 요점은 내가 묻고 자하는 질문과 관련이 없습니다. 예를 들어 :datetimeRails 문서에 의도 된 의미가 없다면, 해당 컬럼 유형을 선택할 때 db-adapter-writer는 무엇을 수행합니까?



답변

개인적인 경험을 바탕으로 작성된 지침 :

  • 문자열 :
    • 255 자로 제한됨 (DBMS에 따라 다름)
    • 짧은 텍스트 필드 (이름, 이메일 등)에 사용
  • 텍스트 :
    • 무제한 길이 (DBMS에 따라 다름)
    • 댓글, 블로그 게시물 등에 사용합니다. 일반적인 경험 법칙 : 텍스트 영역을 통해 캡처 된 경우 텍스트를 사용하십시오. 텍스트 필드를 사용하여 입력하려면 문자열을 사용하십시오.
  • 정수 :
    • 정수
  • 플로트 :
    • 부동 소수점 정밀도로 저장된 10 진수
    • 정밀도는 고정되어 일부 계산에 문제가 될 수 있습니다. 일반적으로 부정확 한 반올림으로 인해 수학 연산에 적합하지 않습니다.
  • 십진법 :
    • 계산에 필요한 것에 따라 달라지는 정밀도로 저장된 10 진수; 정확한 수학에 사용하십시오
    • 부동 소수점과 소수의 차이점에 대한 예와 자세한 설명은 게시물을 참조하십시오 .
  • 부울 :
    • true / false 속성을 저장하는 데 사용합니다 (예 : on / off와 같이 두 가지 상태 만있는 것).
  • 이진 :
    • 이미지, 동영상 및 기타 파일을 원래의 원시 형식으로 Blob 이라는 데이터 덩어리에 저장하는 데 사용
  • : primary_key
    • 이 데이터 유형은 Rails가 선택한 데이터베이스에 필요한 기본 키 데이터 유형 (예 : serial primary keypostgreSQL)으로 변환하는 자리 표시 자입니다 . 사용은 다소 복잡하므로 권장하지 않습니다.
    • 자신의 필드 중 하나에서 기본 키 기능을 시뮬레이션 하려면 모델 및 마이그레이션 제약 조건 (예 : 옵션 validates_uniqueness_ofadd_index함께 :unique => true)을 사용하십시오.
  • 날짜 :
    • 날짜 만 저장 (년, 월, 일)
  • 시간 :
    • 시간 (시간, 분, 초) 만 저장
  • 날짜 시간 :
    • 날짜와 시간을 모두 저장
  • 타임 스탬프
    • 날짜와 시간을 모두 저장
    • 참고 : Rails의 목적 상 Timestamp와 DateTime은 모두 같은 의미입니다 (날짜와 시간을 모두 저장하려면 두 유형 중 하나를 사용하십시오). 둘 다 존재하는 이유에 대한 TL; DR 설명은 맨 아래 단락을 읽으십시오.

이것들은 종종 혼란이 존재하는 유형입니다. 이게 도움이 되길 바란다. 나는 왜 이것들에 대한 공식적인 문서가 없는지 모른다. 또한 언급 한 데이터베이스 어댑터가 Rails를 작성한 사람과 동일한 사람들이 작성했다고 생각하므로 어댑터를 작성할 때 설명서가 필요하지 않을 것입니다. 도움이 되었기를 바랍니다!

참고 : :DateTime:Timestamp에서 찾을 수있는 것의 대부분은 데이터베이스 시스템과의 호환성을 위해 Rails에 포함되어 있습니다. 예를 들어, MySQL의 TIMESTAMP데이터 유형은 유닉스 타임 스탬프로 저장됩니다. 유효 범위는 1970 년에서 2038 년 사이이며, 시간은 마지막 epoch 이후에 경과 한 시간 (초)으로 저장됩니다. 표준으로 가정되지만 실제로는 시스템마다 다를 수 있습니다. MySQL은 데이터베이스에서 상대적 시간이 좋지 않다는 것을 인식하고 나중에 DATETIME데이터 유형을 도입했습니다.이 데이터 유형은 1 년, 월, 일,시, 분 및 초의 모든 숫자를 크기 증가 비용으로 저장합니다. 그만큼TIMESTAMP이전 버전과의 호환성을 위해 데이터 유형이 유지되었습니다. 다른 데이터베이스 시스템도 비슷한 발전을 거쳤습니다. Rails는 여러 표준이 존재 함을 인식하고 두 인터페이스를 모두 제공했습니다. 그러나 Rails ActiveRecord 는 MySql ‘s에 저장된 UTC 날짜 :Timestamp:DateTimeUTC 날짜를 기본값으로 사용 DATETIME하므로 Rails 프로그래머와 기능적으로 차이가 없습니다. 이것들 은 두 가지를 구별 하려는 사용자가 그렇게 할 수 있도록 존재합니다 . (자세한 설명은 SO 답변을 참조하십시오 ).


답변

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

supertype_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


답변