Module DataMapper::Persistence
In: lib/data_mapper/persistence.rb
lib/data_mapper/persistence.rb

See DataMapper::Persistence::ClassMethods for DataMapper‘s DSL documentation.

Methods

Included Modules

Comparable Comparable

Classes and Modules

Module DataMapper::Persistence::ClassMethods
Module DataMapper::Persistence::ConvenienceMethods
Class DataMapper::Persistence::IncompleteModelDefinitionError

Attributes

loaded_set  [RW]  This probably needs to be protected
loaded_set  [RW]  This probably needs to be protected
original_values  [R] 
original_values  [R] 

Public Class methods

 Migrates the database schema based on the properties defined within
 models. This includes removing fields no longer listed in models and
 adding new ones.

This is destructive. Any data stored in the database will be destroyed when this method is called.

Returns

 True:: successfully automigrated database
 False:: an error occured when automigrating the database

@public

[Source]

    # File lib/data_mapper/persistence.rb, line 80
80:     def self.auto_migrate!
81:       subclasses.each do |subclass|
82:         subclass.auto_migrate!
83:       end
84:     end
 Migrates the database schema based on the properties defined within
 models. This includes removing fields no longer listed in models and
 adding new ones.

This is destructive. Any data stored in the database will be destroyed when this method is called.

Returns

 True:: successfully automigrated database
 False:: an error occured when automigrating the database

@public

[Source]

    # File lib/data_mapper/persistence.rb, line 80
80:     def self.auto_migrate!
81:       subclasses.each do |subclass|
82:         subclass.auto_migrate!
83:       end
84:     end

Track classes that include this module.

Returns

 Support::TypedSet::
   contains classes that include or inherit from this module

@semipublic

[Source]

     # File lib/data_mapper/persistence.rb, line 116
116:     def self.dependencies
117:       @dependency_queue || (@dependency_queue = DependencyQueue.new)
118:     end

Track classes that include this module.

Returns

 Support::TypedSet::
   contains classes that include or inherit from this module

@semipublic

[Source]

     # File lib/data_mapper/persistence.rb, line 116
116:     def self.dependencies
117:       @dependency_queue || (@dependency_queue = DependencyQueue.new)
118:     end

Drops all tables known by the schema

Returns

 True:: successfully automigrated database
 False:: an error occured when automigrating the database

@public

[Source]

    # File lib/data_mapper/persistence.rb, line 94
94:     def self.drop_all_tables!
95:       database.adapter.schema.each do |table|
96:         table.drop!
97:       end
98:     end

Drops all tables known by the schema

Returns

 True:: successfully automigrated database
 False:: an error occured when automigrating the database

@public

[Source]

    # File lib/data_mapper/persistence.rb, line 94
94:     def self.drop_all_tables!
95:       database.adapter.schema.each do |table|
96:         table.drop!
97:       end
98:     end

[Source]

    # File lib/data_mapper/persistence.rb, line 24
24:     def self.included(klass)
25: 
26:       klass.extend(ClassMethods)
27:       klass.extend(ConvenienceMethods::ClassMethods)
28: 
29:       klass.send(:include, ConvenienceMethods::InstanceMethods)
30:       klass.send(:include, Attributes)
31:       klass.send(:include, Associations)
32:       klass.send(:include, Validations)
33:       klass.send(:include, CallbacksHelper)
34:       klass.send(:include, Support::Serialization)
35: 
36:       klass.instance_variable_set('@properties', [])
37: 
38:       klass.send :extend, AutoMigrations
39:       klass.subclasses
40:       DataMapper::Persistence::subclasses << klass unless klass == DataMapper::Base
41:       klass.send(:undef_method, :id) if method_defined?(:id)
42: 
43:       # When this class is sub-classed, copy the declared columns.
44:       klass.class_eval do
45:         def self.subclasses
46:           @subclasses || (@subclasses = Support::TypedSet.new(Class))
47:         end
48: 
49:         def self.inherited(subclass)
50:           super_table = database.table(self)
51: 
52:           if super_table.type_column.nil?
53:             super_table.add_column(:type, :class, {})
54:           end
55: 
56:           subclass.instance_variable_set('@properties', self.instance_variable_get("@properties").dup)
57:           subclass.instance_variable_set("@callbacks", self.callbacks.dup)
58: 
59:           self::subclasses << subclass
60:         end
61: 
62:         def self.persistent?
63:           true
64:         end
65:       end
66:     end

[Source]

    # File lib/data_mapper/persistence.rb, line 24
24:     def self.included(klass)
25: 
26:       klass.extend(ClassMethods)
27:       klass.extend(ConvenienceMethods::ClassMethods)
28: 
29:       klass.send(:include, ConvenienceMethods::InstanceMethods)
30:       klass.send(:include, Attributes)
31:       klass.send(:include, Associations)
32:       klass.send(:include, Validations)
33:       klass.send(:include, CallbacksHelper)
34:       klass.send(:include, Support::Serialization)
35: 
36:       klass.instance_variable_set('@properties', [])
37: 
38:       klass.send :extend, AutoMigrations
39:       klass.subclasses
40:       DataMapper::Persistence::subclasses << klass unless klass == DataMapper::Base
41:       klass.send(:undef_method, :id) if method_defined?(:id)
42: 
43:       # When this class is sub-classed, copy the declared columns.
44:       klass.class_eval do
45:         def self.subclasses
46:           @subclasses || (@subclasses = Support::TypedSet.new(Class))
47:         end
48: 
49:         def self.inherited(subclass)
50:           super_table = database.table(self)
51: 
52:           if super_table.type_column.nil?
53:             super_table.add_column(:type, :class, {})
54:           end
55: 
56:           subclass.instance_variable_set('@properties', self.instance_variable_get("@properties").dup)
57:           subclass.instance_variable_set("@callbacks", self.callbacks.dup)
58: 
59:           self::subclasses << subclass
60:         end
61: 
62:         def self.persistent?
63:           true
64:         end
65:       end
66:     end

[Source]

    # File lib/data_mapper/persistence.rb, line 49
49:         def self.inherited(subclass)
50:           super_table = database.table(self)
51: 
52:           if super_table.type_column.nil?
53:             super_table.add_column(:type, :class, {})
54:           end
55: 
56:           subclass.instance_variable_set('@properties', self.instance_variable_get("@properties").dup)
57:           subclass.instance_variable_set("@callbacks", self.callbacks.dup)
58: 
59:           self::subclasses << subclass
60:         end

[Source]

    # File lib/data_mapper/persistence.rb, line 49
49:         def self.inherited(subclass)
50:           super_table = database.table(self)
51: 
52:           if super_table.type_column.nil?
53:             super_table.add_column(:type, :class, {})
54:           end
55: 
56:           subclass.instance_variable_set('@properties', self.instance_variable_get("@properties").dup)
57:           subclass.instance_variable_set("@callbacks", self.callbacks.dup)
58: 
59:           self::subclasses << subclass
60:         end

[Source]

     # File lib/data_mapper/persistence.rb, line 120
120:     def initialize(details = nil)
121:       check_for_properties!
122:       if details
123:         initialize_with_attributes(details)
124:       end
125:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 120
120:     def initialize(details = nil)
121:       check_for_properties!
122:       if details
123:         initialize_with_attributes(details)
124:       end
125:     end

[Source]

    # File lib/data_mapper/persistence.rb, line 62
62:         def self.persistent?
63:           true
64:         end

[Source]

    # File lib/data_mapper/persistence.rb, line 62
62:         def self.persistent?
63:           true
64:         end

Track classes that include this module.

Returns

 Support::TypedSet::
   contains classes that include or inherit from this module

@semipublic

[Source]

     # File lib/data_mapper/persistence.rb, line 106
106:     def self.subclasses
107:       @subclasses || (@subclasses = Support::TypedSet.new(Class))
108:     end

Track classes that include this module.

Returns

 Support::TypedSet::
   contains classes that include or inherit from this module

@semipublic

[Source]

     # File lib/data_mapper/persistence.rb, line 106
106:     def self.subclasses
107:       @subclasses || (@subclasses = Support::TypedSet.new(Class))
108:     end

[Source]

    # File lib/data_mapper/persistence.rb, line 45
45:         def self.subclasses
46:           @subclasses || (@subclasses = Support::TypedSet.new(Class))
47:         end

[Source]

    # File lib/data_mapper/persistence.rb, line 45
45:         def self.subclasses
46:           @subclasses || (@subclasses = Support::TypedSet.new(Class))
47:         end

Public Instance methods

[Source]

     # File lib/data_mapper/persistence.rb, line 818
818:     def <=>(other)
819:       keys <=> other.keys
820:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 818
818:     def <=>(other)
819:       keys <=> other.keys
820:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 833
833:     def ==(other)
834:       eql?(other)
835:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 833
833:     def ==(other)
834:       eql?(other)
835:     end

Returns the difference between two objects, in terms of their attributes.

[Source]

     # File lib/data_mapper/persistence.rb, line 839
839:     def ^(other)
840:       results = {}
841: 
842:       self_attributes, other_attributes = attributes, other.attributes
843: 
844:       self_attributes.each_pair do |k,v|
845:         other_value = other_attributes[k]
846:         unless v == other_value
847:           results[k] = [v, other_value]
848:         end
849:       end
850: 
851:       results
852:     end

Returns the difference between two objects, in terms of their attributes.

[Source]

     # File lib/data_mapper/persistence.rb, line 839
839:     def ^(other)
840:       results = {}
841: 
842:       self_attributes, other_attributes = attributes, other.attributes
843: 
844:       self_attributes.each_pair do |k,v|
845:         other_value = other_attributes[k]
846:         unless v == other_value
847:           results[k] = [v, other_value]
848:         end
849:       end
850: 
851:       results
852:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 135
135:     def check_for_properties!
136:       raise IncompleteModelDefinitionError.new("Models must have at least one property to be initialized.") if self.class.properties.empty?
137:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 135
135:     def check_for_properties!
136:       raise IncompleteModelDefinitionError.new("Models must have at least one property to be initialized.") if self.class.properties.empty?
137:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 693
693:     def database_context
694:       @database_context || ( @database_context = database )
695:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 693
693:     def database_context
694:       @database_context || ( @database_context = database )
695:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 697
697:     def database_context=(value)
698:       @database_context = value
699:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 697
697:     def database_context=(value)
698:       @database_context = value
699:     end

Returns true if the unsaved model has had properties changed since it was loaded from the database. Returns false otherwise.

[Source]

     # File lib/data_mapper/persistence.rb, line 726
726:     def dirty?(cleared = Set.new)
727:       return false if cleared.include?(self)
728:       cleared << self
729: 
730:       result = database_context.table(self).columns.any? do |column|
731:         if column.type == :object
732:           Marshal.dump(self.instance_variable_get(column.instance_variable_name)) != original_values[column.name]
733:         else
734:           self.instance_variable_get(column.instance_variable_name) != original_values[column.name]
735:         end
736:       end
737: 
738:       return true if result
739: 
740:       loaded_associations.any? do |loaded_association|
741:         loaded_association.dirty?(cleared)
742:       end
743:     end

Returns true if the unsaved model has had properties changed since it was loaded from the database. Returns false otherwise.

[Source]

     # File lib/data_mapper/persistence.rb, line 726
726:     def dirty?(cleared = Set.new)
727:       return false if cleared.include?(self)
728:       cleared << self
729: 
730:       result = database_context.table(self).columns.any? do |column|
731:         if column.type == :object
732:           Marshal.dump(self.instance_variable_get(column.instance_variable_name)) != original_values[column.name]
733:         else
734:           self.instance_variable_get(column.instance_variable_name) != original_values[column.name]
735:         end
736:       end
737: 
738:       return true if result
739: 
740:       loaded_associations.any? do |loaded_association|
741:         loaded_association.dirty?(cleared)
742:       end
743:     end

For unsaved models, returns a hash of properties that have had their values changed since it was loaded from the database.

[Source]

     # File lib/data_mapper/persistence.rb, line 747
747:     def dirty_attributes
748:       pairs = {}
749: 
750:       database_context.table(self).columns.each do |column|
751:         value = instance_variable_get(column.instance_variable_name)
752:         if value != original_values[column.name] && (!new_record? || !column.serial?)
753:           pairs[column.name] = column.type != :object ? value : YAML.dump(value)
754:         end
755:       end
756: 
757:       pairs
758:     end

For unsaved models, returns a hash of properties that have had their values changed since it was loaded from the database.

[Source]

     # File lib/data_mapper/persistence.rb, line 747
747:     def dirty_attributes
748:       pairs = {}
749: 
750:       database_context.table(self).columns.each do |column|
751:         value = instance_variable_get(column.instance_variable_name)
752:         if value != original_values[column.name] && (!new_record? || !column.serial?)
753:           pairs[column.name] = column.type != :object ? value : YAML.dump(value)
754:         end
755:       end
756: 
757:       pairs
758:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 827
827:     def eql?(other)
828:       return false unless other.is_a?(self.class) || self.is_a?(other.class)
829:       comparator = keys.empty? ? :private_attributes : :keys
830:       send(comparator) == other.send(comparator)
831:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 827
827:     def eql?(other)
828:       return false unless other.is_a?(self.class) || self.is_a?(other.class)
829:       comparator = keys.empty? ? :private_attributes : :keys
830:       send(comparator) == other.send(comparator)
831:     end

Look to ::included for __hash alias

[Source]

     # File lib/data_mapper/persistence.rb, line 823
823:     def hash
824:       @__hash || @__hash = keys.empty? ? super : keys.hash
825:     end

Look to ::included for __hash alias

[Source]

     # File lib/data_mapper/persistence.rb, line 823
823:     def hash
824:       @__hash || @__hash = keys.empty? ? super : keys.hash
825:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 127
127:     def initialize_with_attributes(details)
128:       case details
129:       when Hash then self.attributes = details
130:       when details.respond_to?(:persistent?) then self.private_attributes = details.attributes
131:       when Struct then self.private_attributes = details.attributes
132:       end
133:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 127
127:     def initialize_with_attributes(details)
128:       case details
129:       when Hash then self.attributes = details
130:       when details.respond_to?(:persistent?) then self.private_attributes = details.attributes
131:       when Struct then self.private_attributes = details.attributes
132:       end
133:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 783
783:     def inspect
784:       inspected_attributes = attributes.map { |k,v| "@#{k}=#{v.inspect}" }
785: 
786:       instance_variables.each do |name|
787:         if instance_variable_get(name).kind_of?(Associations::HasManyAssociation)
788:           inspected_attributes << "#{name}=#{instance_variable_get(name).inspect}"
789:         end
790:       end
791: 
792:       "#<%s:0x%x @new_record=%s, %s>" % [self.class.name, (object_id * 2), new_record?, inspected_attributes.join(', ')]
793:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 783
783:     def inspect
784:       inspected_attributes = attributes.map { |k,v| "@#{k}=#{v.inspect}" }
785: 
786:       instance_variables.each do |name|
787:         if instance_variable_get(name).kind_of?(Associations::HasManyAssociation)
788:           inspected_attributes << "#{name}=#{instance_variable_get(name).inspect}"
789:         end
790:       end
791: 
792:       "#<%s:0x%x @new_record=%s, %s>" % [self.class.name, (object_id * 2), new_record?, inspected_attributes.join(', ')]
793:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 805
805:     def key
806:       @__key || @__key = begin
807:         key_column = database_context.table(self.class).key
808:         key_column.type_cast_value(instance_variable_get(key_column.instance_variable_name))
809:       end
810:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 805
805:     def key
806:       @__key || @__key = begin
807:         key_column = database_context.table(self.class).key
808:         key_column.type_cast_value(instance_variable_get(key_column.instance_variable_name))
809:       end
810:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 799
799:     def key=(value)
800:       key_column = database_context.table(self.class).key
801:       @__key = key_column.type_cast_value(value)
802:       instance_variable_set(key_column.instance_variable_name, @__key)
803:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 799
799:     def key=(value)
800:       key_column = database_context.table(self.class).key
801:       @__key = key_column.type_cast_value(value)
802:       instance_variable_set(key_column.instance_variable_name, @__key)
803:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 812
812:     def keys
813:       self.class.table.keys.map do |column|
814:         column.type_cast_value(instance_variable_get(column.instance_variable_name))
815:       end.compact
816:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 812
812:     def keys
813:       self.class.table.keys.map do |column|
814:         column.type_cast_value(instance_variable_get(column.instance_variable_name))
815:       end.compact
816:     end

Lazy-loads the attributes for a loaded_set, then overwrites the accessors for the named methods so that the lazy_loading is skipped the second time.

[Source]

     # File lib/data_mapper/persistence.rb, line 663
663:     def lazy_load!(*names)
664: 
665:       names = names.map { |name| name.to_sym }.reject { |name| lazy_loaded_attributes.include?(name) }
666: 
667:       reset_attribute = lambda do |instance|
668:         singleton_class = (class << instance; self end)
669:         names.each do |name|
670:           instance.lazy_loaded_attributes << name
671:           singleton_class.send(:attr_accessor, name)
672:         end
673:       end
674: 
675:       unless names.empty? || new_record? || loaded_set.nil?
676: 
677:         key = database_context.table(self.class).key.to_sym
678:         keys_to_select = loaded_set.map do |instance|
679:           instance.send(key)
680:         end
681: 
682:         database_context.all(
683:           self.class,
684:           :select => ([key] + names),
685:           :reload => true,
686:           key => keys_to_select
687:         ).each(&reset_attribute)
688:       else
689:         reset_attribute[self]
690:       end
691:     end

Lazy-loads the attributes for a loaded_set, then overwrites the accessors for the named methods so that the lazy_loading is skipped the second time.

[Source]

     # File lib/data_mapper/persistence.rb, line 663
663:     def lazy_load!(*names)
664: 
665:       names = names.map { |name| name.to_sym }.reject { |name| lazy_loaded_attributes.include?(name) }
666: 
667:       reset_attribute = lambda do |instance|
668:         singleton_class = (class << instance; self end)
669:         names.each do |name|
670:           instance.lazy_loaded_attributes << name
671:           singleton_class.send(:attr_accessor, name)
672:         end
673:       end
674: 
675:       unless names.empty? || new_record? || loaded_set.nil?
676: 
677:         key = database_context.table(self.class).key.to_sym
678:         keys_to_select = loaded_set.map do |instance|
679:           instance.send(key)
680:         end
681: 
682:         database_context.all(
683:           self.class,
684:           :select => ([key] + names),
685:           :reload => true,
686:           key => keys_to_select
687:         ).each(&reset_attribute)
688:       else
689:         reset_attribute[self]
690:       end
691:     end

Returns a Set containing the properties that have had their :lazy option set to true, or are lazily loaded by default — i.e. text fields.

[Source]

     # File lib/data_mapper/persistence.rb, line 714
714:     def lazy_loaded_attributes
715:       @lazy_loaded_attributes || @lazy_loaded_attributes = Set.new
716:     end

Returns a Set containing the properties that have had their :lazy option set to true, or are lazily loaded by default — i.e. text fields.

[Source]

     # File lib/data_mapper/persistence.rb, line 714
714:     def lazy_loaded_attributes
715:       @lazy_loaded_attributes || @lazy_loaded_attributes = Set.new
716:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 795
795:     def loaded_associations
796:       @loaded_associations || @loaded_associations = []
797:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 795
795:     def loaded_associations
796:       @loaded_associations || @loaded_associations = []
797:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 778
778:     def loaded_set=(value)
779:       value << self
780:       @loaded_set = value
781:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 778
778:     def loaded_set=(value)
779:       value << self
780:       @loaded_set = value
781:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 701
701:     def logger
702:       self.class.logger
703:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 701
701:     def logger
702:       self.class.logger
703:     end

Returns true if this model hasn‘t been saved to the database, false otherwise.

[Source]

     # File lib/data_mapper/persistence.rb, line 707
707:     def new_record?
708:       @new_record.nil? || @new_record
709:     end

Returns true if this model hasn‘t been saved to the database, false otherwise.

[Source]

     # File lib/data_mapper/persistence.rb, line 707
707:     def new_record?
708:       @new_record.nil? || @new_record
709:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 770
770:     def original_values
771:       class << self
772:         attr_reader :original_values
773:       end
774: 
775:       @original_values = {}
776:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 770
770:     def original_values
771:       class << self
772:         attr_reader :original_values
773:       end
774: 
775:       @original_values = {}
776:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 760
760:     def original_values=(values)
761:       values.each_pair do |k,v|
762:         original_values[k] = case v
763:                 when String, Date, Time then v.dup
764:                   # when column.type == :object then Marshal.dump(v)
765:                 else v
766:         end
767:       end
768:     end

[Source]

     # File lib/data_mapper/persistence.rb, line 760
760:     def original_values=(values)
761:       values.each_pair do |k,v|
762:         original_values[k] = case v
763:                 when String, Date, Time then v.dup
764:                   # when column.type == :object then Marshal.dump(v)
765:                 else v
766:         end
767:       end
768:     end

Accepts a hash of properties and values to be updated and then calls save

[Source]

     # File lib/data_mapper/persistence.rb, line 719
719:     def update_attributes(update_hash)
720:       self.attributes = update_hash
721:       self.save
722:     end

Accepts a hash of properties and values to be updated and then calls save

[Source]

     # File lib/data_mapper/persistence.rb, line 719
719:     def update_attributes(update_hash)
720:       self.attributes = update_hash
721:       self.save
722:     end

[Validate]