code: def property(name, *bool_options, **options)
        sym_name = name.to_sym
        @_lazer_metadata.add(sym_name, KeyMetadata.new(sym_name, *bool_options, **options))
        define_method(sym_name) { read_attribute(sym_name) }
      end
docs: Define a property.
   @param name [Symbol] the name of the property method
   @param bool_options [Array<Symbol>] options that are set to true
   @param options [Hash] the options to create the property with
   @option options [Boolean] :required (false) whether existence of this property should be
     checked on model creation
   @option options [Boolean] :nil (false) shortcut for default: nil
   @option options [Object, Proc] :default the default value to return if not provided
   @option options [Symbol] :from (name) the key in the source object to get the property from
   @option options [Proc, Symbol, nil] :with an optional transformation to apply to the value
   @return [Symbol] the name of the created property
  
   @example
     class MyModel
       include LazyLazer
  
       property :id, :required
       property :timestamp, with: ->(i) { Time.at(i) }
       property :created_at, default: ->() { Time.now }
       property :camel_case, from: :camelCase
     end