Module: DataMapper::Resource
- Includes:
- Assertions
- Defined in:
- lib/dm-core/resource.rb,
lib/dm-core/resource/state.rb,
lib/dm-core/resource/state/clean.rb,
lib/dm-core/resource/state/dirty.rb,
lib/dm-core/resource/state/deleted.rb,
lib/dm-core/resource/state/immutable.rb,
lib/dm-core/resource/state/persisted.rb,
lib/dm-core/resource/state/transient.rb
Defined Under Namespace
Classes: State
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.
-
#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).
-
#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.
-
#persisted_state ⇒ Resource::State
private
Get the persisted state for the resource.
-
#persisted_state=(state) ⇒ undefined
private
Set the persisted state for the resource.
-
#persisted_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 Chainable
Methods included from Deprecate
Methods included from Assertions
Class Method Details
.append_inclusions(*inclusions) ⇒ Object
13 14 15 16 |
# File 'lib/dm-core/resource.rb', line 13 def self.append_inclusions(*inclusions) warn "DataMapper::Resource.append_inclusions is deprecated, use DataMapper::Model.append_inclusions instead (#{caller[0]})" Model.append_inclusions(*inclusions) end |
.descendants ⇒ Object
25 26 27 28 |
# File 'lib/dm-core/resource.rb', line 25 def self.descendants warn "DataMapper::Resource.descendants is deprecated, use DataMapper::Model.descendants instead (#{caller[0]})" Model.descendants end |
.extra_inclusions ⇒ Object
19 20 21 22 |
# File 'lib/dm-core/resource.rb', line 19 def self.extra_inclusions warn "DataMapper::Resource.extra_inclusions is deprecated, use DataMapper::Model.extra_inclusions instead (#{caller[0]})" Model.extra_inclusions 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
85 86 87 |
# File 'lib/dm-core/resource.rb', line 85 def self.included(model) model.extend Model end |
Instance Method Details
#<=>(other) ⇒ Integer
Compares two Resources to allow them to be sorted
510 511 512 513 514 515 516 517 518 519 520 |
# File 'lib/dm-core/resource.rb', line 510 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
493 494 495 496 497 |
# File 'lib/dm-core/resource.rb', line 493 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 |
#attribute_dirty?(name) ⇒ Boolean
Checks if an attribute has unsaved changes
605 606 607 |
# File 'lib/dm-core/resource.rb', line 605 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.
253 254 255 |
# File 'lib/dm-core/resource.rb', line 253 def attribute_get(name) persisted_state.get(properties[name]) 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
592 593 594 |
# File 'lib/dm-core/resource.rb', line 592 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.
294 295 296 |
# File 'lib/dm-core/resource.rb', line 294 def attribute_set(name, value) self.persisted_state = persisted_state.set(properties[name], value) end |
#attributes(key_on = :name) ⇒ Hash
Gets all the attributes of the Resource instance
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
# File 'lib/dm-core/resource.rb', line 311 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)
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 |
# File 'lib/dm-core/resource.rb', line 339 def attributes=(attributes) model = self.model attributes.each do |name, value| case name when String, Symbol if model.public_method_defined?(setter = "#{name}=") __send__(setter, value) else raise ArgumentError, "The attribute '#{name}' is not accessible in #{model}" end when Associations::Relationship, Property self.persisted_state = persisted_state.set(name, value) end end end |
#clean? ⇒ Boolean
Checks if the resource has no changes to save
196 197 198 |
# File 'lib/dm-core/resource.rb', line 196 def clean? persisted_state.kind_of?(State::Clean) || persisted_state.kind_of?(State::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
634 635 636 637 |
# File 'lib/dm-core/resource.rb', line 634 def collection return @_collection if (@_collection && @_collection.query.conditions.matches?(self)) || 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
650 651 652 |
# File 'lib/dm-core/resource.rb', line 650 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
660 661 662 |
# File 'lib/dm-core/resource.rb', line 660 def collection_for_self Collection.new(query, [ self ]) end |
#destroy ⇒ Boolean
Destroy the instance, remove it from the repository
441 442 443 444 445 446 447 448 449 |
# File 'lib/dm-core/resource.rb', line 441 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
457 458 459 460 461 |
# File 'lib/dm-core/resource.rb', line 457 def destroy! return true if destroyed? _destroy(false) destroyed? end |
#destroyed? ⇒ Boolean
Checks if this Resource instance is destroyed
186 187 188 |
# File 'lib/dm-core/resource.rb', line 186 def destroyed? readonly? && !key.nil? end |
#dirty? ⇒ Boolean
Checks if the resource has unsaved changes
206 207 208 209 210 |
# File 'lib/dm-core/resource.rb', line 206 def dirty? run_once(true) do dirty_self? || dirty_parents? || dirty_children? end end |
#dirty_attributes ⇒ Hash
Hash of attributes that have unsaved changes
615 616 617 618 619 620 621 622 623 624 |
# File 'lib/dm-core/resource.rb', line 615 def dirty_attributes dirty_attributes = {} original_attributes.each_key do |property| next unless property.respond_to?(:value) 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
476 477 478 479 |
# File 'lib/dm-core/resource.rb', line 476 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
532 533 534 |
# File 'lib/dm-core/resource.rb', line 532 def 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>
544 545 546 547 548 549 550 551 552 553 554 555 556 557 |
# File 'lib/dm-core/resource.rb', line 544 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.
147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/dm-core/resource.rb', line 147 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
166 167 168 |
# File 'lib/dm-core/resource.rb', line 166 def new? persisted_state.kind_of?(State::Transient) end |
#original_attributes ⇒ Hash
Hash of original values of attributes that have unsaved changes
565 566 567 568 569 570 571 |
# File 'lib/dm-core/resource.rb', line 565 def original_attributes if persisted_state.respond_to?(:original_attributes) persisted_state.original_attributes.dup.freeze else {}.freeze end end |
#persisted_state ⇒ Resource::State
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
98 99 100 |
# File 'lib/dm-core/resource.rb', line 98 def persisted_state @_state ||= Resource::State::Transient.new(self) end |
#persisted_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
110 111 112 |
# File 'lib/dm-core/resource.rb', line 110 def persisted_state=(state) @_state = state end |
#persisted_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
120 121 122 |
# File 'lib/dm-core/resource.rb', line 120 def persisted_state? defined?(@_state) ? true : false end |
#query ⇒ Query
Returns a Query that will match the resource
670 671 672 |
# File 'lib/dm-core/resource.rb', line 670 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
40 41 42 43 44 45 46 |
# File 'lib/dm-core/resource.rb', line 40 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)
57 58 59 |
# File 'lib/dm-core/resource.rb', line 57 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
218 219 220 |
# File 'lib/dm-core/resource.rb', line 218 def readonly? persisted_state.kind_of?(State::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 is more consistent behavior since no cached results will remain from the initial load.
368 369 370 371 372 373 374 375 376 377 |
# File 'lib/dm-core/resource.rb', line 368 def reload if key reset_key clear_subjects end self.persisted_state = persisted_state.rollback self end |
#repository ⇒ Repository
Repository this resource belongs to in the context of this collection or of the resource’s class.
132 133 134 135 |
# File 'lib/dm-core/resource.rb', line 132 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
415 416 417 418 419 420 |
# File 'lib/dm-core/resource.rb', line 415 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
428 429 430 431 432 433 |
# File 'lib/dm-core/resource.rb', line 428 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
176 177 178 |
# File 'lib/dm-core/resource.rb', line 176 def saved? persisted_state.kind_of?(State::Persisted) end |
#update(attributes) ⇒ Boolean
Updates attributes and saves this Resource instance
388 389 390 391 392 |
# File 'lib/dm-core/resource.rb', line 388 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
403 404 405 406 407 |
# File 'lib/dm-core/resource.rb', line 403 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
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/dm-core/resource.rb', line 66 def update_attributes(attributes = {}, *allowed) model = self.model call_stack = caller[0] warn "#{model}#update_attributes is deprecated, use #{model}#update instead (#{call_stack})" if allowed.any? warn "specifying allowed in #{model}#update_attributes is deprecated, " \ "use Hash#only to filter the attributes in the caller (#{call_stack})" attributes = attributes.only(*allowed) end assert_update_clean_only(:update_attributes) update(attributes) end |