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,251 @@
|
|
|
1
|
+
module DataMapper
|
|
2
|
+
|
|
3
|
+
# An insertion ordered set of named objects
|
|
4
|
+
#
|
|
5
|
+
# {SubjectSet} uses {DataMapper::OrderedSet}
|
|
6
|
+
# under the hood to keep track of a set of
|
|
7
|
+
# entries. In DataMapper code, a subject
|
|
8
|
+
# can be either a {DataMapper::Property}, or
|
|
9
|
+
# a {DataMapper::Associations::Relationship}.
|
|
10
|
+
#
|
|
11
|
+
# All entries added to instances of this
|
|
12
|
+
# class must respond to the {#name} method
|
|
13
|
+
#
|
|
14
|
+
# The motivation behind this is that we
|
|
15
|
+
# use this class as a base to keep track
|
|
16
|
+
# properties and relationships.
|
|
17
|
+
# The following constraints apply for these
|
|
18
|
+
# types of objects: {Property} names must be
|
|
19
|
+
# unique within any model.
|
|
20
|
+
# {Associations::Relationship} names must be
|
|
21
|
+
# unique within any model
|
|
22
|
+
#
|
|
23
|
+
# When adding an entry with a name that
|
|
24
|
+
# already exists, the already existing
|
|
25
|
+
# entry will be replaced with the new
|
|
26
|
+
# entry with the same name. This is because
|
|
27
|
+
# we want to be able to update properties,
|
|
28
|
+
# and relationship during the course of
|
|
29
|
+
# initializing our application.
|
|
30
|
+
#
|
|
31
|
+
# This also happens to be consistent with
|
|
32
|
+
# the way ruby handles redefining methods,
|
|
33
|
+
# where the last definitions "wins".
|
|
34
|
+
#
|
|
35
|
+
# Furthermore, the builtin ruby {Set#<<} method
|
|
36
|
+
# also updates the old object if a new object
|
|
37
|
+
# gets added.
|
|
38
|
+
#
|
|
39
|
+
# @api private
|
|
40
|
+
class SubjectSet
|
|
41
|
+
|
|
42
|
+
# An {OrderedSet::Cache::API} implementation that establishes
|
|
43
|
+
# set semantics based on the name of its entries. The cache
|
|
44
|
+
# uses the entries' names as cache key and refuses to add
|
|
45
|
+
# entries that don't respond_to?(:name).
|
|
46
|
+
#
|
|
47
|
+
# @see OrderedSet::Cache::API
|
|
48
|
+
#
|
|
49
|
+
# @api private
|
|
50
|
+
class NameCache
|
|
51
|
+
|
|
52
|
+
include OrderedSet::Cache::API
|
|
53
|
+
|
|
54
|
+
# Tests if the given entry qualifies to be added to the cache
|
|
55
|
+
#
|
|
56
|
+
# @param [#name] entry
|
|
57
|
+
# the entry to be checked
|
|
58
|
+
#
|
|
59
|
+
# @return [Boolean]
|
|
60
|
+
# true if the entry respond_to?(:name)
|
|
61
|
+
#
|
|
62
|
+
# @api private
|
|
63
|
+
def valid?(entry)
|
|
64
|
+
entry.respond_to?(:name)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Given an entry, return the key to be used in the cache
|
|
68
|
+
#
|
|
69
|
+
# @param [#name] entry
|
|
70
|
+
# the entry to get the key for
|
|
71
|
+
#
|
|
72
|
+
# @return [#to_s, nil]
|
|
73
|
+
# the entry's name or nil if the entry isn't #valid?
|
|
74
|
+
#
|
|
75
|
+
# @api private
|
|
76
|
+
def key_for(entry)
|
|
77
|
+
valid?(entry) ? entry.name : nil
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
end # class NameCache
|
|
81
|
+
|
|
82
|
+
include Enumerable
|
|
83
|
+
|
|
84
|
+
# The elements in the SubjectSet
|
|
85
|
+
#
|
|
86
|
+
# @return [OrderedSet]
|
|
87
|
+
#
|
|
88
|
+
# @api private
|
|
89
|
+
attr_reader :entries
|
|
90
|
+
|
|
91
|
+
# Initialize a SubjectSet
|
|
92
|
+
#
|
|
93
|
+
# @param [Enumerable<#name>] entries
|
|
94
|
+
# the entries to initialize this set with
|
|
95
|
+
#
|
|
96
|
+
# @api private
|
|
97
|
+
def initialize(entries = [])
|
|
98
|
+
@entries = OrderedSet.new(entries, NameCache)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Initialize a copy of a SubjectSet
|
|
102
|
+
#
|
|
103
|
+
# @api private
|
|
104
|
+
def initialize_copy(*)
|
|
105
|
+
@entries = @entries.dup
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Make sure that entry is part of this SubjectSet
|
|
109
|
+
#
|
|
110
|
+
# If an entry with the same name already exists, it
|
|
111
|
+
# will be updated. If no such named entry exists, it
|
|
112
|
+
# will be added.
|
|
113
|
+
#
|
|
114
|
+
# @param [#name] entry
|
|
115
|
+
# the entry to be added
|
|
116
|
+
#
|
|
117
|
+
# @return [SubjectSet] self
|
|
118
|
+
#
|
|
119
|
+
# @api private
|
|
120
|
+
def <<(entry)
|
|
121
|
+
entries << entry
|
|
122
|
+
self
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Delete an entry from this SubjectSet
|
|
126
|
+
#
|
|
127
|
+
# @param [#name] entry
|
|
128
|
+
# the entry to delete
|
|
129
|
+
#
|
|
130
|
+
# @return [#name, nil]
|
|
131
|
+
# the deleted entry or nil
|
|
132
|
+
#
|
|
133
|
+
# @api private
|
|
134
|
+
def delete(entry)
|
|
135
|
+
entries.delete(entry)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Removes all entries and returns self
|
|
139
|
+
#
|
|
140
|
+
# @return [SubjectSet] self
|
|
141
|
+
#
|
|
142
|
+
# @api private
|
|
143
|
+
def clear
|
|
144
|
+
entries.clear
|
|
145
|
+
self
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Test if the given entry is included in this SubjectSet
|
|
149
|
+
#
|
|
150
|
+
# @param [#name] entry
|
|
151
|
+
# the entry to test for
|
|
152
|
+
#
|
|
153
|
+
# @return [Boolean]
|
|
154
|
+
# true if the entry is included in this SubjectSet
|
|
155
|
+
#
|
|
156
|
+
# @api private
|
|
157
|
+
def include?(entry)
|
|
158
|
+
entries.include?(entry)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Tests wether the SubjectSet contains a entry named name
|
|
162
|
+
#
|
|
163
|
+
# @param [#to_s] name
|
|
164
|
+
# the entry name to test for
|
|
165
|
+
#
|
|
166
|
+
# @return [Boolean]
|
|
167
|
+
# true if the SubjectSet contains a entry named name
|
|
168
|
+
#
|
|
169
|
+
# @api private
|
|
170
|
+
def named?(name)
|
|
171
|
+
!self[name].nil?
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Check if there are any entries
|
|
175
|
+
#
|
|
176
|
+
# @return [Boolean]
|
|
177
|
+
# true if the set contains at least one entry
|
|
178
|
+
#
|
|
179
|
+
# @api private
|
|
180
|
+
def empty?
|
|
181
|
+
entries.empty?
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# Lookup an entry in the SubjectSet based on a given name
|
|
185
|
+
#
|
|
186
|
+
# @param [#to_s] name
|
|
187
|
+
# the name of the entry
|
|
188
|
+
#
|
|
189
|
+
# @return [Object, nil]
|
|
190
|
+
# the entry having the given name, or nil if not found
|
|
191
|
+
#
|
|
192
|
+
# @api private
|
|
193
|
+
def [](name)
|
|
194
|
+
name = name.to_s
|
|
195
|
+
entries.detect { |entry| entry.name.to_s == name }
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# Iterate over each entry in the set
|
|
199
|
+
#
|
|
200
|
+
# @yield [entry]
|
|
201
|
+
# each entry in the set
|
|
202
|
+
#
|
|
203
|
+
# @yieldparam [#name] entry
|
|
204
|
+
# an entry in the set
|
|
205
|
+
#
|
|
206
|
+
# @return [SubjectSet] self
|
|
207
|
+
#
|
|
208
|
+
# @api private
|
|
209
|
+
def each
|
|
210
|
+
return to_enum unless block_given?
|
|
211
|
+
entries.each { |entry| yield(entry) }
|
|
212
|
+
self
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# All entries (or nil values) that have any of the given names
|
|
216
|
+
#
|
|
217
|
+
# @param [Enumerable<#to_s>] names
|
|
218
|
+
# the names of the desired entries
|
|
219
|
+
#
|
|
220
|
+
# @return [Array<#name, nil>]
|
|
221
|
+
# an array containing entries whose names match any of the given
|
|
222
|
+
# names, or nil values for those names with no matching entries
|
|
223
|
+
# in the set
|
|
224
|
+
#
|
|
225
|
+
# @api private
|
|
226
|
+
def values_at(*names)
|
|
227
|
+
names.map { |name| self[name] }
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# Get the number of elements inside this SubjectSet
|
|
231
|
+
#
|
|
232
|
+
# @return [Integer]
|
|
233
|
+
# the number of elements
|
|
234
|
+
#
|
|
235
|
+
# @api private
|
|
236
|
+
def size
|
|
237
|
+
entries.size
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
# Convert the SubjectSet into an Array
|
|
241
|
+
#
|
|
242
|
+
# @return [Array]
|
|
243
|
+
# an array containing all the SubjectSet's entries
|
|
244
|
+
#
|
|
245
|
+
# @api private
|
|
246
|
+
def to_ary
|
|
247
|
+
to_a
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
end # class SubjectSet
|
|
251
|
+
end # module DataMapper
|
data/lib/dm-core.rb
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
require 'addressable/uri'
|
|
2
|
+
require 'bigdecimal'
|
|
3
|
+
require 'bigdecimal/util'
|
|
4
|
+
require 'date'
|
|
5
|
+
require 'pathname'
|
|
6
|
+
require 'time'
|
|
7
|
+
require 'yaml'
|
|
8
|
+
|
|
9
|
+
module DataMapper
|
|
10
|
+
module Undefined; end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
require 'dm-core/support/ext/blank'
|
|
14
|
+
require 'dm-core/support/ext/hash'
|
|
15
|
+
require 'dm-core/support/ext/object'
|
|
16
|
+
require 'dm-core/support/ext/string'
|
|
17
|
+
|
|
18
|
+
require 'dm-core/core_ext/pathname'
|
|
19
|
+
require 'dm-core/support/ext/module'
|
|
20
|
+
require 'dm-core/support/ext/array'
|
|
21
|
+
require 'dm-core/support/ext/try_dup'
|
|
22
|
+
|
|
23
|
+
require 'dm-core/support/mash'
|
|
24
|
+
require 'dm-core/support/inflector/inflections'
|
|
25
|
+
require 'dm-core/support/inflector/methods'
|
|
26
|
+
require 'dm-core/support/inflections'
|
|
27
|
+
require 'dm-core/support/chainable'
|
|
28
|
+
require 'dm-core/support/deprecate'
|
|
29
|
+
require 'dm-core/support/descendant_set'
|
|
30
|
+
require 'dm-core/support/equalizer'
|
|
31
|
+
require 'dm-core/support/assertions'
|
|
32
|
+
require 'dm-core/support/lazy_array'
|
|
33
|
+
require 'dm-core/support/local_object_space'
|
|
34
|
+
require 'dm-core/support/hook'
|
|
35
|
+
require 'dm-core/support/subject'
|
|
36
|
+
require 'dm-core/support/ordered_set'
|
|
37
|
+
require 'dm-core/support/subject_set'
|
|
38
|
+
|
|
39
|
+
require 'dm-core/query'
|
|
40
|
+
require 'dm-core/query/conditions/operation'
|
|
41
|
+
require 'dm-core/query/conditions/comparison'
|
|
42
|
+
require 'dm-core/query/operator'
|
|
43
|
+
require 'dm-core/query/direction'
|
|
44
|
+
require 'dm-core/query/path'
|
|
45
|
+
require 'dm-core/query/sort'
|
|
46
|
+
|
|
47
|
+
require 'dm-core/resource'
|
|
48
|
+
require 'dm-core/resource/persistence_state'
|
|
49
|
+
require 'dm-core/resource/persistence_state/transient'
|
|
50
|
+
require 'dm-core/resource/persistence_state/immutable'
|
|
51
|
+
require 'dm-core/resource/persistence_state/persisted'
|
|
52
|
+
require 'dm-core/resource/persistence_state/clean'
|
|
53
|
+
require 'dm-core/resource/persistence_state/deleted'
|
|
54
|
+
require 'dm-core/resource/persistence_state/dirty'
|
|
55
|
+
|
|
56
|
+
require 'dm-core/property/invalid_value_error'
|
|
57
|
+
require 'dm-core/property'
|
|
58
|
+
require 'dm-core/property/typecast/numeric'
|
|
59
|
+
require 'dm-core/property/typecast/time'
|
|
60
|
+
require 'dm-core/property/object'
|
|
61
|
+
require 'dm-core/property/string'
|
|
62
|
+
require 'dm-core/property/binary'
|
|
63
|
+
require 'dm-core/property/text'
|
|
64
|
+
require 'dm-core/property/numeric'
|
|
65
|
+
require 'dm-core/property/float'
|
|
66
|
+
require 'dm-core/property/decimal'
|
|
67
|
+
require 'dm-core/property/boolean'
|
|
68
|
+
require 'dm-core/property/integer'
|
|
69
|
+
require 'dm-core/property/serial'
|
|
70
|
+
require 'dm-core/property/date'
|
|
71
|
+
require 'dm-core/property/date_time'
|
|
72
|
+
require 'dm-core/property/time'
|
|
73
|
+
require 'dm-core/property/class'
|
|
74
|
+
require 'dm-core/property/discriminator'
|
|
75
|
+
require 'dm-core/property/lookup'
|
|
76
|
+
require 'dm-core/property_set'
|
|
77
|
+
|
|
78
|
+
require 'dm-core/model'
|
|
79
|
+
require 'dm-core/model/hook'
|
|
80
|
+
require 'dm-core/model/is'
|
|
81
|
+
require 'dm-core/model/scope'
|
|
82
|
+
require 'dm-core/model/relationship'
|
|
83
|
+
require 'dm-core/model/property'
|
|
84
|
+
|
|
85
|
+
require 'dm-core/collection'
|
|
86
|
+
require 'dm-core/relationship_set'
|
|
87
|
+
require 'dm-core/associations/relationship'
|
|
88
|
+
require 'dm-core/associations/one_to_many'
|
|
89
|
+
require 'dm-core/associations/one_to_one'
|
|
90
|
+
require 'dm-core/associations/many_to_one'
|
|
91
|
+
require 'dm-core/associations/many_to_many'
|
|
92
|
+
|
|
93
|
+
require 'dm-core/identity_map'
|
|
94
|
+
require 'dm-core/repository'
|
|
95
|
+
require 'dm-core/adapters'
|
|
96
|
+
require 'dm-core/adapters/abstract_adapter'
|
|
97
|
+
|
|
98
|
+
require 'dm-core/support/logger'
|
|
99
|
+
require 'dm-core/support/naming_conventions'
|
|
100
|
+
require 'dm-core/version'
|
|
101
|
+
|
|
102
|
+
require 'dm-core/core_ext/kernel' # TODO: do not load automatically
|
|
103
|
+
require 'dm-core/core_ext/symbol' # TODO: do not load automatically
|
|
104
|
+
|
|
105
|
+
require 'dm-core/backwards' # TODO: do not load automatically
|
|
106
|
+
|
|
107
|
+
# A logger should always be present. Lets be consistent with DO
|
|
108
|
+
DataMapper::Logger.new(StringIO.new, :fatal)
|
|
109
|
+
|
|
110
|
+
Infinity = 1.0 / 0 unless defined?(Infinity)
|
|
111
|
+
|
|
112
|
+
# == Setup and Configuration
|
|
113
|
+
# DataMapper uses URIs or a connection hash to connect to your data-store.
|
|
114
|
+
# URI connections takes the form of:
|
|
115
|
+
# DataMapper.setup(:default, 'protocol://username:password@127.0.0.1:port/path/to/repo')
|
|
116
|
+
#
|
|
117
|
+
# Breaking this down, the first argument is the name you wish to give this
|
|
118
|
+
# connection. If you do not specify one, it will be assigned :default. If you
|
|
119
|
+
# would like to connect to more than one data-store, simply issue this command
|
|
120
|
+
# again, but with a different name specified.
|
|
121
|
+
#
|
|
122
|
+
# In order to issue ORM commands without specifying the repository context, you
|
|
123
|
+
# must define the :default database. Otherwise, you'll need to wrap your ORM
|
|
124
|
+
# calls in <tt>repository(:name) { }</tt>.
|
|
125
|
+
#
|
|
126
|
+
# Second, the URI breaks down into the access protocol, the username, the
|
|
127
|
+
# server, the password, and whatever path information is needed to properly
|
|
128
|
+
# address the data-store on the server.
|
|
129
|
+
#
|
|
130
|
+
# Here's some examples
|
|
131
|
+
# DataMapper.setup(:default, 'sqlite3://path/to/your/project/db/development.db')
|
|
132
|
+
# DataMapper.setup(:default, 'mysql://127.0.0.1/dm_core_test')
|
|
133
|
+
# # no auth-info
|
|
134
|
+
# DataMapper.setup(:default, 'postgres://root:supahsekret@127.0.0.1/dm_core_test')
|
|
135
|
+
# # with auth-info
|
|
136
|
+
#
|
|
137
|
+
#
|
|
138
|
+
# Alternatively, you can supply a hash as the second parameter, which would
|
|
139
|
+
# take the form:
|
|
140
|
+
#
|
|
141
|
+
# DataMapper.setup(:default, {
|
|
142
|
+
# :adapter => 'adapter_name_here',
|
|
143
|
+
# :database => 'path/to/repo',
|
|
144
|
+
# :username => 'username',
|
|
145
|
+
# :password => 'password',
|
|
146
|
+
# :host => 'hostname'
|
|
147
|
+
# })
|
|
148
|
+
#
|
|
149
|
+
# === Logging
|
|
150
|
+
# To turn on error logging to STDOUT, issue:
|
|
151
|
+
#
|
|
152
|
+
# DataMapper::Logger.new($stdout, :debug)
|
|
153
|
+
#
|
|
154
|
+
# You can pass a file location ("/path/to/log/file.log") in place of $stdout.
|
|
155
|
+
# see DataMapper::Logger for more information.
|
|
156
|
+
#
|
|
157
|
+
module DataMapper
|
|
158
|
+
extend DataMapper::Assertions
|
|
159
|
+
|
|
160
|
+
class RepositoryNotSetupError < StandardError; end
|
|
161
|
+
|
|
162
|
+
class IncompleteModelError < StandardError; end
|
|
163
|
+
|
|
164
|
+
class PluginNotFoundError < StandardError; end
|
|
165
|
+
|
|
166
|
+
class UnknownRelationshipError < StandardError; end
|
|
167
|
+
|
|
168
|
+
class ObjectNotFoundError < RuntimeError; end
|
|
169
|
+
|
|
170
|
+
class PersistenceError < RuntimeError; end
|
|
171
|
+
|
|
172
|
+
class UpdateConflictError < PersistenceError; end
|
|
173
|
+
|
|
174
|
+
class SaveFailureError < PersistenceError
|
|
175
|
+
attr_reader :resource
|
|
176
|
+
|
|
177
|
+
def initialize(message, resource)
|
|
178
|
+
super(message)
|
|
179
|
+
@resource = resource
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
class ImmutableError < RuntimeError; end
|
|
184
|
+
|
|
185
|
+
class ImmutableDeletedError < ImmutableError; end
|
|
186
|
+
|
|
187
|
+
# Raised on attempt to operate on collection of child objects
|
|
188
|
+
# when parent object is not yet saved.
|
|
189
|
+
# For instance, if your article object is not saved,
|
|
190
|
+
# but you try to fetch or scope down comments (1:n case), or
|
|
191
|
+
# publications (n:m case), operation cannot be completed
|
|
192
|
+
# because parent object's keys are not yet persisted,
|
|
193
|
+
# and thus there is no FK value to use in the query.
|
|
194
|
+
class UnsavedParentError < PersistenceError; end
|
|
195
|
+
|
|
196
|
+
# @api private
|
|
197
|
+
def self.root
|
|
198
|
+
@root ||= Pathname(__FILE__).dirname.parent.expand_path.freeze
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# Setups up a connection to a data-store
|
|
202
|
+
#
|
|
203
|
+
# @param [Symbol] name
|
|
204
|
+
# a name for the context, defaults to :default
|
|
205
|
+
# @param [Hash(Symbol => String), Addressable::URI, String] uri_or_options
|
|
206
|
+
# connection information
|
|
207
|
+
#
|
|
208
|
+
# @return [DataMapper::Adapters::AbstractAdapter]
|
|
209
|
+
# the resulting setup adapter
|
|
210
|
+
#
|
|
211
|
+
# @raise [ArgumentError] "+name+ must be a Symbol, but was..."
|
|
212
|
+
# indicates that an invalid argument was passed for name[Symbol]
|
|
213
|
+
# @raise [ArgumentError] "+uri_or_options+ must be a Hash, URI or String, but was..."
|
|
214
|
+
# indicates that connection information could not be gleaned from
|
|
215
|
+
# the given uri_or_options[Hash, Addressable::URI, String]
|
|
216
|
+
#
|
|
217
|
+
# @api public
|
|
218
|
+
def self.setup(*args)
|
|
219
|
+
adapter = args.first
|
|
220
|
+
|
|
221
|
+
adapter = Adapters.new(*args) unless adapter.is_a?(Adapters::AbstractAdapter)
|
|
222
|
+
|
|
223
|
+
Repository.adapters[adapter.name] = adapter
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# Block Syntax
|
|
227
|
+
# Pushes the named repository onto the context-stack,
|
|
228
|
+
# yields a new session, and pops the context-stack.
|
|
229
|
+
#
|
|
230
|
+
# Non-Block Syntax
|
|
231
|
+
# Returns the current session, or if there is none,
|
|
232
|
+
# a new Session.
|
|
233
|
+
#
|
|
234
|
+
# @param [Symbol] args the name of a repository to act within or return, :default is default
|
|
235
|
+
#
|
|
236
|
+
# @yield [Proc] (optional) block to execute within the context of the named repository
|
|
237
|
+
#
|
|
238
|
+
# @api public
|
|
239
|
+
def self.repository(name = nil)
|
|
240
|
+
context = Repository.context
|
|
241
|
+
|
|
242
|
+
current_repository = if name
|
|
243
|
+
name = name.to_sym
|
|
244
|
+
context.detect { |repository| repository.name == name }
|
|
245
|
+
else
|
|
246
|
+
name = Repository.default_name
|
|
247
|
+
context.last
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
current_repository ||= Repository.new(name)
|
|
251
|
+
|
|
252
|
+
if block_given?
|
|
253
|
+
current_repository.scope { |*block_args| yield(*block_args) }
|
|
254
|
+
else
|
|
255
|
+
current_repository
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
# Perform necessary steps to finalize DataMapper for the current repository
|
|
260
|
+
#
|
|
261
|
+
# This method should be called after loading all models and plugins.
|
|
262
|
+
#
|
|
263
|
+
# It ensures foreign key properties and anonymous join models are created.
|
|
264
|
+
# These are otherwise lazily declared, which can lead to unexpected errors.
|
|
265
|
+
# It also performs basic validity checking of the DataMapper models.
|
|
266
|
+
#
|
|
267
|
+
# @return [self]
|
|
268
|
+
#
|
|
269
|
+
# @api public
|
|
270
|
+
def self.finalize
|
|
271
|
+
Model.descendants.each(&:finalize)
|
|
272
|
+
self
|
|
273
|
+
end
|
|
274
|
+
end
|