new (DataMapper::Property)

    # 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