ghost_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.
- data/.autotest +29 -0
- data/.document +5 -0
- data/.gitignore +35 -0
- data/.yardopts +1 -0
- data/Gemfile +65 -0
- data/LICENSE +20 -0
- data/README.md +269 -0
- data/Rakefile +4 -0
- data/dm-core.gemspec +24 -0
- data/lib/dm-core.rb +292 -0
- data/lib/dm-core/adapters.rb +222 -0
- data/lib/dm-core/adapters/abstract_adapter.rb +237 -0
- data/lib/dm-core/adapters/in_memory_adapter.rb +113 -0
- data/lib/dm-core/associations/many_to_many.rb +499 -0
- data/lib/dm-core/associations/many_to_one.rb +290 -0
- data/lib/dm-core/associations/one_to_many.rb +348 -0
- data/lib/dm-core/associations/one_to_one.rb +86 -0
- data/lib/dm-core/associations/relationship.rb +663 -0
- data/lib/dm-core/backwards.rb +13 -0
- data/lib/dm-core/collection.rb +1515 -0
- data/lib/dm-core/core_ext/kernel.rb +23 -0
- data/lib/dm-core/core_ext/pathname.rb +6 -0
- data/lib/dm-core/core_ext/symbol.rb +10 -0
- data/lib/dm-core/identity_map.rb +7 -0
- data/lib/dm-core/model.rb +874 -0
- data/lib/dm-core/model/hook.rb +103 -0
- data/lib/dm-core/model/is.rb +32 -0
- data/lib/dm-core/model/property.rb +249 -0
- data/lib/dm-core/model/relationship.rb +378 -0
- data/lib/dm-core/model/scope.rb +89 -0
- data/lib/dm-core/property.rb +866 -0
- data/lib/dm-core/property/binary.rb +21 -0
- data/lib/dm-core/property/boolean.rb +20 -0
- data/lib/dm-core/property/class.rb +17 -0
- data/lib/dm-core/property/date.rb +10 -0
- data/lib/dm-core/property/date_time.rb +10 -0
- data/lib/dm-core/property/decimal.rb +36 -0
- data/lib/dm-core/property/discriminator.rb +44 -0
- data/lib/dm-core/property/float.rb +16 -0
- data/lib/dm-core/property/integer.rb +22 -0
- data/lib/dm-core/property/invalid_value_error.rb +22 -0
- data/lib/dm-core/property/lookup.rb +27 -0
- data/lib/dm-core/property/numeric.rb +38 -0
- data/lib/dm-core/property/object.rb +34 -0
- data/lib/dm-core/property/serial.rb +14 -0
- data/lib/dm-core/property/string.rb +38 -0
- data/lib/dm-core/property/text.rb +9 -0
- data/lib/dm-core/property/time.rb +10 -0
- data/lib/dm-core/property_set.rb +177 -0
- data/lib/dm-core/query.rb +1366 -0
- data/lib/dm-core/query/conditions/comparison.rb +911 -0
- data/lib/dm-core/query/conditions/operation.rb +721 -0
- data/lib/dm-core/query/direction.rb +36 -0
- data/lib/dm-core/query/operator.rb +35 -0
- data/lib/dm-core/query/path.rb +114 -0
- data/lib/dm-core/query/sort.rb +39 -0
- data/lib/dm-core/relationship_set.rb +72 -0
- data/lib/dm-core/repository.rb +226 -0
- data/lib/dm-core/resource.rb +1214 -0
- data/lib/dm-core/resource/persistence_state.rb +75 -0
- data/lib/dm-core/resource/persistence_state/clean.rb +40 -0
- data/lib/dm-core/resource/persistence_state/deleted.rb +30 -0
- data/lib/dm-core/resource/persistence_state/dirty.rb +96 -0
- data/lib/dm-core/resource/persistence_state/immutable.rb +34 -0
- data/lib/dm-core/resource/persistence_state/persisted.rb +29 -0
- data/lib/dm-core/resource/persistence_state/transient.rb +80 -0
- data/lib/dm-core/spec/lib/adapter_helpers.rb +64 -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 +174 -0
- data/lib/dm-core/spec/shared/adapter_spec.rb +341 -0
- data/lib/dm-core/spec/shared/public/property_spec.rb +229 -0
- data/lib/dm-core/spec/shared/resource_spec.rb +1232 -0
- data/lib/dm-core/spec/shared/sel_spec.rb +111 -0
- data/lib/dm-core/spec/shared/semipublic/property_spec.rb +176 -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 +405 -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 +90 -0
- data/lib/dm-core/support/ordered_set.rb +380 -0
- data/lib/dm-core/support/subject.rb +33 -0
- data/lib/dm-core/support/subject_set.rb +250 -0
- data/lib/dm-core/version.rb +3 -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 +68 -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 +76 -0
- data/spec/public/model/hook_spec.rb +246 -0
- data/spec/public/model/property_spec.rb +88 -0
- data/spec/public/model/relationship_spec.rb +1040 -0
- data/spec/public/model_spec.rb +462 -0
- data/spec/public/property/binary_spec.rb +41 -0
- data/spec/public/property/boolean_spec.rb +22 -0
- data/spec/public/property/class_spec.rb +28 -0
- data/spec/public/property/date_spec.rb +22 -0
- data/spec/public/property/date_time_spec.rb +22 -0
- data/spec/public/property/decimal_spec.rb +23 -0
- data/spec/public/property/discriminator_spec.rb +135 -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 +107 -0
- data/spec/public/property/serial_spec.rb +22 -0
- data/spec/public/property/string_spec.rb +22 -0
- data/spec/public/property/text_spec.rb +63 -0
- data/spec/public/property/time_spec.rb +22 -0
- data/spec/public/property_spec.rb +341 -0
- data/spec/public/resource_spec.rb +288 -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 +1667 -0
- data/spec/public/shared/finder_shared_spec.rb +1629 -0
- data/spec/rcov.opts +6 -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 +1501 -0
- data/spec/semipublic/query/conditions/operation_spec.rb +1294 -0
- data/spec/semipublic/query/path_spec.rb +471 -0
- data/spec/semipublic/query_spec.rb +3682 -0
- data/spec/semipublic/resource/state/clean_spec.rb +88 -0
- data/spec/semipublic/resource/state/deleted_spec.rb +78 -0
- data/spec/semipublic/resource/state/dirty_spec.rb +162 -0
- data/spec/semipublic/resource/state/immutable_spec.rb +105 -0
- data/spec/semipublic/resource/state/transient_spec.rb +162 -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 +199 -0
- data/spec/semipublic/shared/resource_state_shared_spec.rb +79 -0
- data/spec/semipublic/shared/subject_shared_spec.rb +79 -0
- data/spec/spec.opts +5 -0
- data/spec/spec_helper.rb +38 -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 +28 -0
- data/spec/unit/hook_spec.rb +1235 -0
- data/spec/unit/inflections_spec.rb +16 -0
- data/spec/unit/lazy_array_spec.rb +1949 -0
- data/spec/unit/mash_spec.rb +312 -0
- data/spec/unit/module_spec.rb +71 -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 +38 -0
- data/tasks/yard.rake +9 -0
- data/tasks/yardstick.rake +19 -0
- metadata +365 -0
data/lib/dm-core.rb
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
require 'addressable/uri'
|
|
2
|
+
require 'bigdecimal'
|
|
3
|
+
require 'bigdecimal/util'
|
|
4
|
+
require 'date'
|
|
5
|
+
require 'pathname'
|
|
6
|
+
require 'set'
|
|
7
|
+
require 'time'
|
|
8
|
+
require 'yaml'
|
|
9
|
+
|
|
10
|
+
module DataMapper
|
|
11
|
+
module Undefined; end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
require 'virtus'
|
|
15
|
+
|
|
16
|
+
class Virtus::Coercion::Object
|
|
17
|
+
def self.to_string(value)
|
|
18
|
+
value.nil? ? value : value.to_s
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
require 'dm-core/support/ext/blank'
|
|
23
|
+
require 'dm-core/support/ext/hash'
|
|
24
|
+
require 'dm-core/support/ext/object'
|
|
25
|
+
require 'dm-core/support/ext/string'
|
|
26
|
+
|
|
27
|
+
begin
|
|
28
|
+
require 'fastthread'
|
|
29
|
+
rescue LoadError
|
|
30
|
+
# fastthread not installed
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
require 'dm-core/core_ext/pathname'
|
|
34
|
+
require 'dm-core/support/ext/module'
|
|
35
|
+
require 'dm-core/support/ext/array'
|
|
36
|
+
require 'dm-core/support/ext/try_dup'
|
|
37
|
+
|
|
38
|
+
require 'dm-core/support/mash'
|
|
39
|
+
require 'dm-core/support/inflector/inflections'
|
|
40
|
+
require 'dm-core/support/inflector/methods'
|
|
41
|
+
require 'dm-core/support/inflections'
|
|
42
|
+
require 'dm-core/support/chainable'
|
|
43
|
+
require 'dm-core/support/deprecate'
|
|
44
|
+
require 'dm-core/support/descendant_set'
|
|
45
|
+
require 'dm-core/support/equalizer'
|
|
46
|
+
require 'dm-core/support/assertions'
|
|
47
|
+
require 'dm-core/support/lazy_array'
|
|
48
|
+
require 'dm-core/support/local_object_space'
|
|
49
|
+
require 'dm-core/support/hook'
|
|
50
|
+
require 'dm-core/support/subject'
|
|
51
|
+
require 'dm-core/support/ordered_set'
|
|
52
|
+
require 'dm-core/support/subject_set'
|
|
53
|
+
|
|
54
|
+
require 'dm-core/query'
|
|
55
|
+
require 'dm-core/query/conditions/operation'
|
|
56
|
+
require 'dm-core/query/conditions/comparison'
|
|
57
|
+
require 'dm-core/query/operator'
|
|
58
|
+
require 'dm-core/query/direction'
|
|
59
|
+
require 'dm-core/query/path'
|
|
60
|
+
require 'dm-core/query/sort'
|
|
61
|
+
|
|
62
|
+
require 'dm-core/resource'
|
|
63
|
+
require 'dm-core/resource/persistence_state'
|
|
64
|
+
require 'dm-core/resource/persistence_state/transient'
|
|
65
|
+
require 'dm-core/resource/persistence_state/immutable'
|
|
66
|
+
require 'dm-core/resource/persistence_state/persisted'
|
|
67
|
+
require 'dm-core/resource/persistence_state/clean'
|
|
68
|
+
require 'dm-core/resource/persistence_state/deleted'
|
|
69
|
+
require 'dm-core/resource/persistence_state/dirty'
|
|
70
|
+
|
|
71
|
+
require 'dm-core/property'
|
|
72
|
+
require 'dm-core/property/invalid_value_error'
|
|
73
|
+
require 'dm-core/property/object'
|
|
74
|
+
require 'dm-core/property/string'
|
|
75
|
+
require 'dm-core/property/binary'
|
|
76
|
+
require 'dm-core/property/text'
|
|
77
|
+
require 'dm-core/property/numeric'
|
|
78
|
+
require 'dm-core/property/float'
|
|
79
|
+
require 'dm-core/property/decimal'
|
|
80
|
+
require 'dm-core/property/boolean'
|
|
81
|
+
require 'dm-core/property/integer'
|
|
82
|
+
require 'dm-core/property/serial'
|
|
83
|
+
require 'dm-core/property/date'
|
|
84
|
+
require 'dm-core/property/date_time'
|
|
85
|
+
require 'dm-core/property/time'
|
|
86
|
+
require 'dm-core/property/class'
|
|
87
|
+
require 'dm-core/property/discriminator'
|
|
88
|
+
require 'dm-core/property/lookup'
|
|
89
|
+
require 'dm-core/property_set'
|
|
90
|
+
|
|
91
|
+
require 'dm-core/model'
|
|
92
|
+
require 'dm-core/model/hook'
|
|
93
|
+
require 'dm-core/model/is'
|
|
94
|
+
require 'dm-core/model/scope'
|
|
95
|
+
require 'dm-core/model/relationship'
|
|
96
|
+
require 'dm-core/model/property'
|
|
97
|
+
|
|
98
|
+
require 'dm-core/collection'
|
|
99
|
+
require 'dm-core/relationship_set'
|
|
100
|
+
require 'dm-core/associations/relationship'
|
|
101
|
+
require 'dm-core/associations/one_to_many'
|
|
102
|
+
require 'dm-core/associations/one_to_one'
|
|
103
|
+
require 'dm-core/associations/many_to_one'
|
|
104
|
+
require 'dm-core/associations/many_to_many'
|
|
105
|
+
|
|
106
|
+
require 'dm-core/identity_map'
|
|
107
|
+
require 'dm-core/repository'
|
|
108
|
+
require 'dm-core/adapters'
|
|
109
|
+
require 'dm-core/adapters/abstract_adapter'
|
|
110
|
+
|
|
111
|
+
require 'dm-core/support/logger'
|
|
112
|
+
require 'dm-core/support/naming_conventions'
|
|
113
|
+
require 'dm-core/version'
|
|
114
|
+
|
|
115
|
+
require 'dm-core/core_ext/kernel' # TODO: do not load automatically
|
|
116
|
+
require 'dm-core/core_ext/symbol' # TODO: do not load automatically
|
|
117
|
+
|
|
118
|
+
require 'dm-core/backwards' # TODO: do not load automatically
|
|
119
|
+
|
|
120
|
+
# A logger should always be present. Lets be consistent with DO
|
|
121
|
+
DataMapper::Logger.new(StringIO.new, :fatal)
|
|
122
|
+
|
|
123
|
+
unless defined?(Infinity)
|
|
124
|
+
Infinity = 1.0/0
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# == Setup and Configuration
|
|
128
|
+
# DataMapper uses URIs or a connection hash to connect to your data-store.
|
|
129
|
+
# URI connections takes the form of:
|
|
130
|
+
# DataMapper.setup(:default, 'protocol://username:password@localhost:port/path/to/repo')
|
|
131
|
+
#
|
|
132
|
+
# Breaking this down, the first argument is the name you wish to give this
|
|
133
|
+
# connection. If you do not specify one, it will be assigned :default. If you
|
|
134
|
+
# would like to connect to more than one data-store, simply issue this command
|
|
135
|
+
# again, but with a different name specified.
|
|
136
|
+
#
|
|
137
|
+
# In order to issue ORM commands without specifying the repository context, you
|
|
138
|
+
# must define the :default database. Otherwise, you'll need to wrap your ORM
|
|
139
|
+
# calls in <tt>repository(:name) { }</tt>.
|
|
140
|
+
#
|
|
141
|
+
# Second, the URI breaks down into the access protocol, the username, the
|
|
142
|
+
# server, the password, and whatever path information is needed to properly
|
|
143
|
+
# address the data-store on the server.
|
|
144
|
+
#
|
|
145
|
+
# Here's some examples
|
|
146
|
+
# DataMapper.setup(:default, 'sqlite3://path/to/your/project/db/development.db')
|
|
147
|
+
# DataMapper.setup(:default, 'mysql://localhost/dm_core_test')
|
|
148
|
+
# # no auth-info
|
|
149
|
+
# DataMapper.setup(:default, 'postgres://root:supahsekret@127.0.0.1/dm_core_test')
|
|
150
|
+
# # with auth-info
|
|
151
|
+
#
|
|
152
|
+
#
|
|
153
|
+
# Alternatively, you can supply a hash as the second parameter, which would
|
|
154
|
+
# take the form:
|
|
155
|
+
#
|
|
156
|
+
# DataMapper.setup(:default, {
|
|
157
|
+
# :adapter => 'adapter_name_here',
|
|
158
|
+
# :database => 'path/to/repo',
|
|
159
|
+
# :username => 'username',
|
|
160
|
+
# :password => 'password',
|
|
161
|
+
# :host => 'hostname'
|
|
162
|
+
# })
|
|
163
|
+
#
|
|
164
|
+
# === Logging
|
|
165
|
+
# To turn on error logging to STDOUT, issue:
|
|
166
|
+
#
|
|
167
|
+
# DataMapper::Logger.new($stdout, :debug)
|
|
168
|
+
#
|
|
169
|
+
# You can pass a file location ("/path/to/log/file.log") in place of $stdout.
|
|
170
|
+
# see DataMapper::Logger for more information.
|
|
171
|
+
#
|
|
172
|
+
module DataMapper
|
|
173
|
+
extend DataMapper::Assertions
|
|
174
|
+
|
|
175
|
+
class RepositoryNotSetupError < StandardError; end
|
|
176
|
+
|
|
177
|
+
class IncompleteModelError < StandardError; end
|
|
178
|
+
|
|
179
|
+
class PluginNotFoundError < StandardError; end
|
|
180
|
+
|
|
181
|
+
class UnknownRelationshipError < StandardError; end
|
|
182
|
+
|
|
183
|
+
class ObjectNotFoundError < RuntimeError; end
|
|
184
|
+
|
|
185
|
+
class PersistenceError < RuntimeError; end
|
|
186
|
+
|
|
187
|
+
class UpdateConflictError < PersistenceError; end
|
|
188
|
+
|
|
189
|
+
class SaveFailureError < PersistenceError
|
|
190
|
+
attr_reader :resource
|
|
191
|
+
|
|
192
|
+
def initialize(message, resource)
|
|
193
|
+
super(message)
|
|
194
|
+
@resource = resource
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
class ImmutableError < RuntimeError; end
|
|
199
|
+
|
|
200
|
+
class ImmutableDeletedError < ImmutableError; end
|
|
201
|
+
|
|
202
|
+
# Raised on attempt to operate on collection of child objects
|
|
203
|
+
# when parent object is not yet saved.
|
|
204
|
+
# For instance, if your article object is not saved,
|
|
205
|
+
# but you try to fetch or scope down comments (1:n case), or
|
|
206
|
+
# publications (n:m case), operation cannot be completed
|
|
207
|
+
# because parent object's keys are not yet persisted,
|
|
208
|
+
# and thus there is no FK value to use in the query.
|
|
209
|
+
class UnsavedParentError < PersistenceError; end
|
|
210
|
+
|
|
211
|
+
# @api private
|
|
212
|
+
def self.root
|
|
213
|
+
@root ||= Pathname(__FILE__).dirname.parent.expand_path.freeze
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# Setups up a connection to a data-store
|
|
217
|
+
#
|
|
218
|
+
# @param [Symbol] name
|
|
219
|
+
# a name for the context, defaults to :default
|
|
220
|
+
# @param [Hash(Symbol => String), Addressable::URI, String] uri_or_options
|
|
221
|
+
# connection information
|
|
222
|
+
#
|
|
223
|
+
# @return [DataMapper::Adapters::AbstractAdapter]
|
|
224
|
+
# the resulting setup adapter
|
|
225
|
+
#
|
|
226
|
+
# @raise [ArgumentError] "+name+ must be a Symbol, but was..."
|
|
227
|
+
# indicates that an invalid argument was passed for name[Symbol]
|
|
228
|
+
# @raise [ArgumentError] "+uri_or_options+ must be a Hash, URI or String, but was..."
|
|
229
|
+
# indicates that connection information could not be gleaned from
|
|
230
|
+
# the given uri_or_options[Hash, Addressable::URI, String]
|
|
231
|
+
#
|
|
232
|
+
# @api public
|
|
233
|
+
def self.setup(*args)
|
|
234
|
+
adapter = args.first
|
|
235
|
+
|
|
236
|
+
unless adapter.kind_of?(Adapters::AbstractAdapter)
|
|
237
|
+
adapter = Adapters.new(*args)
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
Repository.adapters[adapter.name] = adapter
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
# Block Syntax
|
|
244
|
+
# Pushes the named repository onto the context-stack,
|
|
245
|
+
# yields a new session, and pops the context-stack.
|
|
246
|
+
#
|
|
247
|
+
# Non-Block Syntax
|
|
248
|
+
# Returns the current session, or if there is none,
|
|
249
|
+
# a new Session.
|
|
250
|
+
#
|
|
251
|
+
# @param [Symbol] args the name of a repository to act within or return, :default is default
|
|
252
|
+
#
|
|
253
|
+
# @yield [Proc] (optional) block to execute within the context of the named repository
|
|
254
|
+
#
|
|
255
|
+
# @api public
|
|
256
|
+
def self.repository(name = nil)
|
|
257
|
+
context = Repository.context
|
|
258
|
+
|
|
259
|
+
current_repository = if name
|
|
260
|
+
name = name.to_sym
|
|
261
|
+
context.detect { |repository| repository.name == name }
|
|
262
|
+
else
|
|
263
|
+
name = Repository.default_name
|
|
264
|
+
context.last
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
current_repository ||= Repository.new(name)
|
|
268
|
+
|
|
269
|
+
if block_given?
|
|
270
|
+
current_repository.scope { |*block_args| yield(*block_args) }
|
|
271
|
+
else
|
|
272
|
+
current_repository
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
# Perform necessary steps to finalize DataMapper for the current repository
|
|
277
|
+
#
|
|
278
|
+
# This method should be called after loading all models and plugins.
|
|
279
|
+
#
|
|
280
|
+
# It ensures foreign key properties and anonymous join models are created.
|
|
281
|
+
# These are otherwise lazily declared, which can lead to unexpected errors.
|
|
282
|
+
# It also performs basic validity checking of the DataMapper models.
|
|
283
|
+
#
|
|
284
|
+
# @return [self]
|
|
285
|
+
#
|
|
286
|
+
# @api public
|
|
287
|
+
def self.finalize
|
|
288
|
+
Model.descendants.each { |model| model.finalize }
|
|
289
|
+
self
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
end # module DataMapper
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
module DataMapper
|
|
2
|
+
module Adapters
|
|
3
|
+
extend Chainable
|
|
4
|
+
extend DataMapper::Assertions
|
|
5
|
+
|
|
6
|
+
# Set up an adapter for a storage engine
|
|
7
|
+
#
|
|
8
|
+
# @see DataMapper.setup
|
|
9
|
+
#
|
|
10
|
+
# @api private
|
|
11
|
+
def self.new(repository_name, options)
|
|
12
|
+
options = normalize_options(options)
|
|
13
|
+
adapter_class(options.fetch(:adapter)).new(repository_name, options)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# The path used to require the in memory adapter
|
|
17
|
+
#
|
|
18
|
+
# Set this if you want to register your own adapter
|
|
19
|
+
# to be used when you specify an 'in_memory' connection
|
|
20
|
+
# during
|
|
21
|
+
#
|
|
22
|
+
# @see DataMapper.setup
|
|
23
|
+
#
|
|
24
|
+
# @param [String] path
|
|
25
|
+
# the path used to require the desired in memory adapter
|
|
26
|
+
#
|
|
27
|
+
# @api semipublic
|
|
28
|
+
def self.in_memory_adapter_path=(path)
|
|
29
|
+
@in_memory_adapter_path = path
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# The path used to require the in memory adapter
|
|
33
|
+
#
|
|
34
|
+
# @see DataMapper.setup
|
|
35
|
+
#
|
|
36
|
+
# @return [String]
|
|
37
|
+
# the path used to require the desired in memory adapter
|
|
38
|
+
#
|
|
39
|
+
# @api semipublic
|
|
40
|
+
def self.in_memory_adapter_path
|
|
41
|
+
@in_memory_adapter_path ||= 'dm-core/adapters/in_memory_adapter'
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
class << self
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
# Normalize the arguments passed to new()
|
|
48
|
+
#
|
|
49
|
+
# Turns options hash or connection URI into the options hash used
|
|
50
|
+
# by the adapter.
|
|
51
|
+
#
|
|
52
|
+
# @param [Hash, Addressable::URI, String] options
|
|
53
|
+
# the options to be normalized
|
|
54
|
+
#
|
|
55
|
+
# @return [Mash]
|
|
56
|
+
# the options normalized as a Mash
|
|
57
|
+
#
|
|
58
|
+
# @api private
|
|
59
|
+
def normalize_options(options)
|
|
60
|
+
case options
|
|
61
|
+
when Hash then normalize_options_hash(options)
|
|
62
|
+
when Addressable::URI then normalize_options_uri(options)
|
|
63
|
+
when String then normalize_options_string(options)
|
|
64
|
+
else
|
|
65
|
+
assert_kind_of 'options', options, Hash, Addressable::URI, String
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Normalize Hash options into a Mash
|
|
70
|
+
#
|
|
71
|
+
# @param [Hash] hash
|
|
72
|
+
# the hash to be normalized
|
|
73
|
+
#
|
|
74
|
+
# @return [Mash]
|
|
75
|
+
# the options normalized as a Mash
|
|
76
|
+
#
|
|
77
|
+
# @api private
|
|
78
|
+
def normalize_options_hash(hash)
|
|
79
|
+
DataMapper::Ext::Hash.to_mash(hash)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Normalize Addressable::URI options into a Mash
|
|
83
|
+
#
|
|
84
|
+
# @param [Addressable::URI] uri
|
|
85
|
+
# the uri to be normalized
|
|
86
|
+
#
|
|
87
|
+
# @return [Mash]
|
|
88
|
+
# the options normalized as a Mash
|
|
89
|
+
#
|
|
90
|
+
# @api private
|
|
91
|
+
def normalize_options_uri(uri)
|
|
92
|
+
options = normalize_options_hash(uri.to_hash)
|
|
93
|
+
|
|
94
|
+
# Extract the name/value pairs from the query portion of the
|
|
95
|
+
# connection uri, and set them as options directly.
|
|
96
|
+
if options.fetch(:query)
|
|
97
|
+
options.update(uri.query_values)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
options[:adapter] = options.fetch(:scheme)
|
|
101
|
+
|
|
102
|
+
options
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Normalize String options into a Mash
|
|
106
|
+
#
|
|
107
|
+
# @param [String] string
|
|
108
|
+
# the string to be normalized
|
|
109
|
+
#
|
|
110
|
+
# @return [Mash]
|
|
111
|
+
# the options normalized as a Mash
|
|
112
|
+
#
|
|
113
|
+
# @api private
|
|
114
|
+
def normalize_options_string(string)
|
|
115
|
+
normalize_options_uri(Addressable::URI.parse(string))
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Return the adapter class constant
|
|
119
|
+
#
|
|
120
|
+
# @example
|
|
121
|
+
# DataMapper::Adapters.send(:adapter_class, 'mysql') # => DataMapper::Adapters::MysqlAdapter
|
|
122
|
+
#
|
|
123
|
+
# @param [Symbol] name
|
|
124
|
+
# the name of the adapter
|
|
125
|
+
#
|
|
126
|
+
# @return [Class]
|
|
127
|
+
# the AbstractAdapter subclass
|
|
128
|
+
#
|
|
129
|
+
# @api private
|
|
130
|
+
def adapter_class(name)
|
|
131
|
+
adapter_name = normalize_adapter_name(name)
|
|
132
|
+
class_name = (DataMapper::Inflector.camelize(adapter_name) << 'Adapter').to_sym
|
|
133
|
+
load_adapter(adapter_name) unless const_defined?(class_name)
|
|
134
|
+
const_get(class_name)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Return the name of the adapter
|
|
138
|
+
#
|
|
139
|
+
# @example
|
|
140
|
+
# DataMapper::Adapters.adapter_name('MysqlAdapter') # => 'mysql'
|
|
141
|
+
#
|
|
142
|
+
# @param [String] const_name
|
|
143
|
+
# the adapter constant name
|
|
144
|
+
#
|
|
145
|
+
# @return [String]
|
|
146
|
+
# the name of the adapter
|
|
147
|
+
#
|
|
148
|
+
# @api semipublic
|
|
149
|
+
def adapter_name(const_name)
|
|
150
|
+
const_name.to_s.chomp('Adapter').downcase
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Require the adapter library
|
|
154
|
+
#
|
|
155
|
+
# @param [String, Symbol] name
|
|
156
|
+
# the name of the adapter
|
|
157
|
+
#
|
|
158
|
+
# @return [Boolean]
|
|
159
|
+
# true if the adapter is loaded
|
|
160
|
+
#
|
|
161
|
+
# @api private
|
|
162
|
+
def load_adapter(name)
|
|
163
|
+
require "dm-#{name}-adapter"
|
|
164
|
+
rescue LoadError => original_error
|
|
165
|
+
begin
|
|
166
|
+
require in_memory_adapter?(name) ? in_memory_adapter_path : legacy_path(name)
|
|
167
|
+
rescue LoadError
|
|
168
|
+
raise original_error
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Returns wether or not the given adapter name is considered an in memory adapter
|
|
173
|
+
#
|
|
174
|
+
# @param [String, Symbol] name
|
|
175
|
+
# the name of the adapter
|
|
176
|
+
#
|
|
177
|
+
# @return [Boolean]
|
|
178
|
+
# true if the adapter is considered to be an in memory adapter
|
|
179
|
+
#
|
|
180
|
+
# @api private
|
|
181
|
+
def in_memory_adapter?(name)
|
|
182
|
+
name.to_s == 'in_memory'
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Returns the fallback filename that would be used to require the named adapter
|
|
186
|
+
#
|
|
187
|
+
# The fallback format is "#{name}_adapter" and will be phased out in favor of
|
|
188
|
+
# the properly 'namespaced' "dm-#{name}-adapter" format.
|
|
189
|
+
#
|
|
190
|
+
# @param [String, Symbol] name
|
|
191
|
+
# the name of the adapter to require
|
|
192
|
+
#
|
|
193
|
+
# @return [String]
|
|
194
|
+
# the filename that gets required for the adapter identified by name
|
|
195
|
+
#
|
|
196
|
+
# @api private
|
|
197
|
+
def legacy_path(name)
|
|
198
|
+
"#{name}_adapter"
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# Adjust the adapter name to match the name used in the gem providing the adapter
|
|
202
|
+
#
|
|
203
|
+
# @param [String, Symbol] name
|
|
204
|
+
# the name of the adapter
|
|
205
|
+
#
|
|
206
|
+
# @return [String]
|
|
207
|
+
# the normalized adapter name
|
|
208
|
+
#
|
|
209
|
+
# @api private
|
|
210
|
+
def normalize_adapter_name(name)
|
|
211
|
+
(original = name.to_s) == 'sqlite3' ? 'sqlite' : original
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
extendable do
|
|
217
|
+
# @api private
|
|
218
|
+
def const_added(const_name)
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end # module Adapters
|
|
222
|
+
end # module DataMapper
|