# File lib/dm-core/property.rb, line 766
    def initialize(model, name, options = {}, type = nil)
      options = options.to_hash.dup

      if type && !kind_of?(type)
        warn "#{type} < DataMapper::Type is deprecated, use the new DataMapper::Property API instead (#{caller[2]})"
        @type = type
      end

      reserved_method_names = DataMapper::Resource.instance_methods + DataMapper::Resource.private_instance_methods
      if reserved_method_names.map { |m| m.to_s }.include?(name.to_s)
        raise ArgumentError, "+name+ was #{name.inspect}, which cannot be used as a property name since it collides with an existing method"
      end

      assert_valid_options(options)

      predefined_options = self.class.options
      predefined_options.merge!(@type.options) if @type

      @repository_name        = model.repository_name
      @model                  = model
      @name                   = name.to_s.chomp('?').to_sym
      @options                = predefined_options.merge(options).freeze
      @instance_variable_name = "@#{@name}".freeze

      @primitive = self.class.primitive || @type.primitive
      @custom    = !@type.nil?
      @field     = @options[:field].freeze
      @default   = @options[:default]

      @serial       = @options.fetch(:serial,       false)
      @key          = @options.fetch(:key,          @serial)
      @unique       = @options.fetch(:unique,       @key ? :key : false)
      @required     = @options.fetch(:required,     @key)
      @allow_nil    = @options.fetch(:allow_nil,    !@required)
      @allow_blank  = @options.fetch(:allow_blank,  !@required)
      @index        = @options.fetch(:index,        false)
      @unique_index = @options.fetch(:unique_index, @unique)
      @lazy         = @options.fetch(:lazy,         false) && !@key

      determine_visibility

      @type ? @type.bind(self) : bind
    end