sbf-dm-core 1.3.0.beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.autotest +29 -0
- data/.document +5 -0
- data/.gitignore +44 -0
- data/.rspec +1 -0
- data/.rubocop.yml +468 -0
- data/.travis.yml +57 -0
- data/.yardopts +1 -0
- data/Gemfile +70 -0
- data/LICENSE +20 -0
- data/README.md +269 -0
- data/Rakefile +4 -0
- data/dm-core.gemspec +21 -0
- data/lib/dm-core/adapters/abstract_adapter.rb +233 -0
- data/lib/dm-core/adapters/in_memory_adapter.rb +110 -0
- data/lib/dm-core/adapters.rb +249 -0
- data/lib/dm-core/associations/many_to_many.rb +477 -0
- data/lib/dm-core/associations/many_to_one.rb +282 -0
- data/lib/dm-core/associations/one_to_many.rb +332 -0
- data/lib/dm-core/associations/one_to_one.rb +84 -0
- data/lib/dm-core/associations/relationship.rb +650 -0
- data/lib/dm-core/backwards.rb +11 -0
- data/lib/dm-core/collection.rb +1486 -0
- data/lib/dm-core/core_ext/kernel.rb +21 -0
- data/lib/dm-core/core_ext/pathname.rb +4 -0
- data/lib/dm-core/core_ext/symbol.rb +10 -0
- data/lib/dm-core/identity_map.rb +6 -0
- data/lib/dm-core/model/hook.rb +99 -0
- data/lib/dm-core/model/is.rb +30 -0
- data/lib/dm-core/model/property.rb +244 -0
- data/lib/dm-core/model/relationship.rb +366 -0
- data/lib/dm-core/model/scope.rb +87 -0
- data/lib/dm-core/model.rb +876 -0
- data/lib/dm-core/property/binary.rb +19 -0
- data/lib/dm-core/property/boolean.rb +35 -0
- data/lib/dm-core/property/class.rb +23 -0
- data/lib/dm-core/property/date.rb +45 -0
- data/lib/dm-core/property/date_time.rb +44 -0
- data/lib/dm-core/property/decimal.rb +47 -0
- data/lib/dm-core/property/discriminator.rb +40 -0
- data/lib/dm-core/property/float.rb +27 -0
- data/lib/dm-core/property/integer.rb +32 -0
- data/lib/dm-core/property/invalid_value_error.rb +17 -0
- data/lib/dm-core/property/lookup.rb +26 -0
- data/lib/dm-core/property/numeric.rb +35 -0
- data/lib/dm-core/property/object.rb +33 -0
- data/lib/dm-core/property/serial.rb +13 -0
- data/lib/dm-core/property/string.rb +47 -0
- data/lib/dm-core/property/text.rb +12 -0
- data/lib/dm-core/property/time.rb +46 -0
- data/lib/dm-core/property/typecast/numeric.rb +32 -0
- data/lib/dm-core/property/typecast/time.rb +33 -0
- data/lib/dm-core/property.rb +856 -0
- data/lib/dm-core/property_set.rb +177 -0
- data/lib/dm-core/query/conditions/comparison.rb +886 -0
- data/lib/dm-core/query/conditions/operation.rb +710 -0
- data/lib/dm-core/query/direction.rb +33 -0
- data/lib/dm-core/query/operator.rb +34 -0
- data/lib/dm-core/query/path.rb +113 -0
- data/lib/dm-core/query/sort.rb +38 -0
- data/lib/dm-core/query.rb +1352 -0
- data/lib/dm-core/relationship_set.rb +69 -0
- data/lib/dm-core/repository.rb +226 -0
- data/lib/dm-core/resource/persistence_state/clean.rb +36 -0
- data/lib/dm-core/resource/persistence_state/deleted.rb +26 -0
- data/lib/dm-core/resource/persistence_state/dirty.rb +91 -0
- data/lib/dm-core/resource/persistence_state/immutable.rb +32 -0
- data/lib/dm-core/resource/persistence_state/persisted.rb +25 -0
- data/lib/dm-core/resource/persistence_state/transient.rb +87 -0
- data/lib/dm-core/resource/persistence_state.rb +70 -0
- data/lib/dm-core/resource.rb +1220 -0
- data/lib/dm-core/spec/lib/adapter_helpers.rb +63 -0
- data/lib/dm-core/spec/lib/collection_helpers.rb +21 -0
- data/lib/dm-core/spec/lib/counter_adapter.rb +38 -0
- data/lib/dm-core/spec/lib/pending_helpers.rb +50 -0
- data/lib/dm-core/spec/lib/spec_helper.rb +74 -0
- data/lib/dm-core/spec/setup.rb +164 -0
- data/lib/dm-core/spec/shared/adapter_spec.rb +366 -0
- data/lib/dm-core/spec/shared/public/property_spec.rb +229 -0
- data/lib/dm-core/spec/shared/resource_spec.rb +1221 -0
- data/lib/dm-core/spec/shared/sel_spec.rb +111 -0
- data/lib/dm-core/spec/shared/semipublic/property_spec.rb +184 -0
- data/lib/dm-core/spec/shared/semipublic/query/conditions/abstract_comparison_spec.rb +261 -0
- data/lib/dm-core/support/assertions.rb +8 -0
- data/lib/dm-core/support/chainable.rb +18 -0
- data/lib/dm-core/support/deprecate.rb +12 -0
- data/lib/dm-core/support/descendant_set.rb +89 -0
- data/lib/dm-core/support/equalizer.rb +48 -0
- data/lib/dm-core/support/ext/array.rb +22 -0
- data/lib/dm-core/support/ext/blank.rb +25 -0
- data/lib/dm-core/support/ext/hash.rb +67 -0
- data/lib/dm-core/support/ext/module.rb +47 -0
- data/lib/dm-core/support/ext/object.rb +57 -0
- data/lib/dm-core/support/ext/string.rb +24 -0
- data/lib/dm-core/support/ext/try_dup.rb +12 -0
- data/lib/dm-core/support/hook.rb +388 -0
- data/lib/dm-core/support/inflections.rb +60 -0
- data/lib/dm-core/support/inflector/inflections.rb +211 -0
- data/lib/dm-core/support/inflector/methods.rb +151 -0
- data/lib/dm-core/support/lazy_array.rb +451 -0
- data/lib/dm-core/support/local_object_space.rb +13 -0
- data/lib/dm-core/support/logger.rb +201 -0
- data/lib/dm-core/support/mash.rb +176 -0
- data/lib/dm-core/support/naming_conventions.rb +109 -0
- data/lib/dm-core/support/ordered_set.rb +381 -0
- data/lib/dm-core/support/subject.rb +33 -0
- data/lib/dm-core/support/subject_set.rb +251 -0
- data/lib/dm-core/version.rb +3 -0
- data/lib/dm-core.rb +274 -0
- data/script/performance.rb +275 -0
- data/script/profile.rb +218 -0
- data/spec/lib/rspec_immediate_feedback_formatter.rb +54 -0
- data/spec/public/associations/many_to_many/read_multiple_join_spec.rb +69 -0
- data/spec/public/associations/many_to_many_spec.rb +197 -0
- data/spec/public/associations/many_to_one_spec.rb +83 -0
- data/spec/public/associations/many_to_one_with_boolean_cpk_spec.rb +40 -0
- data/spec/public/associations/many_to_one_with_custom_fk_spec.rb +49 -0
- data/spec/public/associations/one_to_many_spec.rb +81 -0
- data/spec/public/associations/one_to_one_spec.rb +176 -0
- data/spec/public/associations/one_to_one_with_boolean_cpk_spec.rb +46 -0
- data/spec/public/collection_spec.rb +69 -0
- data/spec/public/finalize_spec.rb +77 -0
- data/spec/public/model/hook_spec.rb +245 -0
- data/spec/public/model/property_spec.rb +91 -0
- data/spec/public/model/relationship_spec.rb +1040 -0
- data/spec/public/model_spec.rb +456 -0
- data/spec/public/property/binary_spec.rb +43 -0
- data/spec/public/property/boolean_spec.rb +21 -0
- data/spec/public/property/class_spec.rb +27 -0
- data/spec/public/property/date_spec.rb +21 -0
- data/spec/public/property/date_time_spec.rb +21 -0
- data/spec/public/property/decimal_spec.rb +23 -0
- data/spec/public/property/discriminator_spec.rb +134 -0
- data/spec/public/property/float_spec.rb +22 -0
- data/spec/public/property/integer_spec.rb +22 -0
- data/spec/public/property/object_spec.rb +117 -0
- data/spec/public/property/serial_spec.rb +22 -0
- data/spec/public/property/string_spec.rb +21 -0
- data/spec/public/property/text_spec.rb +62 -0
- data/spec/public/property/time_spec.rb +21 -0
- data/spec/public/property_spec.rb +333 -0
- data/spec/public/resource/state_spec.rb +72 -0
- data/spec/public/resource_spec.rb +289 -0
- data/spec/public/sel_spec.rb +53 -0
- data/spec/public/setup_spec.rb +145 -0
- data/spec/public/shared/association_collection_shared_spec.rb +309 -0
- data/spec/public/shared/collection_finder_shared_spec.rb +267 -0
- data/spec/public/shared/collection_shared_spec.rb +1637 -0
- data/spec/public/shared/finder_shared_spec.rb +1647 -0
- data/spec/semipublic/adapters/abstract_adapter_spec.rb +30 -0
- data/spec/semipublic/adapters/in_memory_adapter_spec.rb +13 -0
- data/spec/semipublic/associations/many_to_many_spec.rb +94 -0
- data/spec/semipublic/associations/many_to_one_spec.rb +63 -0
- data/spec/semipublic/associations/one_to_many_spec.rb +55 -0
- data/spec/semipublic/associations/one_to_one_spec.rb +53 -0
- data/spec/semipublic/associations/relationship_spec.rb +200 -0
- data/spec/semipublic/associations_spec.rb +177 -0
- data/spec/semipublic/collection_spec.rb +110 -0
- data/spec/semipublic/model_spec.rb +96 -0
- data/spec/semipublic/property/binary_spec.rb +13 -0
- data/spec/semipublic/property/boolean_spec.rb +47 -0
- data/spec/semipublic/property/class_spec.rb +33 -0
- data/spec/semipublic/property/date_spec.rb +43 -0
- data/spec/semipublic/property/date_time_spec.rb +46 -0
- data/spec/semipublic/property/decimal_spec.rb +83 -0
- data/spec/semipublic/property/discriminator_spec.rb +19 -0
- data/spec/semipublic/property/float_spec.rb +82 -0
- data/spec/semipublic/property/integer_spec.rb +82 -0
- data/spec/semipublic/property/lookup_spec.rb +29 -0
- data/spec/semipublic/property/serial_spec.rb +13 -0
- data/spec/semipublic/property/string_spec.rb +13 -0
- data/spec/semipublic/property/text_spec.rb +31 -0
- data/spec/semipublic/property/time_spec.rb +50 -0
- data/spec/semipublic/property_spec.rb +114 -0
- data/spec/semipublic/query/conditions/comparison_spec.rb +1502 -0
- data/spec/semipublic/query/conditions/operation_spec.rb +1296 -0
- data/spec/semipublic/query/path_spec.rb +471 -0
- data/spec/semipublic/query_spec.rb +3665 -0
- data/spec/semipublic/resource/state/clean_spec.rb +89 -0
- data/spec/semipublic/resource/state/deleted_spec.rb +79 -0
- data/spec/semipublic/resource/state/dirty_spec.rb +163 -0
- data/spec/semipublic/resource/state/immutable_spec.rb +107 -0
- data/spec/semipublic/resource/state/transient_spec.rb +163 -0
- data/spec/semipublic/resource/state_spec.rb +230 -0
- data/spec/semipublic/resource_spec.rb +23 -0
- data/spec/semipublic/shared/condition_shared_spec.rb +9 -0
- data/spec/semipublic/shared/resource_shared_spec.rb +198 -0
- data/spec/semipublic/shared/resource_state_shared_spec.rb +91 -0
- data/spec/semipublic/shared/subject_shared_spec.rb +79 -0
- data/spec/spec_helper.rb +34 -0
- data/spec/support/core_ext/hash.rb +10 -0
- data/spec/support/core_ext/inheritable_attributes.rb +46 -0
- data/spec/support/properties/huge_integer.rb +17 -0
- data/spec/unit/array_spec.rb +23 -0
- data/spec/unit/blank_spec.rb +73 -0
- data/spec/unit/data_mapper/ordered_set/append_spec.rb +26 -0
- data/spec/unit/data_mapper/ordered_set/clear_spec.rb +24 -0
- data/spec/unit/data_mapper/ordered_set/delete_spec.rb +28 -0
- data/spec/unit/data_mapper/ordered_set/each_spec.rb +19 -0
- data/spec/unit/data_mapper/ordered_set/empty_spec.rb +20 -0
- data/spec/unit/data_mapper/ordered_set/entries_spec.rb +22 -0
- data/spec/unit/data_mapper/ordered_set/eql_spec.rb +51 -0
- data/spec/unit/data_mapper/ordered_set/equal_value_spec.rb +84 -0
- data/spec/unit/data_mapper/ordered_set/hash_spec.rb +12 -0
- data/spec/unit/data_mapper/ordered_set/include_spec.rb +23 -0
- data/spec/unit/data_mapper/ordered_set/index_spec.rb +28 -0
- data/spec/unit/data_mapper/ordered_set/initialize_spec.rb +32 -0
- data/spec/unit/data_mapper/ordered_set/merge_spec.rb +36 -0
- data/spec/unit/data_mapper/ordered_set/shared/append_spec.rb +24 -0
- data/spec/unit/data_mapper/ordered_set/shared/clear_spec.rb +9 -0
- data/spec/unit/data_mapper/ordered_set/shared/delete_spec.rb +25 -0
- data/spec/unit/data_mapper/ordered_set/shared/each_spec.rb +17 -0
- data/spec/unit/data_mapper/ordered_set/shared/empty_spec.rb +9 -0
- data/spec/unit/data_mapper/ordered_set/shared/entries_spec.rb +9 -0
- data/spec/unit/data_mapper/ordered_set/shared/include_spec.rb +9 -0
- data/spec/unit/data_mapper/ordered_set/shared/index_spec.rb +13 -0
- data/spec/unit/data_mapper/ordered_set/shared/initialize_spec.rb +28 -0
- data/spec/unit/data_mapper/ordered_set/shared/merge_spec.rb +28 -0
- data/spec/unit/data_mapper/ordered_set/shared/size_spec.rb +13 -0
- data/spec/unit/data_mapper/ordered_set/shared/to_ary_spec.rb +11 -0
- data/spec/unit/data_mapper/ordered_set/size_spec.rb +27 -0
- data/spec/unit/data_mapper/ordered_set/to_ary_spec.rb +23 -0
- data/spec/unit/data_mapper/subject_set/append_spec.rb +47 -0
- data/spec/unit/data_mapper/subject_set/clear_spec.rb +34 -0
- data/spec/unit/data_mapper/subject_set/delete_spec.rb +40 -0
- data/spec/unit/data_mapper/subject_set/each_spec.rb +30 -0
- data/spec/unit/data_mapper/subject_set/empty_spec.rb +31 -0
- data/spec/unit/data_mapper/subject_set/entries_spec.rb +31 -0
- data/spec/unit/data_mapper/subject_set/get_spec.rb +34 -0
- data/spec/unit/data_mapper/subject_set/include_spec.rb +32 -0
- data/spec/unit/data_mapper/subject_set/named_spec.rb +33 -0
- data/spec/unit/data_mapper/subject_set/shared/append_spec.rb +18 -0
- data/spec/unit/data_mapper/subject_set/shared/clear_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/delete_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/each_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/empty_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/entries_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/get_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/include_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/named_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/size_spec.rb +13 -0
- data/spec/unit/data_mapper/subject_set/shared/to_ary_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/values_at_spec.rb +44 -0
- data/spec/unit/data_mapper/subject_set/size_spec.rb +42 -0
- data/spec/unit/data_mapper/subject_set/to_ary_spec.rb +34 -0
- data/spec/unit/data_mapper/subject_set/values_at_spec.rb +57 -0
- data/spec/unit/hash_spec.rb +27 -0
- data/spec/unit/hook_spec.rb +1216 -0
- data/spec/unit/inflections_spec.rb +14 -0
- data/spec/unit/lazy_array_spec.rb +1949 -0
- data/spec/unit/mash_spec.rb +289 -0
- data/spec/unit/module_spec.rb +70 -0
- data/spec/unit/object_spec.rb +38 -0
- data/spec/unit/try_dup_spec.rb +46 -0
- data/tasks/ci.rake +1 -0
- data/tasks/spec.rake +18 -0
- data/tasks/yard.rake +9 -0
- data/tasks/yardstick.rake +19 -0
- metadata +323 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
module DataMapper
|
|
2
|
+
# A {SubjectSet} that keeps track of relationships defined in a {Model}
|
|
3
|
+
#
|
|
4
|
+
class RelationshipSet < SubjectSet
|
|
5
|
+
# A list of all relationships in this set
|
|
6
|
+
#
|
|
7
|
+
# @deprecated use DataMapper::RelationshipSet#each or DataMapper::RelationshipSet#to_a instead
|
|
8
|
+
#
|
|
9
|
+
# @return [Array]
|
|
10
|
+
# a list of all relationships in the set
|
|
11
|
+
#
|
|
12
|
+
# @api semipublic
|
|
13
|
+
def values
|
|
14
|
+
warn "#{self.class}#values is deprecated. Use #{self.class}#each or #{self.class}#to_a instead: #{caller.first}"
|
|
15
|
+
to_a
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# A list of all relationships in this set
|
|
19
|
+
#
|
|
20
|
+
# @deprecated use DataMapper::RelationshipSet#each instead
|
|
21
|
+
#
|
|
22
|
+
# @yield [DataMapper::Associations::Relationship]
|
|
23
|
+
# all relationships in the set
|
|
24
|
+
#
|
|
25
|
+
# @yieldparam [DataMapper::Associations::Relationship] relationship
|
|
26
|
+
# a relationship in the set
|
|
27
|
+
#
|
|
28
|
+
# @return [RelationshipSet] self
|
|
29
|
+
#
|
|
30
|
+
# @api semipublic
|
|
31
|
+
def each_value(&block)
|
|
32
|
+
warn "#{self.class}#each_value is deprecated. Use #{self.class}#each instead: #{caller.first}"
|
|
33
|
+
each(&block)
|
|
34
|
+
self
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Check whether this RelationshipSet includes an entry with the given name
|
|
38
|
+
#
|
|
39
|
+
# @deprecated use DataMapper::RelationshipSet#named? instead
|
|
40
|
+
#
|
|
41
|
+
# @param [#to_s] name
|
|
42
|
+
# the name of the entry to look for
|
|
43
|
+
#
|
|
44
|
+
# @return [Boolean]
|
|
45
|
+
# true if the set contains a relationship with the given name
|
|
46
|
+
#
|
|
47
|
+
# @api semipublic
|
|
48
|
+
def key?(name)
|
|
49
|
+
warn "#{self.class}#key? is deprecated. Use #{self.class}#named? instead: #{caller.first}"
|
|
50
|
+
named?(name)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Check whether this RelationshipSet includes an entry with the given name
|
|
54
|
+
#
|
|
55
|
+
# @deprecated use DataMapper::RelationshipSet#named? instead
|
|
56
|
+
#
|
|
57
|
+
# @param [#to_s] name
|
|
58
|
+
# the name of the entry to look for
|
|
59
|
+
#
|
|
60
|
+
# @return [Boolean]
|
|
61
|
+
# true if the set contains a relationship with the given name
|
|
62
|
+
#
|
|
63
|
+
# @api semipublic
|
|
64
|
+
def has_key?(name)
|
|
65
|
+
warn "#{self.class}#has_key? is deprecated. Use #{self.class}#named? instead: #{caller.first}"
|
|
66
|
+
named?(name)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
module DataMapper
|
|
2
|
+
class Repository
|
|
3
|
+
include DataMapper::Assertions
|
|
4
|
+
extend Equalizer
|
|
5
|
+
|
|
6
|
+
equalize :name
|
|
7
|
+
|
|
8
|
+
# Get the list of adapters registered for all Repositories,
|
|
9
|
+
# keyed by repository name.
|
|
10
|
+
#
|
|
11
|
+
# TODO: create example
|
|
12
|
+
#
|
|
13
|
+
# @return [Hash(Symbol => Adapters::AbstractAdapter)]
|
|
14
|
+
# the adapters registered for all Repositories
|
|
15
|
+
#
|
|
16
|
+
# @api private
|
|
17
|
+
def self.adapters
|
|
18
|
+
@adapters ||= {}
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Get the stack of current repository contexts
|
|
22
|
+
#
|
|
23
|
+
# TODO: create example
|
|
24
|
+
#
|
|
25
|
+
# @return [Array]
|
|
26
|
+
# List of Repository contexts for the current Thread
|
|
27
|
+
#
|
|
28
|
+
# @api private
|
|
29
|
+
def self.context
|
|
30
|
+
Thread.current[:dm_repository_contexts] ||= []
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Get the default name of this Repository
|
|
34
|
+
#
|
|
35
|
+
# TODO: create example
|
|
36
|
+
#
|
|
37
|
+
# @return [Symbol]
|
|
38
|
+
# the default name of this repository
|
|
39
|
+
#
|
|
40
|
+
# @api private
|
|
41
|
+
def self.default_name
|
|
42
|
+
:default
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# @api semipublic
|
|
46
|
+
attr_reader :name
|
|
47
|
+
|
|
48
|
+
# @api semipublic
|
|
49
|
+
alias_method :to_sym, :name
|
|
50
|
+
|
|
51
|
+
# Get the adapter for this repository
|
|
52
|
+
#
|
|
53
|
+
# Lazy loads adapter setup from registered adapters
|
|
54
|
+
#
|
|
55
|
+
# TODO: create example
|
|
56
|
+
#
|
|
57
|
+
# @return [Adapters::AbstractAdapter]
|
|
58
|
+
# the adapter for this repository
|
|
59
|
+
#
|
|
60
|
+
# @raise [RepositoryNotSetupError]
|
|
61
|
+
# if there is no adapter registered for a repository named @name
|
|
62
|
+
#
|
|
63
|
+
# @api semipublic
|
|
64
|
+
def adapter
|
|
65
|
+
# Make adapter instantiation lazy so we can defer repository setup until it's actually
|
|
66
|
+
# needed. Do not remove this code.
|
|
67
|
+
@adapter ||=
|
|
68
|
+
begin
|
|
69
|
+
adapters = self.class.adapters
|
|
70
|
+
|
|
71
|
+
raise RepositoryNotSetupError, "Adapter not set: #{@name}. Did you forget to setup?" unless adapters.key?(@name)
|
|
72
|
+
|
|
73
|
+
adapters[@name]
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Get the identity for a particular model within this repository.
|
|
78
|
+
#
|
|
79
|
+
# If one doesn't yet exist, create a new default in-memory IdentityMap
|
|
80
|
+
# for the requested model.
|
|
81
|
+
#
|
|
82
|
+
# TODO: create example
|
|
83
|
+
#
|
|
84
|
+
# @param [Model] model
|
|
85
|
+
# Model whose identity map should be returned
|
|
86
|
+
#
|
|
87
|
+
# @return [IdentityMap]
|
|
88
|
+
# The IdentityMap for model in this Repository
|
|
89
|
+
#
|
|
90
|
+
# @api private
|
|
91
|
+
def identity_map(model)
|
|
92
|
+
@identity_maps[model.base_model] ||= IdentityMap.new
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Executes a block in the scope of this Repository
|
|
96
|
+
#
|
|
97
|
+
# TODO: create example
|
|
98
|
+
#
|
|
99
|
+
# @yieldparam [Repository] repository
|
|
100
|
+
# yields self within the block
|
|
101
|
+
#
|
|
102
|
+
# @yield
|
|
103
|
+
# execute block in the scope of this Repository
|
|
104
|
+
#
|
|
105
|
+
# @api private
|
|
106
|
+
def scope
|
|
107
|
+
context = Repository.context
|
|
108
|
+
|
|
109
|
+
context << self
|
|
110
|
+
|
|
111
|
+
begin
|
|
112
|
+
yield self
|
|
113
|
+
ensure
|
|
114
|
+
context.pop
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Create a Query or subclass instance for this repository.
|
|
119
|
+
#
|
|
120
|
+
# @param [Model] model
|
|
121
|
+
# the Model to retrieve results from
|
|
122
|
+
# @param [Hash] options
|
|
123
|
+
# the conditions and scope
|
|
124
|
+
#
|
|
125
|
+
# @return [Query]
|
|
126
|
+
#
|
|
127
|
+
# @api semipublic
|
|
128
|
+
def new_query(model, options = {})
|
|
129
|
+
adapter.new_query(self, model, options)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Create one or more resource instances in this repository.
|
|
133
|
+
#
|
|
134
|
+
# TODO: create example
|
|
135
|
+
#
|
|
136
|
+
# @param [Enumerable(Resource)] resources
|
|
137
|
+
# The list of resources (model instances) to create
|
|
138
|
+
#
|
|
139
|
+
# @return [Integer]
|
|
140
|
+
# The number of records that were actually saved into the data-store
|
|
141
|
+
#
|
|
142
|
+
# @api semipublic
|
|
143
|
+
def create(resources)
|
|
144
|
+
adapter.create(resources)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Retrieve a collection of results of a query
|
|
148
|
+
#
|
|
149
|
+
# TODO: create example
|
|
150
|
+
#
|
|
151
|
+
# @param [Query] query
|
|
152
|
+
# composition of the query to perform
|
|
153
|
+
#
|
|
154
|
+
# @return [Mixed]
|
|
155
|
+
# [DataMapper::Resource] result set of the query
|
|
156
|
+
# [Array]
|
|
157
|
+
#
|
|
158
|
+
# @api semipublic
|
|
159
|
+
def read(query)
|
|
160
|
+
return [] unless query.valid?
|
|
161
|
+
|
|
162
|
+
query.model.load(adapter.read(query), query)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Update the attributes of one or more resource instances
|
|
166
|
+
#
|
|
167
|
+
# TODO: create example
|
|
168
|
+
#
|
|
169
|
+
# @param [Hash(Property => Object)] attributes
|
|
170
|
+
# hash of attribute values to set, keyed by Property
|
|
171
|
+
# @param [Collection] collection
|
|
172
|
+
# collection of records to be updated
|
|
173
|
+
#
|
|
174
|
+
# @return [Integer]
|
|
175
|
+
# the number of records updated
|
|
176
|
+
#
|
|
177
|
+
# @api semipublic
|
|
178
|
+
def update(attributes, collection)
|
|
179
|
+
return 0 unless collection.query.valid? && attributes.any?
|
|
180
|
+
|
|
181
|
+
adapter.update(attributes, collection)
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# Delete one or more resource instances
|
|
185
|
+
#
|
|
186
|
+
# TODO: create example
|
|
187
|
+
#
|
|
188
|
+
# @param [Collection] collection
|
|
189
|
+
# collection of records to be deleted
|
|
190
|
+
#
|
|
191
|
+
# @return [Integer]
|
|
192
|
+
# the number of records deleted
|
|
193
|
+
#
|
|
194
|
+
# @api semipublic
|
|
195
|
+
def delete(collection)
|
|
196
|
+
return 0 unless collection.query.valid?
|
|
197
|
+
|
|
198
|
+
adapter.delete(collection)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# Return a human readable representation of the repository
|
|
202
|
+
#
|
|
203
|
+
# TODO: create example
|
|
204
|
+
#
|
|
205
|
+
# @return [String]
|
|
206
|
+
# human readable representation of the repository
|
|
207
|
+
#
|
|
208
|
+
# @api private
|
|
209
|
+
def inspect
|
|
210
|
+
"#<#{self.class.name} @name=#{@name}>"
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# Initializes a new Repository
|
|
214
|
+
#
|
|
215
|
+
# TODO: create example
|
|
216
|
+
#
|
|
217
|
+
# @param [Symbol] name
|
|
218
|
+
# The name of the Repository
|
|
219
|
+
#
|
|
220
|
+
# @api semipublic
|
|
221
|
+
private def initialize(name)
|
|
222
|
+
@name = name.to_sym
|
|
223
|
+
@identity_maps = {}
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module DataMapper
|
|
2
|
+
module Resource
|
|
3
|
+
class PersistenceState
|
|
4
|
+
# a persisted/unmodified resource
|
|
5
|
+
class Clean < Persisted
|
|
6
|
+
def set(subject, value)
|
|
7
|
+
if not_modified?(subject, value)
|
|
8
|
+
self
|
|
9
|
+
else
|
|
10
|
+
# assign to persistence_state so that if Dirty#set calls
|
|
11
|
+
# a Relationship#set, which modifies a Property, the same
|
|
12
|
+
# Dirty state instance will be reused.
|
|
13
|
+
state = resource.persistence_state = Dirty.new(resource)
|
|
14
|
+
state.set(subject, value)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def delete
|
|
19
|
+
Deleted.new(resource)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def commit
|
|
23
|
+
self
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def rollback
|
|
27
|
+
self
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private def not_modified?(subject, value)
|
|
31
|
+
subject.loaded?(resource) && subject.get!(resource).eql?(value)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module DataMapper
|
|
2
|
+
module Resource
|
|
3
|
+
class PersistenceState
|
|
4
|
+
# a persisted/deleted resource
|
|
5
|
+
class Deleted < Persisted
|
|
6
|
+
def set(_subject, _value)
|
|
7
|
+
raise ImmutableDeletedError, 'Deleted resource cannot be modified'
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def delete
|
|
11
|
+
self
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def commit
|
|
15
|
+
delete_resource
|
|
16
|
+
remove_from_identity_map
|
|
17
|
+
Immutable.new(resource)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private def delete_resource
|
|
21
|
+
repository.delete(collection_for_self)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
module DataMapper
|
|
2
|
+
module Resource
|
|
3
|
+
class PersistenceState
|
|
4
|
+
# a persisted/dirty resource
|
|
5
|
+
class Dirty < Persisted
|
|
6
|
+
def set(subject, value)
|
|
7
|
+
track(subject, value)
|
|
8
|
+
super
|
|
9
|
+
original_attributes.empty? ? Clean.new(resource) : self
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def delete
|
|
13
|
+
reset_resource
|
|
14
|
+
Deleted.new(resource)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def commit
|
|
18
|
+
remove_from_identity_map
|
|
19
|
+
set_child_keys
|
|
20
|
+
assert_valid_attributes
|
|
21
|
+
update_resource
|
|
22
|
+
reset_original_attributes
|
|
23
|
+
reset_resource_key
|
|
24
|
+
Clean.new(resource)
|
|
25
|
+
ensure
|
|
26
|
+
add_to_identity_map
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def rollback
|
|
30
|
+
reset_resource
|
|
31
|
+
Clean.new(resource)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def original_attributes
|
|
35
|
+
@original_attributes ||= {}
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private def track(subject, value)
|
|
39
|
+
if original_attributes.key?(subject)
|
|
40
|
+
# stop tracking if the new value is the same as the original
|
|
41
|
+
original_attributes.delete(subject) if original_attributes[subject].eql?(value)
|
|
42
|
+
elsif !value.eql?((original = get(subject)))
|
|
43
|
+
# track the original value
|
|
44
|
+
original_attributes[subject] = original
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private def update_resource
|
|
49
|
+
repository.update(resource.dirty_attributes, collection_for_self)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private def reset_resource
|
|
53
|
+
reset_resource_properties
|
|
54
|
+
reset_resource_relationships
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private def reset_resource_key
|
|
58
|
+
resource.instance_eval { remove_instance_variable(:@_key) }
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private def reset_resource_properties
|
|
62
|
+
# delete every original attribute after resetting the resource
|
|
63
|
+
original_attributes.delete_if do |property, value|
|
|
64
|
+
property.set!(resource, value)
|
|
65
|
+
true
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
private def reset_resource_relationships
|
|
70
|
+
relationships.each do |relationship|
|
|
71
|
+
next unless relationship.loaded?(resource)
|
|
72
|
+
|
|
73
|
+
# TODO: consider a method in Relationship that can reset the relationship
|
|
74
|
+
resource.instance_eval { remove_instance_variable(relationship.instance_variable_name) }
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
private def reset_original_attributes
|
|
79
|
+
original_attributes.clear
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
private def assert_valid_attributes
|
|
83
|
+
properties.each do |property|
|
|
84
|
+
value = property.get! resource
|
|
85
|
+
property.assert_valid_value(value)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module DataMapper
|
|
2
|
+
module Resource
|
|
3
|
+
class PersistenceState
|
|
4
|
+
# a not-persisted/unmodifiable resource
|
|
5
|
+
class Immutable < PersistenceState
|
|
6
|
+
def get(subject, *args)
|
|
7
|
+
unless subject.loaded?(resource) || subject.is_a?(Associations::Relationship)
|
|
8
|
+
raise ImmutableError, 'Immutable resource cannot be lazy loaded'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
super
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def set(_subject, _value)
|
|
15
|
+
raise ImmutableError, 'Immutable resource cannot be modified'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def delete
|
|
19
|
+
raise ImmutableError, 'Immutable resource cannot be deleted'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def commit
|
|
23
|
+
self
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def rollback
|
|
27
|
+
self
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module DataMapper
|
|
2
|
+
module Resource
|
|
3
|
+
class PersistenceState
|
|
4
|
+
# a persisted resource (abstract)
|
|
5
|
+
class Persisted < PersistenceState
|
|
6
|
+
def get(subject, *args)
|
|
7
|
+
lazy_load(subject)
|
|
8
|
+
super
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
private def repository
|
|
12
|
+
@repository ||= resource.instance_variable_get(:@_repository)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private def collection_for_self
|
|
16
|
+
@collection_for_self ||= resource.collection_for_self
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private def lazy_load(subject)
|
|
20
|
+
subject.lazy_load(resource)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
module DataMapper
|
|
2
|
+
module Resource
|
|
3
|
+
class PersistenceState
|
|
4
|
+
# a not-persisted/modifiable resource
|
|
5
|
+
class Transient < PersistenceState
|
|
6
|
+
def get(subject, *args)
|
|
7
|
+
set_default_value(subject)
|
|
8
|
+
super
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def set(subject, value)
|
|
12
|
+
track(subject)
|
|
13
|
+
super
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def delete
|
|
17
|
+
self
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def commit
|
|
21
|
+
set_child_keys
|
|
22
|
+
set_default_values
|
|
23
|
+
assert_valid_attributes
|
|
24
|
+
create_resource
|
|
25
|
+
set_repository
|
|
26
|
+
add_to_identity_map
|
|
27
|
+
Clean.new(resource)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def rollback
|
|
31
|
+
self
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def original_attributes
|
|
35
|
+
@original_attributes ||= {}
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private def repository
|
|
39
|
+
@repository ||= model.repository
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private def set_default_values
|
|
43
|
+
(properties | relationships).each do |subject|
|
|
44
|
+
set_default_value(subject)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private def set_default_value(subject)
|
|
49
|
+
return if subject.loaded?(resource) || !subject.default?
|
|
50
|
+
|
|
51
|
+
default = typecast_default(subject, subject.default_for(resource))
|
|
52
|
+
set(subject, default)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private def typecast_default(subject, default)
|
|
56
|
+
return default unless subject.respond_to?(:typecast)
|
|
57
|
+
|
|
58
|
+
typecasted_default = subject.send(:typecast, default)
|
|
59
|
+
unless typecasted_default.eql?(default)
|
|
60
|
+
warn "Automatic typecasting of default property values is deprecated (#{default.inspect} was casted to #{typecasted_default.inspect}). " \
|
|
61
|
+
"Specify the correct type for #{resource.class}."
|
|
62
|
+
end
|
|
63
|
+
typecasted_default
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private def track(subject)
|
|
67
|
+
original_attributes[subject] = nil
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private def create_resource
|
|
71
|
+
repository.create([resource])
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
private def set_repository
|
|
75
|
+
resource.instance_variable_set(:@_repository, repository)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
private def assert_valid_attributes
|
|
79
|
+
properties.each do |property|
|
|
80
|
+
value = get(property)
|
|
81
|
+
property.assert_valid_value(value) unless property.serial? && value.nil?
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
module DataMapper
|
|
2
|
+
module Resource
|
|
3
|
+
# the state of the resource (abstract)
|
|
4
|
+
class PersistenceState
|
|
5
|
+
extend Equalizer
|
|
6
|
+
|
|
7
|
+
equalize :resource
|
|
8
|
+
|
|
9
|
+
attr_reader :resource, :model
|
|
10
|
+
|
|
11
|
+
def initialize(resource)
|
|
12
|
+
@resource = resource
|
|
13
|
+
@model = resource.model
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def get(subject, *args)
|
|
17
|
+
subject.get(resource, *args)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def set(subject, value)
|
|
21
|
+
subject.set(resource, value)
|
|
22
|
+
self
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def delete
|
|
26
|
+
raise NotImplementedError, "#{self.class}#delete should be implemented"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def commit
|
|
30
|
+
raise NotImplementedError, "#{self.class}#commit should be implemented"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def rollback
|
|
34
|
+
raise NotImplementedError, "#{self.class}#rollback should be implemented"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private def properties
|
|
38
|
+
@properties ||= model.properties(repository&.name)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private def relationships
|
|
42
|
+
@relationships ||= model.relationships(repository&.name)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private def identity_map
|
|
46
|
+
@identity_map ||= repository&.identity_map(model)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private def remove_from_identity_map
|
|
50
|
+
identity_map.delete(resource.key)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private def add_to_identity_map
|
|
54
|
+
identity_map[resource.key] = resource
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private def set_child_keys
|
|
58
|
+
relationships.each do |relationship|
|
|
59
|
+
set_child_key(relationship)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private def set_child_key(relationship)
|
|
64
|
+
return unless relationship.loaded?(resource) && relationship.respond_to?(:resource_for)
|
|
65
|
+
|
|
66
|
+
set(relationship, get(relationship))
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|