# File lib/dm-core/property.rb, line 751
    def initialize(model, name, type, options = {})
      assert_kind_of 'model',   model,   Model
      assert_kind_of 'name',    name,    Symbol
      assert_kind_of 'type',    type,    Class, Module
      assert_kind_of 'options', options, Hash

      options = options.dup

      if TrueClass == type
        warn "#{type} is deprecated, use Boolean instead at #{caller[2]}"
        type = Types::Boolean
      elsif Integer == type && options.delete(:serial)
        warn "#{type} with explicit :serial option is deprecated, use Serial instead (#{caller[2]})"
        type = Types::Serial
      elsif options.key?(:size)
        if String == type
          warn ":size option is deprecated, use #{type} with :length instead (#{caller[2]})"
          length = options.delete(:size)
          options[:length] = length unless options.key?(:length)
        elsif Numeric > type
          warn ":size option is deprecated, specify :min and :max instead (#{caller[2]})"
        end
      end

      assert_valid_options(options)

      # if the type can be found within Types then
      # use that class rather than the primitive
      unless type.name.blank?
        type = Types.find_const(type.name)
      end

      unless PRIMITIVES.include?(type) || (Type > type && PRIMITIVES.include?(type.primitive))
        raise ArgumentError, "+type+ was #{type.inspect}, which is not a supported type"
      end

      @repository_name        = model.repository_name
      @model                  = model
      @name                   = name.to_s.sub(/\?$/, '').to_sym
      @type                   = type
      @custom                 = Type > @type
      @options                = (@custom ? @type.options.merge(options) : options.dup).freeze
      @instance_variable_name = "@#{@name}".freeze

      @primitive = @type.respond_to?(:primitive) ? @type.primitive : @type
      @field     = @options[:field].freeze
      @default   = @options[:default]

      @serial       = @options.fetch(:serial,       false)
      @key          = @options.fetch(:key,          @serial || false)
      @nullable     = @options.fetch(:nullable,     @key == false)
      @index        = @options.fetch(:index,        nil)
      @unique_index = @options.fetch(:unique_index, nil)
      @unique       = @options.fetch(:unique,       @serial || @key || false)
      @lazy         = @options.fetch(:lazy,         @type.respond_to?(:lazy) ? @type.lazy : false) && !@key

      # assign attributes per-type
      if String == @primitive || Class == @primitive
        @length = @options.fetch(:length, DEFAULT_LENGTH)
      elsif BigDecimal == @primitive || Float == @primitive
        @precision = @options.fetch(:precision, DEFAULT_PRECISION)
        @scale     = @options.fetch(:scale,     Float == @primitive ? DEFAULT_SCALE_FLOAT : DEFAULT_SCALE_BIGDECIMAL)

        unless @precision > 0
          raise ArgumentError, "precision must be greater than 0, but was #{@precision.inspect}"
        end

        unless Float == @primitive && @scale.nil?
          unless @scale >= 0
            raise ArgumentError, "scale must be equal to or greater than 0, but was #{@scale.inspect}"
          end

          unless @precision >= @scale
            raise ArgumentError, "precision must be equal to or greater than scale, but was #{@precision.inspect} and scale was #{@scale.inspect}"
          end
        end
      end

      if Numeric > @primitive && (@options.keys & [ :min, :max ]).any?
        @min = @options.fetch(:min, DEFAULT_NUMERIC_MIN)
        @max = @options.fetch(:max, DEFAULT_NUMERIC_MAX)

        if @max < DEFAULT_NUMERIC_MIN && !@options.key?(:min)
          raise ArgumentError, "min should be specified when the max is less than #{DEFAULT_NUMERIC_MIN}"
        elsif @max < @min
          raise ArgumentError, "max must be less than the min, but was #{@max} while the min was #{@min}"
        end
      end

      determine_visibility

      if custom?
        type.bind(self)
      end

      # comes from dm-validations
      @model.auto_generate_validations(self) if @model.respond_to?(:auto_generate_validations)
    end