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
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# TODO: rename this DM::Symbol::Direction
|
|
2
|
+
|
|
3
|
+
# TODO: add a method to convert it into a DM::Query::Sort object, eg:
|
|
4
|
+
# operator.sort_for(model)
|
|
5
|
+
|
|
6
|
+
# TODO: rename #target to #property_name
|
|
7
|
+
|
|
8
|
+
# TODO: make sure Query converts this into a DM::Query::Sort object
|
|
9
|
+
# immediately and passes that down to the Adapter
|
|
10
|
+
|
|
11
|
+
# TODO: remove #get method
|
|
12
|
+
|
|
13
|
+
module DataMapper
|
|
14
|
+
class Query
|
|
15
|
+
class Direction < Operator
|
|
16
|
+
|
|
17
|
+
# @api private
|
|
18
|
+
def reverse!
|
|
19
|
+
@operator = @operator == :asc ? :desc : :asc
|
|
20
|
+
self
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# @api private
|
|
24
|
+
def get(resource)
|
|
25
|
+
Sort.new(target.get(resource), @operator == :asc)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
# @api private
|
|
31
|
+
def initialize(target, operator = :asc)
|
|
32
|
+
super
|
|
33
|
+
end
|
|
34
|
+
end # class Direction
|
|
35
|
+
end # class Query
|
|
36
|
+
end # module DataMapper
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# TODO: rename this DM::Symbol::Operator
|
|
2
|
+
|
|
3
|
+
# TODO: add a method to convert it into a DM::Query::AbstractComparison object, eg:
|
|
4
|
+
# operator.comparison_for(repository, model)
|
|
5
|
+
|
|
6
|
+
# TODO: rename #target to #property_name
|
|
7
|
+
|
|
8
|
+
module DataMapper
|
|
9
|
+
class Query
|
|
10
|
+
class Operator
|
|
11
|
+
include DataMapper::Assertions
|
|
12
|
+
extend Equalizer
|
|
13
|
+
|
|
14
|
+
equalize :target, :operator
|
|
15
|
+
|
|
16
|
+
# @api private
|
|
17
|
+
attr_reader :target
|
|
18
|
+
|
|
19
|
+
# @api private
|
|
20
|
+
attr_reader :operator
|
|
21
|
+
|
|
22
|
+
# @api private
|
|
23
|
+
def inspect
|
|
24
|
+
"#<#{self.class.name} @target=#{target.inspect} @operator=#{operator.inspect}>"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
# @api private
|
|
30
|
+
def initialize(target, operator)
|
|
31
|
+
@target, @operator = target, operator.to_sym
|
|
32
|
+
end
|
|
33
|
+
end # class Operator
|
|
34
|
+
end # class Query
|
|
35
|
+
end # module DataMapper
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# TODO: instead of an Array of Path objects, create a Relationship
|
|
2
|
+
# on the fly using :through on the previous relationship, creating a
|
|
3
|
+
# chain. Query::Path could then be a thin wrapper that specifies extra
|
|
4
|
+
# conditions on the Relationships, like the target property o match
|
|
5
|
+
# on.
|
|
6
|
+
|
|
7
|
+
module DataMapper
|
|
8
|
+
class Query
|
|
9
|
+
class Path
|
|
10
|
+
# TODO: replace this with BasicObject
|
|
11
|
+
instance_methods.each do |method|
|
|
12
|
+
next if method =~ /\A__/ ||
|
|
13
|
+
%w[ send class dup object_id kind_of? instance_of? respond_to? respond_to_missing? equal? freeze frozen? should should_not instance_variables instance_variable_set instance_variable_get instance_variable_defined? remove_instance_variable extend hash inspect to_s copy_object initialize_dup ].include?(method.to_s)
|
|
14
|
+
undef_method method
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
include DataMapper::Assertions
|
|
18
|
+
extend Equalizer
|
|
19
|
+
|
|
20
|
+
equalize :relationships, :property
|
|
21
|
+
|
|
22
|
+
# @api semipublic
|
|
23
|
+
attr_reader :repository_name
|
|
24
|
+
|
|
25
|
+
# @api semipublic
|
|
26
|
+
attr_reader :relationships
|
|
27
|
+
|
|
28
|
+
# @api semipublic
|
|
29
|
+
attr_reader :model
|
|
30
|
+
|
|
31
|
+
# @api semipublic
|
|
32
|
+
attr_reader :property
|
|
33
|
+
|
|
34
|
+
(Conditions::Comparison.slugs | [ :not ]).each do |slug|
|
|
35
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
36
|
+
def #{slug} # def eql
|
|
37
|
+
#{"raise \"explicit use of '#{slug}' operator is deprecated (#{caller.first})\"" if slug == :eql || slug == :in} # raise "explicit use of 'eql' operator is deprecated (#{caller.first})"
|
|
38
|
+
Operator.new(self, #{slug.inspect}) # Operator.new(self, :eql)
|
|
39
|
+
end # end
|
|
40
|
+
RUBY
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# @api public
|
|
44
|
+
def kind_of?(klass)
|
|
45
|
+
super || (defined?(@property) ? @property.kind_of?(klass) : false)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# @api public
|
|
49
|
+
def instance_of?(klass)
|
|
50
|
+
super || (defined?(@property) ? @property.instance_of?(klass) : false)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Used for creating :order options. This technique may be deprecated,
|
|
54
|
+
# so marking as semipublic until the issue is resolved.
|
|
55
|
+
#
|
|
56
|
+
# @api semipublic
|
|
57
|
+
def asc
|
|
58
|
+
Operator.new(property, :asc)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Used for creating :order options. This technique may be deprecated,
|
|
62
|
+
# so marking as semipublic until the issue is resolved.
|
|
63
|
+
#
|
|
64
|
+
# @api semipublic
|
|
65
|
+
def desc
|
|
66
|
+
Operator.new(property, :desc)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# @api semipublic
|
|
70
|
+
def respond_to?(method, include_private = false)
|
|
71
|
+
super ||
|
|
72
|
+
(defined?(@property) && @property.respond_to?(method, include_private)) ||
|
|
73
|
+
@model.relationships(@repository_name).named?(method) ||
|
|
74
|
+
@model.properties(@repository_name).named?(method)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
|
|
79
|
+
# @api semipublic
|
|
80
|
+
def initialize(relationships, property_name = nil)
|
|
81
|
+
@relationships = relationships.to_ary.dup
|
|
82
|
+
|
|
83
|
+
last_relationship = @relationships.last
|
|
84
|
+
@repository_name = last_relationship.relative_target_repository_name
|
|
85
|
+
@model = last_relationship.target_model
|
|
86
|
+
|
|
87
|
+
if property_name
|
|
88
|
+
property_name = property_name.to_sym
|
|
89
|
+
@property = @model.properties(@repository_name)[property_name] ||
|
|
90
|
+
raise(ArgumentError, "Unknown property '#{property_name}' in #{@model}")
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# @api semipublic
|
|
95
|
+
def method_missing(method, *args)
|
|
96
|
+
if @property
|
|
97
|
+
return @property.send(method, *args)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
path_class = self.class
|
|
101
|
+
|
|
102
|
+
if relationship = @model.relationships(@repository_name)[method]
|
|
103
|
+
return path_class.new(@relationships.dup << relationship)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
if @model.properties(@repository_name).named?(method)
|
|
107
|
+
return path_class.new(@relationships, method)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
raise NoMethodError, "undefined property or relationship '#{method}' on #{@model}"
|
|
111
|
+
end
|
|
112
|
+
end # class Path
|
|
113
|
+
end # class Query
|
|
114
|
+
end # module DataMapper
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# TODO: add #reverse and #reverse! methods
|
|
2
|
+
|
|
3
|
+
module DataMapper
|
|
4
|
+
class Query
|
|
5
|
+
class Sort
|
|
6
|
+
# @api semipublic
|
|
7
|
+
attr_reader :value
|
|
8
|
+
|
|
9
|
+
# @api semipublic
|
|
10
|
+
def direction
|
|
11
|
+
@ascending ? :ascending : :descending
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# @api private
|
|
15
|
+
def <=>(other)
|
|
16
|
+
other_value = other.value
|
|
17
|
+
value_nil = @value.nil?
|
|
18
|
+
other_nil = other_value.nil?
|
|
19
|
+
|
|
20
|
+
cmp = case
|
|
21
|
+
when value_nil then other_nil ? 0 : 1
|
|
22
|
+
when other_nil then -1
|
|
23
|
+
else
|
|
24
|
+
@value <=> other_value
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
@ascending ? cmp : cmp * -1
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
# @api private
|
|
33
|
+
def initialize(value, ascending = true)
|
|
34
|
+
@value = value
|
|
35
|
+
@ascending = ascending
|
|
36
|
+
end
|
|
37
|
+
end # class Sort
|
|
38
|
+
end # class Query
|
|
39
|
+
end # module DataMapper
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
module DataMapper
|
|
2
|
+
|
|
3
|
+
# A {SubjectSet} that keeps track of relationships defined in a {Model}
|
|
4
|
+
#
|
|
5
|
+
class RelationshipSet < SubjectSet
|
|
6
|
+
|
|
7
|
+
# A list of all relationships in this set
|
|
8
|
+
#
|
|
9
|
+
# @deprecated use DataMapper::RelationshipSet#each or DataMapper::RelationshipSet#to_a instead
|
|
10
|
+
#
|
|
11
|
+
# @return [Array]
|
|
12
|
+
# a list of all relationships in the set
|
|
13
|
+
#
|
|
14
|
+
# @api semipublic
|
|
15
|
+
def values
|
|
16
|
+
warn "#{self.class}#values is deprecated. Use #{self.class}#each or #{self.class}#to_a instead: #{caller.first}"
|
|
17
|
+
to_a
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# A list of all relationships in this set
|
|
21
|
+
#
|
|
22
|
+
# @deprecated use DataMapper::RelationshipSet#each instead
|
|
23
|
+
#
|
|
24
|
+
# @yield [DataMapper::Associations::Relationship]
|
|
25
|
+
# all relationships in the set
|
|
26
|
+
#
|
|
27
|
+
# @yieldparam [DataMapper::Associations::Relationship] relationship
|
|
28
|
+
# a relationship in the set
|
|
29
|
+
#
|
|
30
|
+
# @return [RelationshipSet] self
|
|
31
|
+
#
|
|
32
|
+
# @api semipublic
|
|
33
|
+
def each_value
|
|
34
|
+
warn "#{self.class}#each_value is deprecated. Use #{self.class}#each instead: #{caller.first}"
|
|
35
|
+
each { |relationship| yield(relationship) }
|
|
36
|
+
self
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Check wether this RelationshipSet includes an entry with the given name
|
|
40
|
+
#
|
|
41
|
+
# @deprecated use DataMapper::RelationshipSet#named? instead
|
|
42
|
+
#
|
|
43
|
+
# @param [#to_s] name
|
|
44
|
+
# the name of the entry to look for
|
|
45
|
+
#
|
|
46
|
+
# @return [Boolean]
|
|
47
|
+
# true if the set contains a relationship with the given name
|
|
48
|
+
#
|
|
49
|
+
# @api semipublic
|
|
50
|
+
def key?(name)
|
|
51
|
+
warn "#{self.class}#key? is deprecated. Use #{self.class}#named? instead: #{caller.first}"
|
|
52
|
+
named?(name)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Check wether this RelationshipSet includes an entry with the given name
|
|
56
|
+
#
|
|
57
|
+
# @deprecated use DataMapper::RelationshipSet#named? instead
|
|
58
|
+
#
|
|
59
|
+
# @param [#to_s] name
|
|
60
|
+
# the name of the entry to look for
|
|
61
|
+
#
|
|
62
|
+
# @return [Boolean]
|
|
63
|
+
# true if the set contains a relationship with the given name
|
|
64
|
+
#
|
|
65
|
+
# @api semipublic
|
|
66
|
+
def has_key?(name)
|
|
67
|
+
warn "#{self.class}#has_key? is deprecated. Use #{self.class}#named? instead: #{caller.first}"
|
|
68
|
+
named?(name)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end # class RelationshipSet
|
|
72
|
+
end # module DataMapper
|
|
@@ -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
|
+
unless adapters.key?(@name)
|
|
72
|
+
raise RepositoryNotSetupError, "Adapter not set: #{@name}. Did you forget to setup?"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
adapters[@name]
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Get the identity for a particular model within this repository.
|
|
80
|
+
#
|
|
81
|
+
# If one doesn't yet exist, create a new default in-memory IdentityMap
|
|
82
|
+
# for the requested model.
|
|
83
|
+
#
|
|
84
|
+
# TODO: create example
|
|
85
|
+
#
|
|
86
|
+
# @param [Model] model
|
|
87
|
+
# Model whose identity map should be returned
|
|
88
|
+
#
|
|
89
|
+
# @return [IdentityMap]
|
|
90
|
+
# The IdentityMap for model in this Repository
|
|
91
|
+
#
|
|
92
|
+
# @api private
|
|
93
|
+
def identity_map(model)
|
|
94
|
+
@identity_maps[model.base_model] ||= IdentityMap.new
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Executes a block in the scope of this Repository
|
|
98
|
+
#
|
|
99
|
+
# TODO: create example
|
|
100
|
+
#
|
|
101
|
+
# @yieldparam [Repository] repository
|
|
102
|
+
# yields self within the block
|
|
103
|
+
#
|
|
104
|
+
# @yield
|
|
105
|
+
# execute block in the scope of this Repository
|
|
106
|
+
#
|
|
107
|
+
# @api private
|
|
108
|
+
def scope
|
|
109
|
+
context = Repository.context
|
|
110
|
+
|
|
111
|
+
context << self
|
|
112
|
+
|
|
113
|
+
begin
|
|
114
|
+
yield self
|
|
115
|
+
ensure
|
|
116
|
+
context.pop
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Create a Query or subclass instance for this repository.
|
|
121
|
+
#
|
|
122
|
+
# @param [Model] model
|
|
123
|
+
# the Model to retrieve results from
|
|
124
|
+
# @param [Hash] options
|
|
125
|
+
# the conditions and scope
|
|
126
|
+
#
|
|
127
|
+
# @return [Query]
|
|
128
|
+
#
|
|
129
|
+
# @api semipublic
|
|
130
|
+
def new_query(model, options = {})
|
|
131
|
+
adapter.new_query(self, model, options)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Create one or more resource instances in this repository.
|
|
135
|
+
#
|
|
136
|
+
# TODO: create example
|
|
137
|
+
#
|
|
138
|
+
# @param [Enumerable(Resource)] resources
|
|
139
|
+
# The list of resources (model instances) to create
|
|
140
|
+
#
|
|
141
|
+
# @return [Integer]
|
|
142
|
+
# The number of records that were actually saved into the data-store
|
|
143
|
+
#
|
|
144
|
+
# @api semipublic
|
|
145
|
+
def create(resources)
|
|
146
|
+
adapter.create(resources)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Retrieve a collection of results of a query
|
|
150
|
+
#
|
|
151
|
+
# TODO: create example
|
|
152
|
+
#
|
|
153
|
+
# @param [Query] query
|
|
154
|
+
# composition of the query to perform
|
|
155
|
+
#
|
|
156
|
+
# @return [Array]
|
|
157
|
+
# result set of the query
|
|
158
|
+
#
|
|
159
|
+
# @api semipublic
|
|
160
|
+
def read(query)
|
|
161
|
+
return [] unless query.valid?
|
|
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
|
+
adapter.update(attributes, collection)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Delete one or more resource instances
|
|
184
|
+
#
|
|
185
|
+
# TODO: create example
|
|
186
|
+
#
|
|
187
|
+
# @param [Collection] collection
|
|
188
|
+
# collection of records to be deleted
|
|
189
|
+
#
|
|
190
|
+
# @return [Integer]
|
|
191
|
+
# the number of records deleted
|
|
192
|
+
#
|
|
193
|
+
# @api semipublic
|
|
194
|
+
def delete(collection)
|
|
195
|
+
return 0 unless collection.query.valid?
|
|
196
|
+
adapter.delete(collection)
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# Return a human readable representation of the repository
|
|
200
|
+
#
|
|
201
|
+
# TODO: create example
|
|
202
|
+
#
|
|
203
|
+
# @return [String]
|
|
204
|
+
# human readable representation of the repository
|
|
205
|
+
#
|
|
206
|
+
# @api private
|
|
207
|
+
def inspect
|
|
208
|
+
"#<#{self.class.name} @name=#{@name}>"
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
private
|
|
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
|
+
def initialize(name)
|
|
222
|
+
@name = name.to_sym
|
|
223
|
+
@identity_maps = {}
|
|
224
|
+
end
|
|
225
|
+
end # class Repository
|
|
226
|
+
end # module DataMapper
|