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,45 @@
1
+ # encoding: UTF-8
2
+ require 'set'
3
+
4
+ module MarkMapper
5
+ module Plugins
6
+ module Protected
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ class_attribute :protected_attributes
11
+ end
12
+
13
+ module ClassMethods
14
+ def attr_protected(*attrs)
15
+ raise AccessibleOrProtected.new(name) if try(:accessible_attributes?)
16
+ self.protected_attributes = Set.new(attrs) + (protected_attributes || [])
17
+ end
18
+
19
+ def key(*args)
20
+ key = super
21
+ attr_protected key.name.to_sym if key.options[:protected]
22
+ key
23
+ end
24
+ end
25
+
26
+ def attributes=(attrs={})
27
+ super(filter_protected_attrs(attrs))
28
+ end
29
+
30
+ def update_attributes(attrs={})
31
+ super(filter_protected_attrs(attrs))
32
+ end
33
+
34
+ def update_attributes!(attrs={})
35
+ super(filter_protected_attrs(attrs))
36
+ end
37
+
38
+ protected
39
+ def filter_protected_attrs(attrs)
40
+ return attrs if protected_attributes.blank? || attrs.blank?
41
+ attrs.dup.delete_if { |key, val| protected_attributes.include?(key.to_sym) }
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,173 @@
1
+ # encoding: UTF-8
2
+ require 'mark_mapper/plugins/querying/decorated_markmapper_query'
3
+
4
+ module MarkMapper
5
+ module Plugins
6
+ module Querying
7
+ extend ActiveSupport::Concern
8
+
9
+ module ClassMethods
10
+ extend Forwardable
11
+
12
+ def_delegators :query, *Querying::Methods
13
+
14
+ def find_by_id(id)
15
+ find_one(:_id => id)
16
+ end
17
+
18
+ def first_or_create(args)
19
+ first(args) || create(args.reject { |key, value| !key?(key) })
20
+ end
21
+
22
+ def first_or_new(args)
23
+ first(args) || new(args.reject { |key, value| !key?(key) })
24
+ end
25
+
26
+ def create(*docs)
27
+ initialize_each(*docs) do |doc|
28
+ yield doc if block_given?
29
+ doc.save
30
+ end
31
+ end
32
+
33
+ def create!(*docs)
34
+ initialize_each(*docs) do |doc|
35
+ yield doc if block_given?
36
+ doc.save!
37
+ end
38
+ end
39
+
40
+ def update(*args)
41
+ if args.length == 1
42
+ update_multiple(args[0])
43
+ else
44
+ id, attributes = args
45
+ update_single(id, attributes)
46
+ end
47
+ end
48
+
49
+ # @api private for now
50
+ def query(options={})
51
+ query = MarkMapper::Plugins::Querying::DecoratedMarkMapperQuery.new(collection, :transformer => transformer)
52
+ query.object_ids(object_id_keys)
53
+ query.amend(options)
54
+ query.model(self)
55
+ query
56
+ end
57
+ alias_method :scoped, :query
58
+
59
+ # @api private for now
60
+ def criteria_hash(criteria={})
61
+ MarkMapper::CriteriaHash.new(criteria, :object_ids => object_id_keys)
62
+ end
63
+
64
+ private
65
+ def transformer
66
+ @transformer ||= lambda { |doc| load(doc) }
67
+ end
68
+
69
+ def initialize_each(*docs)
70
+ instances = []
71
+ docs = [{}] if docs.blank?
72
+ docs.flatten.each do |attrs|
73
+ doc = new(attrs)
74
+ yield(doc)
75
+ instances << doc
76
+ end
77
+ instances.size == 1 ? instances[0] : instances
78
+ end
79
+
80
+ def update_single(id, attrs)
81
+ if id.blank? || attrs.blank? || !attrs.is_a?(Hash)
82
+ raise ArgumentError, "Updating a single document requires an id and a hash of attributes"
83
+ end
84
+
85
+ find(id).tap do |doc|
86
+ doc.update_attributes(attrs)
87
+ end
88
+ end
89
+
90
+ def update_multiple(docs)
91
+ unless docs.is_a?(Hash)
92
+ raise ArgumentError, "Updating multiple documents takes 1 argument and it must be hash"
93
+ end
94
+
95
+ instances = []
96
+ docs.each_pair { |id, attrs| instances << update(id, attrs) }
97
+ instances
98
+ end
99
+ end
100
+
101
+ def save(options={})
102
+ options.assert_valid_keys(:validate)
103
+ create_or_update(options)
104
+ end
105
+
106
+ def save!(options={})
107
+ save(options) || raise(DocumentNotValid.new(self))
108
+ end
109
+
110
+ def destroy
111
+ delete
112
+ end
113
+
114
+ def delete
115
+ self.class.delete(id).tap { @_destroyed = true } if persisted?
116
+ end
117
+
118
+ private
119
+ def create_or_update(options={})
120
+ result = persisted? ? update(options) : create(options)
121
+ result != false
122
+ end
123
+
124
+ def create(options={})
125
+ save_to_collection(options.merge(:persistence_method => :insert))
126
+ end
127
+
128
+ def update(options={})
129
+ save_to_collection(options.reverse_merge(:persistence_method => :save))
130
+ end
131
+
132
+ def save_to_collection(options={})
133
+ @_new = false
134
+ method = options.delete(:persistence_method) || :save
135
+ update = to_marklogic
136
+
137
+ case method
138
+ when :insert
139
+ collection.insert(update)
140
+ when :save
141
+ collection.save(update)
142
+ when :update
143
+ update.stringify_keys!
144
+
145
+ id = update.delete("_id")
146
+
147
+ set_values = update
148
+ unset_values = {}
149
+
150
+ if fields_for_set = options.delete(:set_fields)
151
+ set_values = set_values.slice(*fields_for_set)
152
+ end
153
+
154
+ if fields_for_unset = options.delete(:unset_fields)
155
+ fields_for_unset.each do |field|
156
+ unset_values[field] = true
157
+ end
158
+ end
159
+
160
+ find_query = { :_id => id }
161
+
162
+ update_query = {}
163
+ update_query["$set"] = set_values if set_values.any?
164
+ update_query["$unset"] = unset_values if unset_values.any?
165
+
166
+ if update_query.any?
167
+ collection.update(find_query, update_query)
168
+ end
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,75 @@
1
+ # encoding: UTF-8
2
+ module MarkMapper
3
+ module Plugins
4
+ module Querying
5
+ Methods = MarkMapper::Methods + [:delete, :delete_all, :destroy, :destroy_all, :find!]
6
+
7
+ class DecoratedMarkMapperQuery < ::MarkMapper::Query
8
+ include DynamicQuerying::ClassMethods
9
+
10
+ def delete(*ids)
11
+ where(:_id => ids.flatten).remove
12
+ end
13
+
14
+ def delete_all(options = {})
15
+ where(options).remove
16
+ end
17
+
18
+ def destroy(*ids)
19
+ [find!(*ids.flatten.compact.uniq)].flatten.each { |doc| doc.destroy }
20
+ end
21
+
22
+ def destroy_all(options={})
23
+ find_each(options) { |document| document.destroy }
24
+ end
25
+
26
+ def model(model=nil)
27
+ return @model if model.nil?
28
+ @model = model
29
+ self
30
+ end
31
+
32
+ def criteria_hash
33
+ @model.dealias_keys super
34
+ end
35
+
36
+ def options_hash
37
+ super.tap do |options|
38
+ case options[:fields]
39
+ when Hash
40
+ options[:fields] = @model.dealias options[:fields]
41
+ when Array
42
+ options[:fields] = options[:fields].map do |field|
43
+ key = keys[field.to_s]
44
+ key && key.abbr || field
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ def find!(*ids)
51
+ ids = Array(ids).flatten.uniq
52
+ raise DocumentNotFound, "Couldn't find without an ID" if ids.size == 0
53
+
54
+ find(*ids).tap do |result|
55
+ if result.nil? || ids.size != Array(result).size
56
+ raise DocumentNotFound, "Couldn't find all of the ids (#{ids.join(',')}). Found #{Array(result).size}, but was expecting #{ids.size}"
57
+ end
58
+ end
59
+ end
60
+
61
+ protected
62
+
63
+ def method_missing(method, *args, &block)
64
+ return super unless model.respond_to?(method)
65
+ result = model.send(method, *args, &block)
66
+ if result.is_a?(MarkMapper::Query)
67
+ merge(result)
68
+ else
69
+ result
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,79 @@
1
+ # encoding: UTF-8
2
+ module MarkMapper
3
+ module Plugins
4
+ module Rails
5
+ autoload :ActiveRecordAssociationAdapter, "mark_mapper/plugins/rails/active_record_association_adapter"
6
+ extend ActiveSupport::Concern
7
+
8
+ def to_param
9
+ id.to_s if persisted?
10
+ end
11
+
12
+ def to_model
13
+ self
14
+ end
15
+
16
+ def to_key
17
+ [id] if persisted?
18
+ end
19
+
20
+ def new_record?
21
+ new?
22
+ end
23
+
24
+ def read_attribute(name)
25
+ self[name]
26
+ end
27
+
28
+ def read_attribute_before_type_cast(name)
29
+ @__mm_pre_cast ||= {}
30
+ name = unalias_key name
31
+ if !@__mm_pre_cast.key?(name)
32
+ @__mm_pre_cast[name] = read_attribute(name)
33
+ end
34
+ @__mm_pre_cast[name]
35
+ end
36
+
37
+ def write_attribute(name, value)
38
+ self[name] = value
39
+ self[name]
40
+ end
41
+
42
+ def write_key(name, value)
43
+ name = unalias_key name
44
+ @__mm_pre_cast ||= {}
45
+ @__mm_pre_cast[name.to_s] = value
46
+ super
47
+ end
48
+
49
+ module ClassMethods
50
+ def has_one(*args)
51
+ one(*args)
52
+ end
53
+
54
+ def has_many(*args, &extension)
55
+ many(*args, &extension)
56
+ end
57
+
58
+ def column_names
59
+ unaliased_keys.keys
60
+ end
61
+
62
+ # Returns returns an ActiveRecordAssociationAdapter for an association. This adapter has an API that is a
63
+ # subset of ActiveRecord::Reflection::AssociationReflection. This allows MarkMapper to be used with the
64
+ # association helpers in gems like simple_form and formtastic.
65
+ def reflect_on_association(name)
66
+ ActiveRecordAssociationAdapter.for_association(associations[name]) if associations[name]
67
+ end
68
+
69
+ def create_accessors_for(key)
70
+ super do
71
+ define_method "#{key.name}_before_type_cast" do
72
+ read_attribute_before_type_cast key.name
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: UTF-8
2
+ module MarkMapper
3
+ module Plugins
4
+ module Rails
5
+ class ActiveRecordAssociationAdapter
6
+ attr_reader :klass, :macro, :name, :options
7
+
8
+ def self.for_association(association)
9
+ macro = case association
10
+ when MarkMapper::Plugins::Associations::BelongsToAssociation
11
+ :belongs_to
12
+ when MarkMapper::Plugins::Associations::ManyAssociation
13
+ :has_many
14
+ when MarkMapper::Plugins::Associations::OneAssociation
15
+ :has_one
16
+ else
17
+ raise "no #{name} for association of type #{association.class}"
18
+ end
19
+
20
+ new(association, macro)
21
+ end
22
+
23
+ def initialize(association, macro)
24
+ @klass, @name = association.klass, association.name
25
+ # only include compatible options
26
+ @options = association.options.slice(:conditions, :order)
27
+
28
+ @macro = macro
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,82 @@
1
+ # encoding: UTF-8
2
+ module MarkMapper
3
+ module Plugins
4
+ module Sci
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ extend ActiveSupport::DescendantsTracker
9
+ end
10
+
11
+ module ClassMethods
12
+ def inherited(subclass)
13
+ super
14
+ if @collection_name == subclass.instance_variable_get("@collection_name")
15
+ key :_type, String unless key?(:_type)
16
+ subclass.single_collection_parent = self
17
+ subclass.instance_variable_set("@single_collection_inherited", true)
18
+ else
19
+ remove_key :_type
20
+ end
21
+ end
22
+
23
+ def single_collection_root
24
+ parent = single_collection_parent || self
25
+ root = parent
26
+
27
+ while parent
28
+ parent = parent.single_collection_parent
29
+ root = parent unless parent.nil?
30
+ end
31
+
32
+ root
33
+ end
34
+
35
+ def criteria_hash(criteria={})
36
+ if single_collection_inherited?
37
+ super criteria.merge(:_type => name)
38
+ else
39
+ super
40
+ end
41
+ end
42
+
43
+ def set_collection_name(name)
44
+ if single_collection_inherited?
45
+ single_collection_parent.remove_key :_type
46
+ single_collection_parent = nil
47
+ @single_collection_inherited = false
48
+ end
49
+ @collection_defined = true
50
+ super
51
+ end
52
+
53
+ def explicit_collection_defined?
54
+ @collection_defined == true
55
+ end
56
+
57
+ def single_collection_parent
58
+ @single_collection_parent
59
+ end
60
+
61
+ def single_collection_parent=(parent)
62
+ @single_collection_parent = parent
63
+ end
64
+
65
+ def single_collection_inherited?
66
+ !!(@single_collection_inherited ||= false)
67
+ end
68
+
69
+ def query(options={})
70
+ super.tap do |query|
71
+ query[:_type] = {'$eq' => [name] + descendants.map(&:name)} if single_collection_inherited?
72
+ end
73
+ end
74
+ end
75
+
76
+ def initialize(*args)
77
+ super
78
+ write_key :_type, self.class.name if self.class.key?(:_type)
79
+ end
80
+ end
81
+ end
82
+ end