mark_mapper 0.0.1

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.
Files changed (211) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.rdoc +39 -0
  4. data/examples/attr_accessible.rb +24 -0
  5. data/examples/attr_protected.rb +24 -0
  6. data/examples/cache_key.rb +26 -0
  7. data/examples/custom_types.rb +26 -0
  8. data/examples/identity_map.rb +30 -0
  9. data/examples/identity_map/automatic.rb +2 -0
  10. data/examples/keys.rb +42 -0
  11. data/examples/modifiers/set.rb +27 -0
  12. data/examples/plugins.rb +40 -0
  13. data/examples/querying.rb +39 -0
  14. data/examples/sample_app.rb +43 -0
  15. data/examples/scopes.rb +56 -0
  16. data/examples/validating/embedded_docs.rb +31 -0
  17. data/lib/mark_mapper.rb +125 -0
  18. data/lib/mark_mapper/config.rb +90 -0
  19. data/lib/mark_mapper/connection.rb +60 -0
  20. data/lib/mark_mapper/criteria_hash.rb +194 -0
  21. data/lib/mark_mapper/document.rb +46 -0
  22. data/lib/mark_mapper/embedded_document.rb +32 -0
  23. data/lib/mark_mapper/exceptions.rb +33 -0
  24. data/lib/mark_mapper/extensions/array.rb +27 -0
  25. data/lib/mark_mapper/extensions/boolean.rb +45 -0
  26. data/lib/mark_mapper/extensions/date.rb +29 -0
  27. data/lib/mark_mapper/extensions/duplicable.rb +86 -0
  28. data/lib/mark_mapper/extensions/float.rb +18 -0
  29. data/lib/mark_mapper/extensions/hash.rb +26 -0
  30. data/lib/mark_mapper/extensions/integer.rb +27 -0
  31. data/lib/mark_mapper/extensions/kernel.rb +11 -0
  32. data/lib/mark_mapper/extensions/nil_class.rb +18 -0
  33. data/lib/mark_mapper/extensions/object.rb +30 -0
  34. data/lib/mark_mapper/extensions/object_id.rb +18 -0
  35. data/lib/mark_mapper/extensions/set.rb +20 -0
  36. data/lib/mark_mapper/extensions/string.rb +31 -0
  37. data/lib/mark_mapper/extensions/symbol.rb +87 -0
  38. data/lib/mark_mapper/extensions/time.rb +29 -0
  39. data/lib/mark_mapper/locale/en.yml +5 -0
  40. data/lib/mark_mapper/middleware/identity_map.rb +41 -0
  41. data/lib/mark_mapper/normalizers/criteria_hash_key.rb +17 -0
  42. data/lib/mark_mapper/normalizers/criteria_hash_value.rb +66 -0
  43. data/lib/mark_mapper/normalizers/fields_value.rb +26 -0
  44. data/lib/mark_mapper/normalizers/hash_key.rb +19 -0
  45. data/lib/mark_mapper/normalizers/integer.rb +19 -0
  46. data/lib/mark_mapper/normalizers/options_hash_value.rb +83 -0
  47. data/lib/mark_mapper/normalizers/sort_value.rb +55 -0
  48. data/lib/mark_mapper/options_hash.rb +103 -0
  49. data/lib/mark_mapper/pagination.rb +6 -0
  50. data/lib/mark_mapper/pagination/collection.rb +32 -0
  51. data/lib/mark_mapper/pagination/paginator.rb +46 -0
  52. data/lib/mark_mapper/plugins.rb +22 -0
  53. data/lib/mark_mapper/plugins/accessible.rb +61 -0
  54. data/lib/mark_mapper/plugins/active_model.rb +18 -0
  55. data/lib/mark_mapper/plugins/associations.rb +96 -0
  56. data/lib/mark_mapper/plugins/associations/base.rb +98 -0
  57. data/lib/mark_mapper/plugins/associations/belongs_to_association.rb +63 -0
  58. data/lib/mark_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +35 -0
  59. data/lib/mark_mapper/plugins/associations/belongs_to_proxy.rb +52 -0
  60. data/lib/mark_mapper/plugins/associations/collection.rb +29 -0
  61. data/lib/mark_mapper/plugins/associations/embedded_collection.rb +44 -0
  62. data/lib/mark_mapper/plugins/associations/in_array_proxy.rb +133 -0
  63. data/lib/mark_mapper/plugins/associations/many_association.rb +63 -0
  64. data/lib/mark_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
  65. data/lib/mark_mapper/plugins/associations/many_documents_proxy.rb +142 -0
  66. data/lib/mark_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +32 -0
  67. data/lib/mark_mapper/plugins/associations/many_embedded_proxy.rb +24 -0
  68. data/lib/mark_mapper/plugins/associations/many_polymorphic_proxy.rb +14 -0
  69. data/lib/mark_mapper/plugins/associations/one_as_proxy.rb +22 -0
  70. data/lib/mark_mapper/plugins/associations/one_association.rb +48 -0
  71. data/lib/mark_mapper/plugins/associations/one_embedded_polymorphic_proxy.rb +30 -0
  72. data/lib/mark_mapper/plugins/associations/one_embedded_proxy.rb +44 -0
  73. data/lib/mark_mapper/plugins/associations/one_proxy.rb +95 -0
  74. data/lib/mark_mapper/plugins/associations/proxy.rb +138 -0
  75. data/lib/mark_mapper/plugins/associations/single_association.rb +46 -0
  76. data/lib/mark_mapper/plugins/caching.rb +21 -0
  77. data/lib/mark_mapper/plugins/callbacks.rb +42 -0
  78. data/lib/mark_mapper/plugins/clone.rb +24 -0
  79. data/lib/mark_mapper/plugins/counter_cache.rb +97 -0
  80. data/lib/mark_mapper/plugins/dirty.rb +61 -0
  81. data/lib/mark_mapper/plugins/document.rb +41 -0
  82. data/lib/mark_mapper/plugins/dumpable.rb +22 -0
  83. data/lib/mark_mapper/plugins/dynamic_querying.rb +45 -0
  84. data/lib/mark_mapper/plugins/dynamic_querying/dynamic_finder.rb +44 -0
  85. data/lib/mark_mapper/plugins/embedded_callbacks.rb +81 -0
  86. data/lib/mark_mapper/plugins/embedded_document.rb +53 -0
  87. data/lib/mark_mapper/plugins/equality.rb +23 -0
  88. data/lib/mark_mapper/plugins/identity_map.rb +144 -0
  89. data/lib/mark_mapper/plugins/indexable.rb +86 -0
  90. data/lib/mark_mapper/plugins/inspect.rb +16 -0
  91. data/lib/mark_mapper/plugins/keys.rb +470 -0
  92. data/lib/mark_mapper/plugins/keys/key.rb +134 -0
  93. data/lib/mark_mapper/plugins/keys/static.rb +45 -0
  94. data/lib/mark_mapper/plugins/logger.rb +18 -0
  95. data/lib/mark_mapper/plugins/modifiers.rb +140 -0
  96. data/lib/mark_mapper/plugins/pagination.rb +16 -0
  97. data/lib/mark_mapper/plugins/partial_updates.rb +77 -0
  98. data/lib/mark_mapper/plugins/persistence.rb +79 -0
  99. data/lib/mark_mapper/plugins/protected.rb +45 -0
  100. data/lib/mark_mapper/plugins/querying.rb +173 -0
  101. data/lib/mark_mapper/plugins/querying/decorated_markmapper_query.rb +75 -0
  102. data/lib/mark_mapper/plugins/rails.rb +79 -0
  103. data/lib/mark_mapper/plugins/rails/active_record_association_adapter.rb +33 -0
  104. data/lib/mark_mapper/plugins/sci.rb +82 -0
  105. data/lib/mark_mapper/plugins/scopes.rb +28 -0
  106. data/lib/mark_mapper/plugins/serialization.rb +109 -0
  107. data/lib/mark_mapper/plugins/timestamps.rb +29 -0
  108. data/lib/mark_mapper/plugins/touch.rb +18 -0
  109. data/lib/mark_mapper/plugins/userstamps.rb +18 -0
  110. data/lib/mark_mapper/plugins/validations.rb +96 -0
  111. data/lib/mark_mapper/query.rb +278 -0
  112. data/lib/mark_mapper/railtie.rb +52 -0
  113. data/lib/mark_mapper/railtie/database.rake +65 -0
  114. data/lib/mark_mapper/translation.rb +10 -0
  115. data/lib/mark_mapper/version.rb +4 -0
  116. data/lib/rails/generators/mark_mapper/config/config_generator.rb +37 -0
  117. data/lib/rails/generators/mark_mapper/config/templates/marklogic.yml +19 -0
  118. data/lib/rails/generators/mark_mapper/model/model_generator.rb +40 -0
  119. data/lib/rails/generators/mark_mapper/model/templates/model.rb +17 -0
  120. data/spec/config/mark_mapper.yml +6 -0
  121. data/spec/examples_spec.rb +25 -0
  122. data/spec/functional/accessible_spec.rb +198 -0
  123. data/spec/functional/associations/belongs_to_polymorphic_proxy_spec.rb +64 -0
  124. data/spec/functional/associations/belongs_to_proxy_spec.rb +255 -0
  125. data/spec/functional/associations/in_array_proxy_spec.rb +349 -0
  126. data/spec/functional/associations/many_documents_as_proxy_spec.rb +230 -0
  127. data/spec/functional/associations/many_documents_proxy_spec.rb +968 -0
  128. data/spec/functional/associations/many_embedded_polymorphic_proxy_spec.rb +238 -0
  129. data/spec/functional/associations/many_embedded_proxy_spec.rb +288 -0
  130. data/spec/functional/associations/many_polymorphic_proxy_spec.rb +302 -0
  131. data/spec/functional/associations/one_as_proxy_spec.rb +489 -0
  132. data/spec/functional/associations/one_embedded_polymorphic_proxy_spec.rb +207 -0
  133. data/spec/functional/associations/one_embedded_proxy_spec.rb +100 -0
  134. data/spec/functional/associations/one_proxy_spec.rb +406 -0
  135. data/spec/functional/associations_spec.rb +48 -0
  136. data/spec/functional/caching_spec.rb +75 -0
  137. data/spec/functional/callbacks_spec.rb +330 -0
  138. data/spec/functional/counter_cache_spec.rb +235 -0
  139. data/spec/functional/dirty_spec.rb +316 -0
  140. data/spec/functional/document_spec.rb +310 -0
  141. data/spec/functional/dumpable_spec.rb +24 -0
  142. data/spec/functional/dynamic_querying_spec.rb +75 -0
  143. data/spec/functional/embedded_document_spec.rb +316 -0
  144. data/spec/functional/equality_spec.rb +20 -0
  145. data/spec/functional/extensions_spec.rb +16 -0
  146. data/spec/functional/identity_map_spec.rb +483 -0
  147. data/spec/functional/keys_spec.rb +339 -0
  148. data/spec/functional/logger_spec.rb +20 -0
  149. data/spec/functional/modifiers_spec.rb +446 -0
  150. data/spec/functional/options_hash_spec.rb +41 -0
  151. data/spec/functional/pagination_spec.rb +89 -0
  152. data/spec/functional/partial_updates_spec.rb +530 -0
  153. data/spec/functional/protected_spec.rb +199 -0
  154. data/spec/functional/querying_spec.rb +984 -0
  155. data/spec/functional/rails_spec.rb +55 -0
  156. data/spec/functional/sci_spec.rb +374 -0
  157. data/spec/functional/scopes_spec.rb +204 -0
  158. data/spec/functional/static_keys_spec.rb +153 -0
  159. data/spec/functional/timestamps_spec.rb +97 -0
  160. data/spec/functional/touch_spec.rb +125 -0
  161. data/spec/functional/userstamps_spec.rb +46 -0
  162. data/spec/functional/validations_spec.rb +416 -0
  163. data/spec/quality_spec.rb +51 -0
  164. data/spec/spec_helper.rb +150 -0
  165. data/spec/support/matchers.rb +15 -0
  166. data/spec/support/models.rb +256 -0
  167. data/spec/symbol_operator_spec.rb +70 -0
  168. data/spec/symbol_spec.rb +9 -0
  169. data/spec/unit/associations/base_spec.rb +146 -0
  170. data/spec/unit/associations/belongs_to_association_spec.rb +30 -0
  171. data/spec/unit/associations/many_association_spec.rb +64 -0
  172. data/spec/unit/associations/one_association_spec.rb +48 -0
  173. data/spec/unit/associations/proxy_spec.rb +103 -0
  174. data/spec/unit/clone_spec.rb +79 -0
  175. data/spec/unit/config_generator_spec.rb +24 -0
  176. data/spec/unit/criteria_hash_spec.rb +218 -0
  177. data/spec/unit/document_spec.rb +251 -0
  178. data/spec/unit/dynamic_finder_spec.rb +125 -0
  179. data/spec/unit/embedded_document_spec.rb +676 -0
  180. data/spec/unit/equality_spec.rb +38 -0
  181. data/spec/unit/exceptions_spec.rb +12 -0
  182. data/spec/unit/extensions_spec.rb +368 -0
  183. data/spec/unit/identity_map_middleware_spec.rb +134 -0
  184. data/spec/unit/inspect_spec.rb +47 -0
  185. data/spec/unit/key_spec.rb +276 -0
  186. data/spec/unit/keys_spec.rb +155 -0
  187. data/spec/unit/mark_mapper_spec.rb +37 -0
  188. data/spec/unit/model_generator_spec.rb +45 -0
  189. data/spec/unit/normalizers/criteria_hash_key_spec.rb +37 -0
  190. data/spec/unit/normalizers/criteria_hash_value_spec.rb +200 -0
  191. data/spec/unit/normalizers/fields_value_spec.rb +45 -0
  192. data/spec/unit/normalizers/hash_key_spec.rb +15 -0
  193. data/spec/unit/normalizers/integer_spec.rb +24 -0
  194. data/spec/unit/normalizers/options_hash_value_spec.rb +99 -0
  195. data/spec/unit/normalizers/sort_value_spec.rb +98 -0
  196. data/spec/unit/options_hash_spec.rb +64 -0
  197. data/spec/unit/pagination/collection_spec.rb +30 -0
  198. data/spec/unit/pagination/paginator_spec.rb +118 -0
  199. data/spec/unit/pagination_spec.rb +11 -0
  200. data/spec/unit/plugins_spec.rb +89 -0
  201. data/spec/unit/query_spec.rb +837 -0
  202. data/spec/unit/rails_compatibility_spec.rb +40 -0
  203. data/spec/unit/rails_reflect_on_association_spec.rb +118 -0
  204. data/spec/unit/rails_spec.rb +188 -0
  205. data/spec/unit/serialization_spec.rb +169 -0
  206. data/spec/unit/serializers/json_serializer_spec.rb +218 -0
  207. data/spec/unit/serializers/xml_serializer_spec.rb +198 -0
  208. data/spec/unit/time_zones_spec.rb +44 -0
  209. data/spec/unit/translation_spec.rb +27 -0
  210. data/spec/unit/validations_spec.rb +588 -0
  211. metadata +307 -0
@@ -0,0 +1,98 @@
1
+ # encoding: UTF-8
2
+ module MarkMapper
3
+ module Plugins
4
+ module Associations
5
+ class Base
6
+ attr_reader :name, :options, :query_options
7
+
8
+ # Options that should not be considered MarkLogic query options/criteria
9
+ AssociationOptions = [:as, :class, :class_name, :dependent, :extend, :foreign_key, :in, :polymorphic, :autosave, :touch, :counter_cache]
10
+
11
+ def initialize(name, options={}, &extension)
12
+ @name, @options, @query_options, @original_options = name.to_sym, {}, {}, options
13
+ options.symbolize_keys!
14
+ options[:extend] = modularized_extensions(extension, options[:extend])
15
+ separate_options_and_conditions
16
+ end
17
+
18
+ def class_name
19
+ @class_name ||= options[:class_name] || name.to_s.camelize
20
+ end
21
+
22
+ def klass
23
+ @klass ||= options[:class] || class_name.constantize
24
+ end
25
+
26
+ def polymorphic?
27
+ !!@options[:polymorphic]
28
+ end
29
+
30
+ def as?
31
+ !!@options[:as]
32
+ end
33
+
34
+ def in_array?
35
+ !!@options[:in]
36
+ end
37
+
38
+ def embeddable?
39
+ klass.embeddable?
40
+ end
41
+
42
+ def touch?
43
+ !!@options[:touch]
44
+ end
45
+
46
+ def counter_cache?
47
+ !!@options[:counter_cache]
48
+ end
49
+
50
+ def type_key_name
51
+ "_type"
52
+ end
53
+
54
+ def as
55
+ @options[:as] || self.name
56
+ end
57
+
58
+ def foreign_key
59
+ @options[:foreign_key] || "#{name}_id"
60
+ end
61
+
62
+ def ivar
63
+ @ivar ||= "@_#{name}"
64
+ end
65
+
66
+ # :nocov:
67
+ def proxy_class
68
+ raise NotImplementedError
69
+ end
70
+
71
+ def autosave?
72
+ raise NotImplementedError
73
+ end
74
+ # :nocov:
75
+
76
+ def setup(model)
77
+ end
78
+
79
+ private
80
+ def separate_options_and_conditions
81
+ @original_options.each_pair do |key, value|
82
+ if AssociationOptions.include?(key)
83
+ @options[key] = value
84
+ else
85
+ @query_options[key] = value
86
+ end
87
+ end
88
+ end
89
+
90
+ def modularized_extensions(*extensions)
91
+ extensions.flatten.compact.map do |extension|
92
+ Proc === extension ? Module.new(&extension) : extension
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,63 @@
1
+ # encoding: UTF-8
2
+ module MarkMapper
3
+ module Plugins
4
+ module Associations
5
+ class BelongsToAssociation < SingleAssociation
6
+ def type_key_name
7
+ "#{as}_type"
8
+ end
9
+
10
+ def embeddable?
11
+ false
12
+ end
13
+
14
+ def proxy_class
15
+ @proxy_class ||= polymorphic? ? BelongsToPolymorphicProxy : BelongsToProxy
16
+ end
17
+
18
+ def setup(model)
19
+ model.key foreign_key, ObjectId unless model.key?(foreign_key)
20
+ model.key type_key_name, String unless model.key?(type_key_name) if polymorphic?
21
+ super
22
+ add_touch_callbacks if touch?
23
+ add_counter_cache if counter_cache?
24
+ end
25
+
26
+ def autosave?
27
+ options.fetch(:autosave, false)
28
+ end
29
+
30
+ def add_touch_callbacks
31
+ name = self.name
32
+ method_name = "belongs_to_touch_after_save_or_destroy_for_#{name}"
33
+ touch = options.fetch(:touch)
34
+
35
+ @model.send(:define_method, method_name) do
36
+ record = send(name)
37
+
38
+ unless record.nil?
39
+ if touch == true
40
+ record.touch
41
+ else
42
+ record.touch(touch)
43
+ end
44
+ end
45
+ end
46
+
47
+ @model.after_save(method_name)
48
+ @model.after_touch(method_name)
49
+ @model.after_destroy(method_name)
50
+ end
51
+
52
+ def add_counter_cache
53
+ options = {}
54
+ if @options[:counter_cache] && @options[:counter_cache] != true
55
+ options[:field] = @options[:counter_cache]
56
+ end
57
+
58
+ @model.counter_cache name, options
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,35 @@
1
+ # encoding: UTF-8
2
+ module MarkMapper
3
+ module Plugins
4
+ module Associations
5
+ class BelongsToPolymorphicProxy < Proxy
6
+ def replace(doc)
7
+ if doc
8
+ doc.save unless doc.persisted?
9
+ id, type = doc.id, doc.class.name
10
+ end
11
+
12
+ proxy_owner[association.foreign_key] = id
13
+ proxy_owner[association.type_key_name] = type
14
+ reset
15
+ unless doc.nil?
16
+ loaded
17
+ @target = doc
18
+ end
19
+
20
+ @target
21
+ end
22
+
23
+ protected
24
+ def find_target
25
+ return nil if association_class.nil? || proxy_owner[association.foreign_key].nil?
26
+ association_class.find_by_id(proxy_owner[association.foreign_key])
27
+ end
28
+
29
+ def association_class
30
+ proxy_owner[association.type_key_name] ? proxy_owner[association.type_key_name].constantize : nil
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,52 @@
1
+ # encoding: UTF-8
2
+ module MarkMapper
3
+ module Plugins
4
+ module Associations
5
+ class BelongsToProxy < Proxy
6
+ def replace(doc)
7
+ if doc
8
+ doc.save if !doc.persisted?
9
+ id = doc.id
10
+ end
11
+
12
+ reset
13
+ proxy_owner[association.foreign_key] = id
14
+ unless doc.nil?
15
+ loaded
16
+ @target = doc
17
+ end
18
+ @target
19
+ end
20
+
21
+ def build(attrs={}, &block)
22
+ instantiate_target(:new, attrs, &block)
23
+ end
24
+
25
+ def create(attrs={}, &block)
26
+ instantiate_target(:create, attrs, &block)
27
+ end
28
+
29
+ def create!(attrs={}, &block)
30
+ instantiate_target(:create!, attrs, &block)
31
+ end
32
+
33
+ def save_to_collection(options={})
34
+ @target.save(options) if @target
35
+ end
36
+
37
+ protected
38
+ def find_target
39
+ return nil if proxy_owner[association.foreign_key].nil?
40
+ klass.find_by_id(proxy_owner[association.foreign_key])
41
+ end
42
+
43
+ def instantiate_target(instantiator, attrs={}, &block)
44
+ @target = klass.send(instantiator, attrs, &block)
45
+ proxy_owner[association.foreign_key] = @target.id
46
+ loaded
47
+ @target
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,29 @@
1
+ # encoding: UTF-8
2
+ module MarkMapper
3
+ module Plugins
4
+ module Associations
5
+ class Collection < Proxy
6
+ def to_ary
7
+ load_target
8
+ if target.is_a?(Array)
9
+ target.to_ary
10
+ else
11
+ Array(target)
12
+ end
13
+ end
14
+
15
+ alias_method :to_a, :to_ary
16
+
17
+ def include?(*args)
18
+ load_target
19
+ target.include?(*args)
20
+ end
21
+
22
+ def reset
23
+ super
24
+ target = []
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,44 @@
1
+ # encoding: UTF-8
2
+ module MarkMapper
3
+ module Plugins
4
+ module Associations
5
+ class EmbeddedCollection < Collection
6
+ def build(attributes={})
7
+ doc = klass.new(attributes)
8
+ assign_references(doc)
9
+ self << doc
10
+ doc
11
+ end
12
+
13
+ def find(id)
14
+ load_target
15
+ target.detect { |item| item.id.to_s == id || item.id == id }
16
+ end
17
+
18
+ def count
19
+ load_target
20
+ target.size
21
+ end
22
+
23
+ def <<(*docs)
24
+ load_target
25
+ docs.each do |doc|
26
+ assign_references(doc)
27
+ target << doc
28
+ end
29
+ end
30
+ alias_method :push, :<<
31
+ alias_method :concat, :<<
32
+
33
+ def save_to_collection(options={})
34
+ @target.each { |doc| doc.persist(options) } if @target
35
+ end
36
+
37
+ private
38
+ def assign_references(*docs)
39
+ docs.each { |doc| doc._parent_document = proxy_owner }
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,133 @@
1
+ # encoding: UTF-8
2
+ module MarkMapper
3
+ module Plugins
4
+ module Associations
5
+ class InArrayProxy < Collection
6
+ include DynamicQuerying::ClassMethods
7
+
8
+ def find(*args)
9
+ query.find(*scoped_ids(args))
10
+ end
11
+
12
+ def find!(*args)
13
+ query.find!(*scoped_ids(args))
14
+ end
15
+
16
+ def paginate(options)
17
+ return [] if ids.blank?
18
+ query.paginate(options)
19
+ end
20
+
21
+ def all(options={})
22
+ return [] if ids.blank?
23
+ query(options).all
24
+ end
25
+
26
+ def first(options={})
27
+ return nil if ids.blank?
28
+ query(options).first
29
+ end
30
+
31
+ def last(options={})
32
+ return nil if ids.blank?
33
+ query(options).last
34
+ end
35
+
36
+ def count(options={})
37
+ return 0 if ids.blank?
38
+ options.blank? ? ids.size : query(options).count
39
+ end
40
+
41
+ def destroy_all(options={})
42
+ all(options).each do |doc|
43
+ ids.delete(doc.id)
44
+ doc.destroy
45
+ end
46
+ reset
47
+ end
48
+
49
+ def delete_all(options={})
50
+ docs = query(options).fields(:_id).all
51
+ docs.each { |doc| ids.delete(doc.id) }
52
+ klass.delete(docs.map { |d| d.id })
53
+ reset
54
+ end
55
+
56
+ def nullify
57
+ replace([])
58
+ reset
59
+ end
60
+
61
+ def create(attrs={})
62
+ doc = klass.create(attrs)
63
+ if doc.persisted?
64
+ ids << doc.id
65
+ proxy_owner.save
66
+ reset
67
+ end
68
+ doc
69
+ end
70
+
71
+ def create!(attrs={})
72
+ doc = klass.create!(attrs)
73
+ if doc.persisted?
74
+ ids << doc.id
75
+ proxy_owner.save
76
+ reset
77
+ end
78
+ doc
79
+ end
80
+
81
+ def <<(*docs)
82
+ flatten_deeper(docs).each do |doc|
83
+ doc.save unless doc.persisted?
84
+ unless ids.include?(doc.id)
85
+ ids << doc.id
86
+ end
87
+ end
88
+ reset
89
+ end
90
+ alias_method :push, :<<
91
+ alias_method :concat, :<<
92
+
93
+ def replace(docs)
94
+ doc_ids = docs.map do |doc|
95
+ doc.save unless doc.persisted?
96
+ doc.id
97
+ end
98
+ ids.replace(doc_ids.uniq)
99
+ reset
100
+ end
101
+
102
+ private
103
+ def query(options={})
104
+ klass.
105
+ query(association.query_options).
106
+ amend(options).
107
+ amend(criteria)
108
+ end
109
+
110
+ def criteria
111
+ {:_id => ids}
112
+ end
113
+
114
+ def scoped_ids(args)
115
+ valid = args.flatten.select do |id|
116
+ id = ObjectId.to_marklogic(id) if klass.using_object_id?
117
+ ids.include?(id)
118
+ end
119
+ valid.empty? ? nil : valid
120
+ end
121
+
122
+ def find_target
123
+ return [] if ids.blank?
124
+ all
125
+ end
126
+
127
+ def ids
128
+ proxy_owner[options[:in]]
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end