Class: DataMapper::Property

Inherits:
Object
  • Object
show all
Extended by:
Deprecate, Equalizer
Includes:
Assertions, Subject
Defined in:
lib/dm-core/property.rb,
lib/dm-core/property/date.rb,
lib/dm-core/property/text.rb,
lib/dm-core/property/time.rb,
lib/dm-core/property/float.rb,
lib/dm-core/property/class.rb,
lib/dm-core/property/lookup.rb,
lib/dm-core/property/serial.rb,
lib/dm-core/property/object.rb,
lib/dm-core/property/string.rb,
lib/dm-core/property/binary.rb,
lib/dm-core/property/boolean.rb,
lib/dm-core/property/decimal.rb,
lib/dm-core/property/numeric.rb,
lib/dm-core/property/integer.rb,
lib/dm-core/property/date_time.rb,
lib/dm-core/property/discriminator.rb,
lib/dm-core/property/invalid_value_error.rb

Overview

Properties

Properties for a model are not derived from a database structure, but instead explicitly declared inside your model class definitions. These properties then map (or, if using automigrate, generate) fields in your repository/database.

If you are coming to DataMapper from another ORM framework, such as ActiveRecord, this may be a fundamental difference in thinking to you. However, there are several advantages to defining your properties in your models:

  • information about your model is centralized in one place: rather than having to dig out migrations, xml or other configuration files.

  • use of mixins can be applied to model properties: better code reuse

  • having information centralized in your models, encourages you and the developers on your team to take a model-centric view of development.

  • it provides the ability to use Ruby's access control functions.

  • and, because DataMapper only cares about properties explicitly defined in your models, DataMapper plays well with legacy databases, and shares databases easily with other applications.

Declaring Properties

Inside your class, you call the property method for each property you want to add. The only two required arguments are the name and type, everything else is optional.

class Post
  include DataMapper::Resource

  property :title,   String,  :required => true  # Cannot be null
  property :publish, Boolean, :default => false  # Default value for new records is false
end

By default, DataMapper supports the following primitive (Ruby) types also called core properties:

  • Boolean

  • Class (datastore primitive is the same as String. Used for Inheritance)

  • Date

  • DateTime

  • Decimal

  • Float

  • Integer

  • Object (marshalled out during serialization)

  • String (default length is 50)

  • Text (limit of 65k characters by default)

  • Time

Limiting Access

Property access control is uses the same terminology Ruby does. Properties are public by default, but can also be declared private or protected as needed (via the :accessor option).

class Post
 include DataMapper::Resource

  property :title, String, :accessor => :private    # Both reader and writer are private
  property :body,  Text,   :accessor => :protected  # Both reader and writer are protected
end

Access control is also analogous to Ruby attribute readers and writers, and can be declared using :reader and :writer, in addition to :accessor.

class Post
  include DataMapper::Resource

  property :title, String, :writer => :private    # Only writer is private
  property :tags,  String, :reader => :protected  # Only reader is protected
end

Overriding Accessors

The reader/writer for any property can be overridden in the same manner that Ruby attr readers/writers can be. After the property is defined, just add your custom reader or writer:

class Post
  include DataMapper::Resource

  property :title, String

  def title=(new_title)
    raise ArgumentError if new_title != 'Lee is l337'
    super(new_title)
  end
end

Calling super ensures that any validators defined for the property are kept active.

Lazy Loading

By default, some properties are not loaded when an object is fetched in DataMapper. These lazily loaded properties are fetched on demand when their accessor is called for the first time (as it is often unnecessary to instantiate -every- property -every- time an object is loaded). For instance, DataMapper::Property::Text fields are lazy loading by default, although you can over-ride this behavior if you wish:

Example:

class Post
  include DataMapper::Resource

  property :title, String  # Loads normally
  property :body,  Text    # Is lazily loaded by default
end

If you want to over-ride the lazy loading on any field you can set it to a context or false to disable it with the :lazy option. Contexts allow multiple lazy properties to be loaded at one time. If you set :lazy to true, it is placed in the :default context

class Post
  include DataMapper::Resource

  property :title,   String                                    # Loads normally
  property :body,    Text,   :lazy => false                    # The default is now over-ridden
  property :comment, String, :lazy => [ :detailed ]            # Loads in the :detailed context
  property :author,  String, :lazy => [ :summary, :detailed ]  # Loads in :summary & :detailed context
end

Delaying the request for lazy-loaded attributes even applies to objects accessed through associations. In a sense, DataMapper anticipates that you will likely be iterating over objects in associations and rolls all of the load commands for lazy-loaded properties into one request from the database.

Example:

Widget.get(1).components
  # loads when the post object is pulled from database, by default

Widget.get(1).components.first.body
  # loads the values for the body property on all objects in the
  # association, rather than just this one.

Widget.get(1).components.first.comment
  # loads both comment and author for all objects in the association
  # since they are both in the :detailed context

Keys

Properties can be declared as primary or natural keys on a table. You should a property as the primary key of the table:

Examples:

property :id,        Serial                # auto-incrementing key
property :legacy_pk, String, :key => true  # 'natural' key

This is roughly equivalent to ActiveRecord's set_primary_key, though non-integer data types may be used, thus DataMapper supports natural keys. When a property is declared as a natural key, accessing the object using the indexer syntax Class[key] remains valid.

User.get(1)
   # when :id is the primary key on the users table
User.get('bill')
   # when :name is the primary (natural) key on the users table

Indices

You can add indices for your properties by using the :index option. If you use true as the option value, the index will be automatically named. If you want to name the index yourself, use a symbol as the value.

property :last_name,  String, :index => true
property :first_name, String, :index => :name

You can create multi-column composite indices by using the same symbol in all the columns belonging to the index. The columns will appear in the index in the order they are declared.

property :last_name,  String, :index => :name
property :first_name, String, :index => :name
   # => index on (last_name, first_name)

If you want to make the indices unique, use :unique_index instead of :index

Inferred Validations

If you require the dm-validations plugin, auto-validations will automatically be mixed-in in to your model classes: validation rules that are inferred when properties are declared with specific column restrictions.

class Post
  include DataMapper::Resource

  property :title, String, :length => 250, :min => 0, :max => 250
  # => infers 'validates_length :title'

  property :title, String, :required => true
  # => infers 'validates_present :title'

  property :email, String, :format => :email_address
  # => infers 'validates_format :email, :with => :email_address'

  property :title, String, :length => 255, :required => true
  # => infers both 'validates_length' as well as 'validates_present'
  #    better: property :title, String, :length => 1..255
end

This functionality is available with the dm-validations gem. For more information about validations, check the documentation for dm-validations.

Default Values

To set a default for a property, use the :default key. The property will be set to the value associated with that key the first time it is accessed, or when the resource is saved if it hasn't been set with another value already. This value can be a static value, such as 'hello' but it can also be a proc that will be evaluated when the property is read before its value has been set. The property is set to the return of the proc. The proc is passed two values, the resource the property is being set for and the property itself.

property :display_name, String, :default => lambda { |resource, property| resource. }

Word of warning. Don't try to read the value of the property you're setting the default for in the proc. An infinite loop will ensue.

Embedded Values (not implemented yet)

As an alternative to extraneous has_one relationships, consider using an EmbeddedValue.

Property options reference

:accessor            if false, neither reader nor writer methods are
                     created for this property

:reader              if false, reader method is not created for this property

:writer              if false, writer method is not created for this property

:lazy                if true, property value is only loaded when on first read
                     if false, property value is always loaded
                     if a symbol, property value is loaded with other properties
                     in the same group

:default             default value of this property

:allow_nil           if true, property may have a nil value on save

:key                 name of the key associated with this property.

:field               field in the data-store which the property corresponds to

:length              string field length

:format              format for autovalidation. Use with dm-validations plugin.

:index               if true, index is created for the property. If a Symbol, index
                     is named after Symbol value instead of being based on property name.

:unique_index        true specifies that index on this property should be unique

:auto_validation     if true, automatic validation is performed on the property

:validates           validation context. Use together with dm-validations.

:unique              if true, property column is unique. Properties of type Serial
                     are unique by default.

:precision           Indicates the number of significant digits. Usually only makes sense
                     for float type properties. Must be >= scale option value. Default is 10.

:scale               The number of significant digits to the right of the decimal point.
                     Only makes sense for float type properties. Must be > 0.
                     Default is nil for Float type and 10 for BigDecimal

Overriding default Property options

There is the ability to reconfigure a Property and it's subclasses by explicitly setting a value in the Property, eg:

# set all String properties to have a default length of 255
DataMapper::Property::String.length(255)

# set all Boolean properties to not allow nil (force true or false)
DataMapper::Property::Boolean.allow_nil(false)

# set all properties to be required by default
DataMapper::Property.required(true)

# turn off auto-validation for all properties by default
DataMapper::Property.auto_validation(false)

# set all mutator methods to be private by default
DataMapper::Property.writer(:private)

Please note that this has no effect when a subclass has explicitly defined it's own option. For example, setting the String length to 255 will not affect the Text property even though it inherits from String, because it sets it's own default length to 65535.

Misc. Notes

  • Properties declared as strings will default to a length of 50, rather than 255 (typical max varchar column size). To overload the default, pass :length => 255 or :length => 0..255. Since DataMapper does not introspect for properties, this means that legacy database tables may need their String columns defined with a :length so that DM does not apply an un-needed length validation, or allow overflow.

  • You may declare a Property with the data-type of Class. see SingleTableInheritance for more on how to use Class columns.

Direct Known Subclasses

Object

Defined Under Namespace

Modules: Lookup Classes: Binary, Boolean, Class, Date, DateTime, Decimal, Discriminator, Float, Integer, InvalidValueError, Numeric, Object, Serial, String, Text, Time

Constant Summary

PRIMITIVES =
[
  TrueClass,
  ::String,
  ::Float,
  ::Integer,
  ::BigDecimal,
  ::DateTime,
  ::Date,
  ::Time,
  ::Class
].to_set.freeze
OPTIONS =
[
  :load_as, :dump_as, :coercion_method,
  :accessor, :reader, :writer,
  :lazy, :default, :key, :field,
  :index, :unique_index,
  :unique, :allow_nil, :allow_blank, :required
]
VISIBILITY_OPTIONS =

Possible :visibility option values

[ :public, :protected, :private ].to_set.freeze
INVALID_NAMES =

Invalid property names

(Resource.instance_methods +
 Resource.private_instance_methods +
 Query::OPTIONS.to_a
).map { |name| name.to_s }

Instance Attribute Summary (collapse)

Class Method Summary (collapse)

Instance Method Summary (collapse)

Methods included from Deprecate

deprecate

Methods included from Equalizer

equalize

Methods included from Subject

#default?, #default_for

Methods included from Assertions

#assert_kind_of

Constructor Details

- (Property) initialize(model, name, options = {}) (protected)

Returns a new instance of Property



759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
# File 'lib/dm-core/property.rb', line 759

def initialize(model, name, options = {})
  options = options.to_hash.dup

  if INVALID_NAMES.include?(name.to_s) || (kind_of?(Boolean) && INVALID_NAMES.include?("#{name}?"))
    raise ArgumentError,
      "+name+ was #{name.inspect}, which cannot be used as a property name since it collides with an existing method or a query option"
  end

  assert_valid_options(options)

  predefined_options = self.class.options

  @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
  @coercion_method        = @options.fetch(:coercion_method)

  @load_as = self.class.load_as
  @dump_as = self.class.dump_as

  @field   = @options[:field].freeze unless @options[:field].nil?
  @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

  bind
end

Instance Attribute Details

- (Object) allow_blank (readonly)

Returns the value of attribute allow_blank



338
339
340
# File 'lib/dm-core/property.rb', line 338

def allow_blank
  @allow_blank
end

- (Object) allow_nil (readonly)

Returns the value of attribute allow_nil



338
339
340
# File 'lib/dm-core/property.rb', line 338

def allow_nil
  @allow_nil
end

- (Object) coercion_method (readonly)

Returns the value of attribute coercion_method



338
339
340
# File 'lib/dm-core/property.rb', line 338

def coercion_method
  @coercion_method
end

- (Object) default (readonly)

Returns the value of attribute default



338
339
340
# File 'lib/dm-core/property.rb', line 338

def default
  @default
end

- (Object) dump_as (readonly) Also known as: dump_class

Returns the value of attribute dump_as



338
339
340
# File 'lib/dm-core/property.rb', line 338

def dump_as
  @dump_as
end

- (Boolean, ...) index (readonly)

Returns index name if property has index.



504
505
506
# File 'lib/dm-core/property.rb', line 504

def index
  @index
end

- (Object) instance_variable_name (readonly)

Returns the value of attribute instance_variable_name



338
339
340
# File 'lib/dm-core/property.rb', line 338

def instance_variable_name
  @instance_variable_name
end

- (Object) load_as (readonly) Also known as: load_class

Returns the value of attribute load_as



338
339
340
# File 'lib/dm-core/property.rb', line 338

def load_as
  @load_as
end

- (Object) model (readonly)

Returns the value of attribute model



338
339
340
# File 'lib/dm-core/property.rb', line 338

def model
  @model
end

- (Object) name (readonly)

Returns the value of attribute name



338
339
340
# File 'lib/dm-core/property.rb', line 338

def name
  @name
end

- (Object) options (readonly)

Returns the value of attribute options



338
339
340
# File 'lib/dm-core/property.rb', line 338

def options
  @options
end

- (Object) reader_visibility (readonly)

Returns the value of attribute reader_visibility



338
339
340
# File 'lib/dm-core/property.rb', line 338

def reader_visibility
  @reader_visibility
end

- (Object) repository_name (readonly)

Returns the value of attribute repository_name



338
339
340
# File 'lib/dm-core/property.rb', line 338

def repository_name
  @repository_name
end

- (Object) required (readonly)

Returns the value of attribute required



338
339
340
# File 'lib/dm-core/property.rb', line 338

def required
  @required
end

- (Boolean, ...) unique_index (readonly)

Returns true if property has unique index. Serial properties and keys are unique by default.



516
517
518
# File 'lib/dm-core/property.rb', line 516

def unique_index
  @unique_index
end

- (Object) writer_visibility (readonly)

Returns the value of attribute writer_visibility



338
339
340
# File 'lib/dm-core/property.rb', line 338

def writer_visibility
  @writer_visibility
end

Class Method Details

+ (Object) accept_options(*args)



413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
# File 'lib/dm-core/property.rb', line 413

def accept_options(*args)
  accepted_options.concat(args)

  # create methods for each new option
  args.each do |property_option|
    class_eval <<-RUBY, __FILE__, __LINE__ + 1
      def self.#{property_option}(value = Undefined)                         # def self.unique(value = Undefined)
        return @#{property_option} if value.equal?(Undefined)                #   return @unique if value.equal?(Undefined)
        descendants.each do |descendant|                                     #   descendants.each do |descendant|
          unless descendant.instance_variable_defined?(:@#{property_option}) #     unless descendant.instance_variable_defined?(:@unique)
            descendant.#{property_option}(value)                             #       descendant.unique(value)
          end                                                                #     end
        end                                                                  #   end
        @#{property_option} = value                                          #   @unique = value
      end                                                                    # end
    RUBY
  end

  descendants.each { |descendant| descendant.accepted_options.concat(args) }
end

+ (Object) accepted_options



408
409
410
# File 'lib/dm-core/property.rb', line 408

def accepted_options
  @accepted_options ||= []
end

+ (Object) demodulized_names

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



358
359
360
# File 'lib/dm-core/property.rb', line 358

def demodulized_names
  @demodulized_names ||= {}
end

+ (Object) descendants



370
371
372
# File 'lib/dm-core/property.rb', line 370

def descendants
  @descendants ||= DescendantSet.new
end

+ (Object) determine_class(type)



352
353
354
355
# File 'lib/dm-core/property.rb', line 352

def determine_class(type)
  return type if type < DataMapper::Property::Object
  find_class(DataMapper::Inflector.demodulize(type.name))
end

+ (Object) find_class(name)



363
364
365
366
367
# File 'lib/dm-core/property.rb', line 363

def find_class(name)
  klass   = demodulized_names[name]
  klass ||= const_get(name) if const_defined?(name)
  klass
end

+ (Object) inherited(descendant)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
# File 'lib/dm-core/property.rb', line 375

def inherited(descendant)
  # Descendants is a tree rooted in DataMapper::Property that tracks
  # inheritance.  We pre-calculate each comparison value (demodulized
  # class name) to achieve a Hash[]-time lookup, rather than walk the
  # entire descendant tree and calculate names on-demand (expensive,
  # redundant).
  #
  # Since the algorithm relegates property class name lookups to a flat
  # namespace, we need to ensure properties defined outside of DM don't
  # override built-ins (Serial, String, etc) by merely defining a property
  # of a same name.  We avoid this by only ever adding to the lookup
  # table.  Given that DM loads its own property classes first, we can
  # assume that their names are "reserved" when added to the table.
  #
  # External property authors who want to provide "replacements" for
  # builtins (e.g. in a non-DM-supported adapter) should follow the
  # convention of wrapping those properties in a module, and include'ing
  # the module on the model class directly.  This bypasses the DM-hooked
  # const_missing lookup that would normally check this table.
  descendants << descendant

  Property.demodulized_names[DataMapper::Inflector.demodulize(descendant.name)] ||= descendant

  # inherit accepted options
  descendant.accepted_options.concat(accepted_options)

  # inherit the option values
  options.each { |key, value| descendant.send(key, value) }

  super
end

+ (Object) nullable(*args)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



435
436
437
438
# File 'lib/dm-core/property.rb', line 435

def nullable(*args)
  # :required is preferable to :allow_nil, but :nullable maps precisely to :allow_nil
  raise "#nullable is deprecated, use #required instead (#{caller.first})"
end

+ (Hash) options

Gives all the options set on this property



445
446
447
448
449
450
451
# File 'lib/dm-core/property.rb', line 445

def options
  options = {}
  accepted_options.each do |name|
    options[name] = send(name) if instance_variable_defined?("@#{name}")
  end
  options
end

+ (Object) primitive(*args)



454
455
456
457
# File 'lib/dm-core/property.rb', line 454

def primitive(*args)
  warn "DataMapper::Property.primitive is deprecated, use .load_as instead (#{caller.first})"
  load_as(*args)
end

Instance Method Details

- (Boolean) allow_blank?

Returns whether or not the property can be a blank value



574
575
576
# File 'lib/dm-core/property.rb', line 574

def allow_blank?
  @allow_blank
end

- (Boolean) allow_nil?

Returns whether or not the property can accept 'nil' as it's value



564
565
566
# File 'lib/dm-core/property.rb', line 564

def allow_nil?
  @allow_nil
end

- (Object) assert_valid_options(options) (protected)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
# File 'lib/dm-core/property.rb', line 800

def assert_valid_options(options)
  keys = options.keys

  if (unknown_keys = keys - self.class.accepted_options).any?
    raise ArgumentError, "options #{unknown_keys.map { |key| key.inspect }.join(' and ')} are unknown"
  end

  options.each do |key, value|
    boolean_value = value == true || value == false

    case key
      when :field
        assert_kind_of "options[:#{key}]", value, ::String

      when :default
        if value.nil?
          raise ArgumentError, "options[:#{key}] must not be nil"
        end

      when :serial, :key, :allow_nil, :allow_blank, :required, :auto_validation
        unless boolean_value
          raise ArgumentError, "options[:#{key}] must be either true or false"
        end

        if key == :required && (keys.include?(:allow_nil) || keys.include?(:allow_blank))
          raise ArgumentError, 'options[:required] cannot be mixed with :allow_nil or :allow_blank'
        end

      when :index, :unique_index, :unique, :lazy
        unless boolean_value || value.kind_of?(Symbol) || (value.kind_of?(Array) && value.any? && value.all? { |val| val.kind_of?(Symbol) })
          raise ArgumentError, "options[:#{key}] must be either true, false, a Symbol or an Array of Symbols"
        end

      when :length
        assert_kind_of "options[:#{key}]", value, Range, ::Integer

      when :size, :precision, :scale
        assert_kind_of "options[:#{key}]", value, ::Integer

      when :reader, :writer, :accessor
        assert_kind_of "options[:#{key}]", value, Symbol

        unless VISIBILITY_OPTIONS.include?(value)
          raise ArgumentError, "options[:#{key}] must be #{VISIBILITY_OPTIONS.join(' or ')}"
        end
    end
  end
end

- (Boolean) assert_valid_value(value)

Asserts value is valid

Raises:



710
711
712
713
714
715
# File 'lib/dm-core/property.rb', line 710

def assert_valid_value(value)
  unless valid?(value)
    raise Property::InvalidValueError.new(self,value)
  end
  true
end

- (Object) bind

A hook to allow properties to extend or modify the model it's bound to. Implementations are not supposed to modify the state of the property class, and should produce no side-effects on the property instance.



465
466
467
# File 'lib/dm-core/property.rb', line 465

def bind
  # no op
end

- (undefined) determine_visibility (protected)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Assert given visibility value is supported.

Will raise ArgumentError if this Property's reader and writer visibilities are not included in VISIBILITY_OPTIONS.

Raises:

  • (ArgumentError)

    “property visibility must be :public, :protected, or :private”



859
860
861
862
863
864
# File 'lib/dm-core/property.rb', line 859

def determine_visibility
  default_accessor = @options.fetch(:accessor, :public)

  @reader_visibility = @options.fetch(:reader, default_accessor)
  @writer_visibility = @options.fetch(:writer, default_accessor)
end

- (String) field(repository_name = nil)

Supplies the field in the data-store which the property corresponds to



474
475
476
477
478
479
480
481
482
# File 'lib/dm-core/property.rb', line 474

def field(repository_name = nil)
  if repository_name
    raise "Passing in +repository_name+ to #{self.class}#field is deprecated (#{caller.first})"
  end

  # defer setting the field with the adapter specific naming
  # conventions until after the adapter has been setup
  @field ||= model.field_naming_convention(self.repository_name).call(self).freeze
end

- (Object) get(resource)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Standardized reader method for the property

Raises:

  • (ArgumentError)

    resource should be a Resource, but was .…”



589
590
591
# File 'lib/dm-core/property.rb', line 589

def get(resource)
  get!(resource)
end

- (Object) get!(resource)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Fetch the ivar value in the resource



602
603
604
# File 'lib/dm-core/property.rb', line 602

def get!(resource)
  resource.instance_variable_get(instance_variable_name)
end

- (String) inspect

Returns a concise string representation of the property instance.



723
724
725
# File 'lib/dm-core/property.rb', line 723

def inspect
  "#<#{self.class.name} @model=#{model.inspect} @name=#{name.inspect}>"
end

- (Boolean) key?

Returns whether or not the property is a key or a part of a key



534
535
536
# File 'lib/dm-core/property.rb', line 534

def key?
  @key
end

- (Boolean) lazy?

Returns whether or not the property is to be lazy-loaded



524
525
526
# File 'lib/dm-core/property.rb', line 524

def lazy?
  @lazy
end

- (Object) lazy_load(resource)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Loads lazy columns when get or set is called.



657
658
659
660
# File 'lib/dm-core/property.rb', line 657

def lazy_load(resource)
  return if loaded?(resource)
  resource.__send__(:lazy_load, lazy_load_properties)
end

- (Object) lazy_load_properties

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



663
664
665
666
667
668
669
# File 'lib/dm-core/property.rb', line 663

def lazy_load_properties
  @lazy_load_properties ||=
    begin
      properties = self.properties
      properties.in_context(lazy? ? [ self ] : properties.defaults)
    end
end

- (Boolean) loaded?(resource)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Check if the attribute corresponding to the property is loaded



647
648
649
# File 'lib/dm-core/property.rb', line 647

def loaded?(resource)
  resource.instance_variable_defined?(instance_variable_name)
end

- (Object) primitive



741
742
743
744
# File 'lib/dm-core/property.rb', line 741

def primitive
  warn "#primitive is deprecated, use #dump_as instead (#{caller.first})"
  dump_as
end

- (Boolean) primitive?(value)

Test a value to see if it matches the primitive type



736
737
738
739
# File 'lib/dm-core/property.rb', line 736

def primitive?(value)
  warn "#primitive? is deprecated, use #value_dumped? instead (#{caller.first})"
  value_dumped?(value)
end

- (Object) properties

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



672
673
674
# File 'lib/dm-core/property.rb', line 672

def properties
  @properties ||= model.properties(repository_name)
end

- (Boolean) required?

Returns whether or not the property must be non-nil and non-blank



554
555
556
# File 'lib/dm-core/property.rb', line 554

def required?
  @required
end

- (Boolean) serial?

Returns whether or not the property is “serial” (auto-incrementing)



544
545
546
# File 'lib/dm-core/property.rb', line 544

def serial?
  @serial
end

- (Object) set(resource, value)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Provides a standardized setter method for the property

Raises:

  • (ArgumentError)

    resource should be a Resource, but was .…”



619
620
621
# File 'lib/dm-core/property.rb', line 619

def set(resource, value)
  set!(resource, typecast(value))
end

- (Object) set!(resource, value)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Set the ivar value in the resource



634
635
636
# File 'lib/dm-core/property.rb', line 634

def set!(resource, value)
  resource.instance_variable_set(instance_variable_name, value)
end

- (Object) typecast(value)



677
678
679
# File 'lib/dm-core/property.rb', line 677

def typecast(value)
  Virtus::Coercion[value.class].send(coercion_method, value)
end

- (Boolean) unique?

Returns true if property is unique. Serial properties and keys are unique by default.



491
492
493
# File 'lib/dm-core/property.rb', line 491

def unique?
  !!@unique
end

- (Boolean) valid?(value, negated = false)

Test the value to see if it is a valid value for this Property



690
691
692
693
694
695
696
697
698
# File 'lib/dm-core/property.rb', line 690

def valid?(value, negated = false)
  dumped_value = dump(value)

  if required? && dumped_value.nil?
    negated || false
  else
    value_dumped?(dumped_value) || (dumped_value.nil? && (allow_nil? || negated))
  end
end

- (Boolean) value_dumped?(value)



747
748
749
# File 'lib/dm-core/property.rb', line 747

def value_dumped?(value)
  value.kind_of?(dump_as)
end

- (Boolean) value_loaded?(value)



752
753
754
# File 'lib/dm-core/property.rb', line 752

def value_loaded?(value)
  value.kind_of?(load_as)
end