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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.rdoc +39 -0
- data/examples/attr_accessible.rb +24 -0
- data/examples/attr_protected.rb +24 -0
- data/examples/cache_key.rb +26 -0
- data/examples/custom_types.rb +26 -0
- data/examples/identity_map.rb +30 -0
- data/examples/identity_map/automatic.rb +2 -0
- data/examples/keys.rb +42 -0
- data/examples/modifiers/set.rb +27 -0
- data/examples/plugins.rb +40 -0
- data/examples/querying.rb +39 -0
- data/examples/sample_app.rb +43 -0
- data/examples/scopes.rb +56 -0
- data/examples/validating/embedded_docs.rb +31 -0
- data/lib/mark_mapper.rb +125 -0
- data/lib/mark_mapper/config.rb +90 -0
- data/lib/mark_mapper/connection.rb +60 -0
- data/lib/mark_mapper/criteria_hash.rb +194 -0
- data/lib/mark_mapper/document.rb +46 -0
- data/lib/mark_mapper/embedded_document.rb +32 -0
- data/lib/mark_mapper/exceptions.rb +33 -0
- data/lib/mark_mapper/extensions/array.rb +27 -0
- data/lib/mark_mapper/extensions/boolean.rb +45 -0
- data/lib/mark_mapper/extensions/date.rb +29 -0
- data/lib/mark_mapper/extensions/duplicable.rb +86 -0
- data/lib/mark_mapper/extensions/float.rb +18 -0
- data/lib/mark_mapper/extensions/hash.rb +26 -0
- data/lib/mark_mapper/extensions/integer.rb +27 -0
- data/lib/mark_mapper/extensions/kernel.rb +11 -0
- data/lib/mark_mapper/extensions/nil_class.rb +18 -0
- data/lib/mark_mapper/extensions/object.rb +30 -0
- data/lib/mark_mapper/extensions/object_id.rb +18 -0
- data/lib/mark_mapper/extensions/set.rb +20 -0
- data/lib/mark_mapper/extensions/string.rb +31 -0
- data/lib/mark_mapper/extensions/symbol.rb +87 -0
- data/lib/mark_mapper/extensions/time.rb +29 -0
- data/lib/mark_mapper/locale/en.yml +5 -0
- data/lib/mark_mapper/middleware/identity_map.rb +41 -0
- data/lib/mark_mapper/normalizers/criteria_hash_key.rb +17 -0
- data/lib/mark_mapper/normalizers/criteria_hash_value.rb +66 -0
- data/lib/mark_mapper/normalizers/fields_value.rb +26 -0
- data/lib/mark_mapper/normalizers/hash_key.rb +19 -0
- data/lib/mark_mapper/normalizers/integer.rb +19 -0
- data/lib/mark_mapper/normalizers/options_hash_value.rb +83 -0
- data/lib/mark_mapper/normalizers/sort_value.rb +55 -0
- data/lib/mark_mapper/options_hash.rb +103 -0
- data/lib/mark_mapper/pagination.rb +6 -0
- data/lib/mark_mapper/pagination/collection.rb +32 -0
- data/lib/mark_mapper/pagination/paginator.rb +46 -0
- data/lib/mark_mapper/plugins.rb +22 -0
- data/lib/mark_mapper/plugins/accessible.rb +61 -0
- data/lib/mark_mapper/plugins/active_model.rb +18 -0
- data/lib/mark_mapper/plugins/associations.rb +96 -0
- data/lib/mark_mapper/plugins/associations/base.rb +98 -0
- data/lib/mark_mapper/plugins/associations/belongs_to_association.rb +63 -0
- data/lib/mark_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +35 -0
- data/lib/mark_mapper/plugins/associations/belongs_to_proxy.rb +52 -0
- data/lib/mark_mapper/plugins/associations/collection.rb +29 -0
- data/lib/mark_mapper/plugins/associations/embedded_collection.rb +44 -0
- data/lib/mark_mapper/plugins/associations/in_array_proxy.rb +133 -0
- data/lib/mark_mapper/plugins/associations/many_association.rb +63 -0
- data/lib/mark_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
- data/lib/mark_mapper/plugins/associations/many_documents_proxy.rb +142 -0
- data/lib/mark_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +32 -0
- data/lib/mark_mapper/plugins/associations/many_embedded_proxy.rb +24 -0
- data/lib/mark_mapper/plugins/associations/many_polymorphic_proxy.rb +14 -0
- data/lib/mark_mapper/plugins/associations/one_as_proxy.rb +22 -0
- data/lib/mark_mapper/plugins/associations/one_association.rb +48 -0
- data/lib/mark_mapper/plugins/associations/one_embedded_polymorphic_proxy.rb +30 -0
- data/lib/mark_mapper/plugins/associations/one_embedded_proxy.rb +44 -0
- data/lib/mark_mapper/plugins/associations/one_proxy.rb +95 -0
- data/lib/mark_mapper/plugins/associations/proxy.rb +138 -0
- data/lib/mark_mapper/plugins/associations/single_association.rb +46 -0
- data/lib/mark_mapper/plugins/caching.rb +21 -0
- data/lib/mark_mapper/plugins/callbacks.rb +42 -0
- data/lib/mark_mapper/plugins/clone.rb +24 -0
- data/lib/mark_mapper/plugins/counter_cache.rb +97 -0
- data/lib/mark_mapper/plugins/dirty.rb +61 -0
- data/lib/mark_mapper/plugins/document.rb +41 -0
- data/lib/mark_mapper/plugins/dumpable.rb +22 -0
- data/lib/mark_mapper/plugins/dynamic_querying.rb +45 -0
- data/lib/mark_mapper/plugins/dynamic_querying/dynamic_finder.rb +44 -0
- data/lib/mark_mapper/plugins/embedded_callbacks.rb +81 -0
- data/lib/mark_mapper/plugins/embedded_document.rb +53 -0
- data/lib/mark_mapper/plugins/equality.rb +23 -0
- data/lib/mark_mapper/plugins/identity_map.rb +144 -0
- data/lib/mark_mapper/plugins/indexable.rb +86 -0
- data/lib/mark_mapper/plugins/inspect.rb +16 -0
- data/lib/mark_mapper/plugins/keys.rb +470 -0
- data/lib/mark_mapper/plugins/keys/key.rb +134 -0
- data/lib/mark_mapper/plugins/keys/static.rb +45 -0
- data/lib/mark_mapper/plugins/logger.rb +18 -0
- data/lib/mark_mapper/plugins/modifiers.rb +140 -0
- data/lib/mark_mapper/plugins/pagination.rb +16 -0
- data/lib/mark_mapper/plugins/partial_updates.rb +77 -0
- data/lib/mark_mapper/plugins/persistence.rb +79 -0
- data/lib/mark_mapper/plugins/protected.rb +45 -0
- data/lib/mark_mapper/plugins/querying.rb +173 -0
- data/lib/mark_mapper/plugins/querying/decorated_markmapper_query.rb +75 -0
- data/lib/mark_mapper/plugins/rails.rb +79 -0
- data/lib/mark_mapper/plugins/rails/active_record_association_adapter.rb +33 -0
- data/lib/mark_mapper/plugins/sci.rb +82 -0
- data/lib/mark_mapper/plugins/scopes.rb +28 -0
- data/lib/mark_mapper/plugins/serialization.rb +109 -0
- data/lib/mark_mapper/plugins/timestamps.rb +29 -0
- data/lib/mark_mapper/plugins/touch.rb +18 -0
- data/lib/mark_mapper/plugins/userstamps.rb +18 -0
- data/lib/mark_mapper/plugins/validations.rb +96 -0
- data/lib/mark_mapper/query.rb +278 -0
- data/lib/mark_mapper/railtie.rb +52 -0
- data/lib/mark_mapper/railtie/database.rake +65 -0
- data/lib/mark_mapper/translation.rb +10 -0
- data/lib/mark_mapper/version.rb +4 -0
- data/lib/rails/generators/mark_mapper/config/config_generator.rb +37 -0
- data/lib/rails/generators/mark_mapper/config/templates/marklogic.yml +19 -0
- data/lib/rails/generators/mark_mapper/model/model_generator.rb +40 -0
- data/lib/rails/generators/mark_mapper/model/templates/model.rb +17 -0
- data/spec/config/mark_mapper.yml +6 -0
- data/spec/examples_spec.rb +25 -0
- data/spec/functional/accessible_spec.rb +198 -0
- data/spec/functional/associations/belongs_to_polymorphic_proxy_spec.rb +64 -0
- data/spec/functional/associations/belongs_to_proxy_spec.rb +255 -0
- data/spec/functional/associations/in_array_proxy_spec.rb +349 -0
- data/spec/functional/associations/many_documents_as_proxy_spec.rb +230 -0
- data/spec/functional/associations/many_documents_proxy_spec.rb +968 -0
- data/spec/functional/associations/many_embedded_polymorphic_proxy_spec.rb +238 -0
- data/spec/functional/associations/many_embedded_proxy_spec.rb +288 -0
- data/spec/functional/associations/many_polymorphic_proxy_spec.rb +302 -0
- data/spec/functional/associations/one_as_proxy_spec.rb +489 -0
- data/spec/functional/associations/one_embedded_polymorphic_proxy_spec.rb +207 -0
- data/spec/functional/associations/one_embedded_proxy_spec.rb +100 -0
- data/spec/functional/associations/one_proxy_spec.rb +406 -0
- data/spec/functional/associations_spec.rb +48 -0
- data/spec/functional/caching_spec.rb +75 -0
- data/spec/functional/callbacks_spec.rb +330 -0
- data/spec/functional/counter_cache_spec.rb +235 -0
- data/spec/functional/dirty_spec.rb +316 -0
- data/spec/functional/document_spec.rb +310 -0
- data/spec/functional/dumpable_spec.rb +24 -0
- data/spec/functional/dynamic_querying_spec.rb +75 -0
- data/spec/functional/embedded_document_spec.rb +316 -0
- data/spec/functional/equality_spec.rb +20 -0
- data/spec/functional/extensions_spec.rb +16 -0
- data/spec/functional/identity_map_spec.rb +483 -0
- data/spec/functional/keys_spec.rb +339 -0
- data/spec/functional/logger_spec.rb +20 -0
- data/spec/functional/modifiers_spec.rb +446 -0
- data/spec/functional/options_hash_spec.rb +41 -0
- data/spec/functional/pagination_spec.rb +89 -0
- data/spec/functional/partial_updates_spec.rb +530 -0
- data/spec/functional/protected_spec.rb +199 -0
- data/spec/functional/querying_spec.rb +984 -0
- data/spec/functional/rails_spec.rb +55 -0
- data/spec/functional/sci_spec.rb +374 -0
- data/spec/functional/scopes_spec.rb +204 -0
- data/spec/functional/static_keys_spec.rb +153 -0
- data/spec/functional/timestamps_spec.rb +97 -0
- data/spec/functional/touch_spec.rb +125 -0
- data/spec/functional/userstamps_spec.rb +46 -0
- data/spec/functional/validations_spec.rb +416 -0
- data/spec/quality_spec.rb +51 -0
- data/spec/spec_helper.rb +150 -0
- data/spec/support/matchers.rb +15 -0
- data/spec/support/models.rb +256 -0
- data/spec/symbol_operator_spec.rb +70 -0
- data/spec/symbol_spec.rb +9 -0
- data/spec/unit/associations/base_spec.rb +146 -0
- data/spec/unit/associations/belongs_to_association_spec.rb +30 -0
- data/spec/unit/associations/many_association_spec.rb +64 -0
- data/spec/unit/associations/one_association_spec.rb +48 -0
- data/spec/unit/associations/proxy_spec.rb +103 -0
- data/spec/unit/clone_spec.rb +79 -0
- data/spec/unit/config_generator_spec.rb +24 -0
- data/spec/unit/criteria_hash_spec.rb +218 -0
- data/spec/unit/document_spec.rb +251 -0
- data/spec/unit/dynamic_finder_spec.rb +125 -0
- data/spec/unit/embedded_document_spec.rb +676 -0
- data/spec/unit/equality_spec.rb +38 -0
- data/spec/unit/exceptions_spec.rb +12 -0
- data/spec/unit/extensions_spec.rb +368 -0
- data/spec/unit/identity_map_middleware_spec.rb +134 -0
- data/spec/unit/inspect_spec.rb +47 -0
- data/spec/unit/key_spec.rb +276 -0
- data/spec/unit/keys_spec.rb +155 -0
- data/spec/unit/mark_mapper_spec.rb +37 -0
- data/spec/unit/model_generator_spec.rb +45 -0
- data/spec/unit/normalizers/criteria_hash_key_spec.rb +37 -0
- data/spec/unit/normalizers/criteria_hash_value_spec.rb +200 -0
- data/spec/unit/normalizers/fields_value_spec.rb +45 -0
- data/spec/unit/normalizers/hash_key_spec.rb +15 -0
- data/spec/unit/normalizers/integer_spec.rb +24 -0
- data/spec/unit/normalizers/options_hash_value_spec.rb +99 -0
- data/spec/unit/normalizers/sort_value_spec.rb +98 -0
- data/spec/unit/options_hash_spec.rb +64 -0
- data/spec/unit/pagination/collection_spec.rb +30 -0
- data/spec/unit/pagination/paginator_spec.rb +118 -0
- data/spec/unit/pagination_spec.rb +11 -0
- data/spec/unit/plugins_spec.rb +89 -0
- data/spec/unit/query_spec.rb +837 -0
- data/spec/unit/rails_compatibility_spec.rb +40 -0
- data/spec/unit/rails_reflect_on_association_spec.rb +118 -0
- data/spec/unit/rails_spec.rb +188 -0
- data/spec/unit/serialization_spec.rb +169 -0
- data/spec/unit/serializers/json_serializer_spec.rb +218 -0
- data/spec/unit/serializers/xml_serializer_spec.rb +198 -0
- data/spec/unit/time_zones_spec.rb +44 -0
- data/spec/unit/translation_spec.rb +27 -0
- data/spec/unit/validations_spec.rb +588 -0
- 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
|