Module: DataMapper::Resource
- Extended by:
- Deprecate
- Includes:
- Assertions
- Defined in:
- lib/dm-core/resource.rb,
lib/dm-core/backwards.rb,
lib/dm-core/resource/persistence_state.rb,
lib/dm-core/resource/persistence_state/clean.rb,
lib/dm-core/resource/persistence_state/dirty.rb,
lib/dm-core/resource/persistence_state/deleted.rb,
lib/dm-core/resource/persistence_state/immutable.rb,
lib/dm-core/resource/persistence_state/persisted.rb,
lib/dm-core/resource/persistence_state/transient.rb
Defined Under Namespace
Classes: PersistenceState
Class Method Summary collapse
- .append_inclusions(*inclusions) ⇒ Object deprecated Deprecated.
- .descendants ⇒ Object deprecated Deprecated.
- .extra_inclusions ⇒ Object deprecated Deprecated.
-
.included(model) ⇒ Object
private
Makes sure a class gets all the methods when it includes Resource.
Instance Method Summary collapse
-
#<=>(other) ⇒ Integer
Compares two Resources to allow them to be sorted.
-
#==(other) ⇒ Boolean
Compares another Resource for equivalency.
-
#after_create_hook ⇒ undefined
protected
private
Method for hooking callbacks after resource creation.
-
#after_destroy_hook ⇒ undefined
protected
private
Method for hooking callbacks after resource destruction.
-
#after_save_hook ⇒ undefined
protected
private
Method for hooking callbacks after resource saving.
-
#after_update_hook ⇒ undefined
protected
private
Method for hooking callbacks after resource updating.
-
#attribute_dirty?(name) ⇒ Boolean
Checks if an attribute has unsaved changes.
-
#attribute_get(name) ⇒ Object
(also: #[])
Returns the value of the attribute.
-
#attribute_loaded?(name) ⇒ Boolean
private
Checks if an attribute has been loaded from the repository.
-
#attribute_set(name, value) ⇒ undefined
(also: #[]=)
Sets the value of the attribute and marks the attribute as dirty if it has been changed so that it may be saved.
-
#attributes(key_on = :name) ⇒ Hash
Gets all the attributes of the Resource instance.
-
#attributes=(attributes) ⇒ Hash
Assign values to multiple attributes in one call (mass assignment).
-
#before_create_hook ⇒ undefined
protected
private
Method for hooking callbacks before resource creation.
-
#before_destroy_hook ⇒ undefined
protected
private
Method for hooking callbacks before resource destruction.
-
#before_save_hook ⇒ undefined
protected
private
Method for hooking callbacks before resource saving.
-
#before_update_hook ⇒ undefined
protected
private
Method for hooking callbacks before resource updating.
-
#clean? ⇒ Boolean
Checks if the resource has no changes to save.
-
#collection ⇒ nil, Collection
private
Returns the Collection the Resource is associated with.
-
#collection=(collection) ⇒ nil, Collection
private
Associates a Resource to a Collection.
-
#collection_for_self ⇒ Collection
private
Return a collection including the current resource only.
-
#destroy ⇒ Boolean
Destroy the instance, remove it from the repository.
-
#destroy! ⇒ Boolean
Destroy the instance, remove it from the repository, bypassing hooks.
-
#destroyed? ⇒ Boolean
Checks if this Resource instance is destroyed.
-
#dirty? ⇒ Boolean
Checks if the resource has unsaved changes.
-
#dirty_attributes ⇒ Hash
Hash of attributes that have unsaved changes.
-
#eql?(other) ⇒ Boolean
Compares another Resource for equality.
-
#hash ⇒ Object
private
Returns hash value of the object.
-
#inspect ⇒ String
Get a Human-readable representation of this Resource instance.
-
#key ⇒ Array(Key)
Retrieve the key(s) for this resource.
-
#new? ⇒ Boolean
Checks if this Resource instance is new.
-
#original_attributes ⇒ Hash
Hash of original values of attributes that have unsaved changes.
-
#persistence_state ⇒ Resource::PersistenceState
private
Get the persisted state for the resource.
-
#persistence_state=(state) ⇒ undefined
private
Set the persisted state for the resource.
-
#persistence_state? ⇒ Boolean
private
Test if the persisted state is set.
-
#query ⇒ Query
Returns a Query that will match the resource.
-
#raise_on_save_failure ⇒ Boolean
Return if Resource#save should raise an exception on save failures (per-resource).
-
#raise_on_save_failure=(raise_on_save_failure) ⇒ Boolean
Specify if Resource#save should raise an exception on save failures (per-resource).
-
#readonly? ⇒ Boolean
Checks if this Resource instance is readonly.
-
#reload ⇒ Resource
Reloads association and all child association.
-
#repository ⇒ Repository
Repository this resource belongs to in the context of this collection or of the resource’s class.
-
#save ⇒ Boolean
Save the instance and loaded, dirty associations to the data-store.
-
#save! ⇒ Boolean
Save the instance and loaded, dirty associations to the data-store, bypassing hooks.
-
#saved? ⇒ Boolean
Checks if this Resource instance is saved.
-
#update(attributes) ⇒ Boolean
Updates attributes and saves this Resource instance.
-
#update!(attributes) ⇒ Boolean
Updates attributes and saves this Resource instance, bypassing hooks.
- #update_attributes(attributes = {}, *allowed) ⇒ Object deprecated Deprecated.
Methods included from Deprecate
Methods included from Assertions
Class Method Details
.append_inclusions(*inclusions) ⇒ Object
6 7 8 |
# File 'lib/dm-core/resource.rb', line 6 def self.append_inclusions(*inclusions) raise "DataMapper::Resource.append_inclusions is deprecated, use DataMapper::Model.append_inclusions instead (#{caller.first})" end |
.descendants ⇒ Object
16 17 18 |
# File 'lib/dm-core/resource.rb', line 16 def self.descendants raise "DataMapper::Resource.descendants is deprecated, use DataMapper::Model.descendants instead (#{caller.first})" end |
.extra_inclusions ⇒ Object
11 12 13 |
# File 'lib/dm-core/resource.rb', line 11 def self.extra_inclusions raise "DataMapper::Resource.extra_inclusions is deprecated, use DataMapper::Model.extra_inclusions instead (#{caller.first})" end |
.included(model) ⇒ Object
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.
Makes sure a class gets all the methods when it includes Resource
Note that including this module into an anonymous class will leave the model descendant tracking mechanism with no possibility to reliably track the anonymous model across code reloads. This means that DescendantSet will currently leak memory in scenarios where anonymous models are reloaded multiple times (as is the case in dm-rails development mode for example).
70 71 72 |
# File 'lib/dm-core/resource.rb', line 70 def self.included(model) model.extend Model end |
Instance Method Details
#<=>(other) ⇒ Integer
Compares two Resources to allow them to be sorted
505 506 507 508 509 510 511 512 513 514 515 |
# File 'lib/dm-core/resource.rb', line 505 def <=>(other) model = self.model unless other.kind_of?(model.base_model) raise ArgumentError, "Cannot compare a #{other.class} instance with a #{model} instance" end model.default_order(repository_name).each do |direction| cmp = direction.get(self) <=> direction.get(other) return cmp if cmp.nonzero? end 0 end |
#==(other) ⇒ Boolean
Compares another Resource for equivalency
Resource is equivalent to other
if they are the same object (identical object_id) or all of their attribute are equivalent
488 489 490 491 492 |
# File 'lib/dm-core/resource.rb', line 488 def ==(other) return true if equal?(other) return false unless other.kind_of?(Resource) && model.base_model.equal?(other.model.base_model) cmp?(other, :==) end |
#after_create_hook ⇒ undefined (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.
Method for hooking callbacks after resource creation
703 704 705 |
# File 'lib/dm-core/resource.rb', line 703 def after_create_hook execute_hooks_for(:after, :create) end |
#after_destroy_hook ⇒ undefined (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.
Method for hooking callbacks after resource destruction
739 740 741 |
# File 'lib/dm-core/resource.rb', line 739 def after_destroy_hook execute_hooks_for(:after, :destroy) end |
#after_save_hook ⇒ undefined (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.
Method for hooking callbacks after resource saving
685 686 687 |
# File 'lib/dm-core/resource.rb', line 685 def after_save_hook execute_hooks_for(:after, :save) end |
#after_update_hook ⇒ undefined (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.
Method for hooking callbacks after resource updating
721 722 723 |
# File 'lib/dm-core/resource.rb', line 721 def after_update_hook execute_hooks_for(:after, :update) end |
#attribute_dirty?(name) ⇒ Boolean
Checks if an attribute has unsaved changes
600 601 602 |
# File 'lib/dm-core/resource.rb', line 600 def attribute_dirty?(name) dirty_attributes.key?(properties[name]) end |
#attribute_get(name) ⇒ Object Also known as: []
Returns the value of the attribute.
Do not read from instance variables directly, but use this method. This method handles lazy loading the attribute and returning of defaults if nessesary.
239 240 241 242 |
# File 'lib/dm-core/resource.rb', line 239 def attribute_get(name) property = properties[name] persistence_state.get(property) if property end |
#attribute_loaded?(name) ⇒ Boolean
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.
Checks if an attribute has been loaded from the repository
587 588 589 |
# File 'lib/dm-core/resource.rb', line 587 def attribute_loaded?(name) properties[name].loaded?(self) end |
#attribute_set(name, value) ⇒ undefined Also known as: []=
Sets the value of the attribute and marks the attribute as dirty if it has been changed so that it may be saved. Do not set from instance variables directly, but use this method. This method handles the lazy loading the property and returning of defaults if nessesary.
281 282 283 284 285 286 287 |
# File 'lib/dm-core/resource.rb', line 281 def attribute_set(name, value) property = properties[name] if property value = property.typecast(value) self.persistence_state = persistence_state.set(property, value) end end |
#attributes(key_on = :name) ⇒ Hash
Gets all the attributes of the Resource instance
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 |
# File 'lib/dm-core/resource.rb', line 302 def attributes(key_on = :name) attributes = {} lazy_load(properties) fields.each do |property| if model.public_method_defined?(name = property.name) key = case key_on when :name then name when :field then property.field else property end attributes[key] = __send__(name) end end attributes end |
#attributes=(attributes) ⇒ Hash
Assign values to multiple attributes in one call (mass assignment)
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 |
# File 'lib/dm-core/resource.rb', line 330 def attributes=(attributes) model = self.model attributes.each do |name, value| case name when String, Symbol if model.allowed_writer_methods.include?(setter = "#{name}=") __send__(setter, value) else raise ArgumentError, "The attribute '#{name}' is not accessible in #{model}" end when Associations::Relationship, Property # only call a public #typecast (e.g. on Property instances) if name.respond_to?(:typecast) value = name.typecast(value) end self.persistence_state = persistence_state.set(name, value) end end end |
#before_create_hook ⇒ undefined (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.
Method for hooking callbacks before resource creation
694 695 696 |
# File 'lib/dm-core/resource.rb', line 694 def before_create_hook execute_hooks_for(:before, :create) end |
#before_destroy_hook ⇒ undefined (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.
Method for hooking callbacks before resource destruction
730 731 732 |
# File 'lib/dm-core/resource.rb', line 730 def before_destroy_hook execute_hooks_for(:before, :destroy) end |
#before_save_hook ⇒ undefined (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.
Method for hooking callbacks before resource saving
676 677 678 |
# File 'lib/dm-core/resource.rb', line 676 def before_save_hook execute_hooks_for(:before, :save) end |
#before_update_hook ⇒ undefined (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.
Method for hooking callbacks before resource updating
712 713 714 |
# File 'lib/dm-core/resource.rb', line 712 def before_update_hook execute_hooks_for(:before, :update) end |
#clean? ⇒ Boolean
Checks if the resource has no changes to save
181 182 183 184 |
# File 'lib/dm-core/resource.rb', line 181 def clean? persistence_state.kind_of?(PersistenceState::Clean) || persistence_state.kind_of?(PersistenceState::Immutable) end |
#collection ⇒ nil, Collection
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.
Returns the Collection the Resource is associated with
629 630 631 632 |
# File 'lib/dm-core/resource.rb', line 629 def collection return @_collection if @_collection || new? || readonly? collection_for_self end |
#collection=(collection) ⇒ nil, Collection
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.
Associates a Resource to a Collection
645 646 647 |
# File 'lib/dm-core/resource.rb', line 645 def collection=(collection) @_collection = collection end |
#collection_for_self ⇒ Collection
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.
Return a collection including the current resource only
655 656 657 |
# File 'lib/dm-core/resource.rb', line 655 def collection_for_self Collection.new(query, [ self ]) end |
#destroy ⇒ Boolean
Destroy the instance, remove it from the repository
436 437 438 439 440 441 442 443 444 |
# File 'lib/dm-core/resource.rb', line 436 def destroy return true if destroyed? catch :halt do before_destroy_hook _destroy after_destroy_hook end destroyed? end |
#destroy! ⇒ Boolean
Destroy the instance, remove it from the repository, bypassing hooks
452 453 454 455 456 |
# File 'lib/dm-core/resource.rb', line 452 def destroy! return true if destroyed? _destroy(false) destroyed? end |
#destroyed? ⇒ Boolean
Checks if this Resource instance is destroyed
171 172 173 |
# File 'lib/dm-core/resource.rb', line 171 def destroyed? readonly? && !key.nil? end |
#dirty? ⇒ Boolean
Checks if the resource has unsaved changes
192 193 194 195 196 |
# File 'lib/dm-core/resource.rb', line 192 def dirty? run_once(true) do dirty_self? || dirty_parents? || dirty_children? end end |
#dirty_attributes ⇒ Hash
Hash of attributes that have unsaved changes
610 611 612 613 614 615 616 617 618 619 |
# File 'lib/dm-core/resource.rb', line 610 def dirty_attributes dirty_attributes = {} original_attributes.each_key do |property| next unless property.respond_to?(:dump) dirty_attributes[property] = property.dump(property.get!(self)) end dirty_attributes end |
#eql?(other) ⇒ Boolean
Compares another Resource for equality
Resource is equal to other
if they are the same object (identical object_id) or if they are both of the *same model* and all of their attributes are equivalent
471 472 473 474 |
# File 'lib/dm-core/resource.rb', line 471 def eql?(other) return true if equal?(other) instance_of?(other.class) && cmp?(other, :eql?) end |
#hash ⇒ Object
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.
Returns hash value of the object. Two objects with the same hash value assumed equal (using eql? method)
DataMapper resources are equal when their models have the same hash and they have the same set of properties
When used as key in a Hash or Hash subclass, objects are compared by eql? and thus hash value has direct effect on lookup
527 528 529 |
# File 'lib/dm-core/resource.rb', line 527 def hash model.hash ^ key.hash end |
#inspect ⇒ String
Get a Human-readable representation of this Resource instance
Foo.new #=> #<Foo name=nil updated_at=nil created_at=nil id=nil>
539 540 541 542 543 544 545 546 547 548 549 550 551 552 |
# File 'lib/dm-core/resource.rb', line 539 def inspect # TODO: display relationship values attrs = properties.map do |property| value = if new? || property.loaded?(self) property.get!(self).inspect else '<not loaded>' end "#{property.instance_variable_name}=#{value}" end "#<#{model.name} #{attrs.join(' ')}>" end |
#key ⇒ Array(Key)
Retrieve the key(s) for this resource.
This always returns the persisted key value, even if the key is changed and not yet persisted. This is done so all relations still work.
132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/dm-core/resource.rb', line 132 def key return @_key if defined?(@_key) model_key = model.key(repository_name) key = model_key.map do |property| original_attributes[property] || (property.loaded?(self) ? property.get!(self) : nil) end # only memoize a valid key @_key = key if model_key.valid?(key) end |
#new? ⇒ Boolean
Checks if this Resource instance is new
151 152 153 |
# File 'lib/dm-core/resource.rb', line 151 def new? persistence_state.kind_of?(PersistenceState::Transient) end |
#original_attributes ⇒ Hash
Hash of original values of attributes that have unsaved changes
560 561 562 563 564 565 566 |
# File 'lib/dm-core/resource.rb', line 560 def original_attributes if persistence_state.respond_to?(:original_attributes) persistence_state.original_attributes.dup.freeze else {}.freeze end end |
#persistence_state ⇒ Resource::PersistenceState
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.
Get the persisted state for the resource
83 84 85 |
# File 'lib/dm-core/resource.rb', line 83 def persistence_state @_persistence_state ||= Resource::PersistenceState::Transient.new(self) end |
#persistence_state=(state) ⇒ undefined
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 persisted state for the resource
95 96 97 |
# File 'lib/dm-core/resource.rb', line 95 def persistence_state=(state) @_persistence_state = state end |
#persistence_state? ⇒ Boolean
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.
Test if the persisted state is set
105 106 107 |
# File 'lib/dm-core/resource.rb', line 105 def persistence_state? defined?(@_persistence_state) ? true : false end |
#query ⇒ Query
Returns a Query that will match the resource
665 666 667 |
# File 'lib/dm-core/resource.rb', line 665 def query repository.new_query(model, :fields => fields, :conditions => conditions) end |
#raise_on_save_failure ⇒ Boolean
Return if Resource#save should raise an exception on save failures (per-resource)
This delegates to model.raise_on_save_failure by default.
user.raise_on_save_failure # => false
30 31 32 33 34 35 36 |
# File 'lib/dm-core/resource.rb', line 30 def raise_on_save_failure if defined?(@raise_on_save_failure) @raise_on_save_failure else model.raise_on_save_failure end end |
#raise_on_save_failure=(raise_on_save_failure) ⇒ Boolean
Specify if Resource#save should raise an exception on save failures (per-resource)
47 48 49 |
# File 'lib/dm-core/resource.rb', line 47 def raise_on_save_failure=(raise_on_save_failure) @raise_on_save_failure = raise_on_save_failure end |
#readonly? ⇒ Boolean
Checks if this Resource instance is readonly
204 205 206 |
# File 'lib/dm-core/resource.rb', line 204 def readonly? persistence_state.kind_of?(PersistenceState::Immutable) end |
#reload ⇒ Resource
Reloads association and all child association
This is accomplished by resetting the Resource key to it’s original value, and then removing all the ivars for properties and relationships. On the next access of those ivars, the resource will eager load what it needs. While this is more of a lazy reload, it should result in more consistent behavior since no cached results will remain from the initial load.
363 364 365 366 367 368 369 370 371 372 |
# File 'lib/dm-core/resource.rb', line 363 def reload if key reset_key clear_subjects end self.persistence_state = persistence_state.rollback self end |
#repository ⇒ Repository
Repository this resource belongs to in the context of this collection or of the resource’s class.
117 118 119 120 |
# File 'lib/dm-core/resource.rb', line 117 def repository # only set @_repository explicitly when persisted defined?(@_repository) ? @_repository : model.repository end |
#save ⇒ Boolean
Save the instance and loaded, dirty associations to the data-store
410 411 412 413 414 415 |
# File 'lib/dm-core/resource.rb', line 410 def save assert_not_destroyed(:save) retval = _save assert_save_successful(:save, retval) retval end |
#save! ⇒ Boolean
Save the instance and loaded, dirty associations to the data-store, bypassing hooks
423 424 425 426 427 428 |
# File 'lib/dm-core/resource.rb', line 423 def save! assert_not_destroyed(:save!) retval = _save(false) assert_save_successful(:save!, retval) retval end |
#saved? ⇒ Boolean
Checks if this Resource instance is saved
161 162 163 |
# File 'lib/dm-core/resource.rb', line 161 def saved? persistence_state.kind_of?(PersistenceState::Persisted) end |
#update(attributes) ⇒ Boolean
Updates attributes and saves this Resource instance
383 384 385 386 387 |
# File 'lib/dm-core/resource.rb', line 383 def update(attributes) assert_update_clean_only(:update) self.attributes = attributes save end |
#update!(attributes) ⇒ Boolean
Updates attributes and saves this Resource instance, bypassing hooks
398 399 400 401 402 |
# File 'lib/dm-core/resource.rb', line 398 def update!(attributes) assert_update_clean_only(:update!) self.attributes = attributes save! end |
#update_attributes(attributes = {}, *allowed) ⇒ Object
Deprecated API for updating attributes and saving Resource
56 57 58 |
# File 'lib/dm-core/resource.rb', line 56 def update_attributes(attributes = {}, *allowed) raise "#{model}#update_attributes is deprecated, use #{model}#update instead (#{caller.first})" end |