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,134 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MarkMapper
|
3
|
+
module Plugins
|
4
|
+
module Keys
|
5
|
+
class Key
|
6
|
+
attr_accessor :name, :type, :options, :default, :ivar, :abbr, :accessors
|
7
|
+
|
8
|
+
ID_STR = '_id'
|
9
|
+
|
10
|
+
def initialize(*args)
|
11
|
+
options_from_args = args.extract_options!
|
12
|
+
@name, @type = args.shift.to_s, args.shift
|
13
|
+
self.options = (options_from_args || {}).symbolize_keys
|
14
|
+
@dynamic = !!options[:__dynamic]
|
15
|
+
@embeddable = type.respond_to?(:embeddable?) ? type.embeddable? : false
|
16
|
+
@is_id = @name == ID_STR
|
17
|
+
@typecast = @options[:typecast]
|
18
|
+
@accessors = Array(@options[:accessors]).compact.map &:to_s
|
19
|
+
@has_default = !!options.key?(:default)
|
20
|
+
self.default = self.options[:default] if default?
|
21
|
+
|
22
|
+
if abbr = @options[:abbr] || @options[:alias] || @options[:field_name]
|
23
|
+
@abbr = abbr.to_s
|
24
|
+
elsif @name.match(/^[A-Z]/) and !dynamic?
|
25
|
+
@abbr = @name
|
26
|
+
@name = @name.gsub(/^([A-Z])/) {|m| m.downcase }
|
27
|
+
Kernel.warn "Key names may not start with uppercase letters. If your field starts " +
|
28
|
+
"with an uppercase letter, use :field_name to specify the real field name. " +
|
29
|
+
"Accessors called `#{@name}` have been created instead."
|
30
|
+
end
|
31
|
+
@ivar = :"@#{name}" if valid_ruby_name?
|
32
|
+
validate_key_name! unless dynamic? or !any_accessor?
|
33
|
+
end
|
34
|
+
|
35
|
+
def persisted_name
|
36
|
+
@abbr || @name
|
37
|
+
end
|
38
|
+
|
39
|
+
def ==(other)
|
40
|
+
@name == other.name && @type == other.type && @abbr == other.abbr
|
41
|
+
end
|
42
|
+
|
43
|
+
def embeddable?
|
44
|
+
@embeddable
|
45
|
+
end
|
46
|
+
|
47
|
+
def number?
|
48
|
+
type == Integer || type == Float
|
49
|
+
end
|
50
|
+
|
51
|
+
def default?
|
52
|
+
@has_default
|
53
|
+
end
|
54
|
+
|
55
|
+
def dynamic?
|
56
|
+
@dynamic
|
57
|
+
end
|
58
|
+
|
59
|
+
def get(value)
|
60
|
+
# Special Case: Generate default _id on access
|
61
|
+
value = default_value if @is_id and !value
|
62
|
+
|
63
|
+
if @typecast
|
64
|
+
klass = typecast_class # Don't make this lookup on every call
|
65
|
+
type.from_marklogic(value).map { |v| klass.from_marklogic(v) }
|
66
|
+
else
|
67
|
+
type.from_marklogic(value)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def set(value)
|
72
|
+
# Avoid tap here so we don't have to create a block binding.
|
73
|
+
values = type.to_marklogic(value)
|
74
|
+
if @typecast
|
75
|
+
values.map { |v| typecast_class.to_marklogic(v) }
|
76
|
+
else
|
77
|
+
values
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def default_value
|
82
|
+
return unless default?
|
83
|
+
if default.instance_of? Proc
|
84
|
+
type.to_marklogic default.call
|
85
|
+
else
|
86
|
+
# Using Marshal is easiest way to get a copy of mutable objects
|
87
|
+
# without getting an error on immutable objects
|
88
|
+
type.to_marklogic Marshal.load(Marshal.dump(default))
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def valid_ruby_name?
|
93
|
+
!!@name.match(/\A[a-z_][a-z0-9_]*\z/i)
|
94
|
+
end
|
95
|
+
|
96
|
+
RESERVED_KEYS = %w( id class object_id )
|
97
|
+
def reserved_name?
|
98
|
+
RESERVED_KEYS.include?(@name)
|
99
|
+
end
|
100
|
+
|
101
|
+
def read_accessor?
|
102
|
+
any_accessor? ["read"]
|
103
|
+
end
|
104
|
+
|
105
|
+
def write_accessor?
|
106
|
+
any_accessor? ["write"]
|
107
|
+
end
|
108
|
+
|
109
|
+
def predicate_accessor?
|
110
|
+
any_accessor? ["present", "predicate", "boolean"]
|
111
|
+
end
|
112
|
+
|
113
|
+
def any_accessor?(arr_opt = [])
|
114
|
+
return true if @accessors.empty?
|
115
|
+
return false unless (@accessors & ["skip", "none"]).empty?
|
116
|
+
return !(@accessors & arr_opt).empty?
|
117
|
+
end
|
118
|
+
|
119
|
+
private
|
120
|
+
def typecast_class
|
121
|
+
@typecast_class ||= options[:typecast].constantize
|
122
|
+
end
|
123
|
+
|
124
|
+
def validate_key_name!
|
125
|
+
if reserved_name?
|
126
|
+
raise MarkMapper::InvalidKey.new("`#{@name}` is a reserved key name (did you mean to use _id?)")
|
127
|
+
elsif !valid_ruby_name?
|
128
|
+
raise MarkMapper::InvalidKey.new("`#{@name}` is not a valid key name. Keys must match [a-z][a-z0-9_]*")
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module MarkMapper
|
2
|
+
module Plugins
|
3
|
+
module Keys
|
4
|
+
module Static
|
5
|
+
class MissingKeyError < StandardError; end
|
6
|
+
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
attr_writer :static_keys
|
11
|
+
|
12
|
+
def static_keys
|
13
|
+
@static_keys || false
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def read_key(name)
|
18
|
+
if !self.class.static_keys || self.class.key?(name)
|
19
|
+
super
|
20
|
+
else
|
21
|
+
raise MissingKeyError, "Tried to read the key #{name.inspect}, but no key was defined. Either define key :#{name} or set self.static_keys = false"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def write_key(name, value)
|
28
|
+
if !self.class.static_keys || self.class.key?(name)
|
29
|
+
super
|
30
|
+
else
|
31
|
+
raise MissingKeyError, "Tried to write the key #{name.inspect}, but no key was defined. Either define key :#{name} or set self.static_keys = false"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def load_from_database(attrs, with_cast = false)
|
36
|
+
return super if !self.class.static_keys || !attrs.respond_to?(:each)
|
37
|
+
|
38
|
+
attrs = attrs.select { |key, _| self.class.key?(key) }
|
39
|
+
|
40
|
+
super(attrs, with_cast)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MarkMapper
|
3
|
+
module Plugins
|
4
|
+
module Modifiers
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def increment(*args)
|
9
|
+
modifier_update('$inc', args)
|
10
|
+
end
|
11
|
+
|
12
|
+
def decrement(*args)
|
13
|
+
criteria, keys, options = criteria_and_keys_from_args(args)
|
14
|
+
values, to_decrement = keys.values, {}
|
15
|
+
keys.keys.each_with_index { |k, i| to_decrement[k] = -values[i].abs }
|
16
|
+
collection.update(criteria, {'$inc' => to_decrement})
|
17
|
+
end
|
18
|
+
|
19
|
+
def set(*args)
|
20
|
+
criteria, updates, options = criteria_and_keys_from_args(args)
|
21
|
+
updates.each do |key, value|
|
22
|
+
updates[key] = keys[key.to_s].set(value) if key?(key)
|
23
|
+
end
|
24
|
+
modifier_update('$set', [criteria, updates, options])
|
25
|
+
end
|
26
|
+
|
27
|
+
def unset(*args)
|
28
|
+
if args[0].is_a?(Hash)
|
29
|
+
criteria, keys = args.shift, args
|
30
|
+
options = keys.last.is_a?(Hash) ? keys.pop : {}
|
31
|
+
else
|
32
|
+
keys, ids = args.partition { |arg| arg.is_a?(Symbol) }
|
33
|
+
options = ids.last.is_a?(Hash) ? ids.pop : {}
|
34
|
+
criteria = {:id => ids}
|
35
|
+
end
|
36
|
+
|
37
|
+
criteria = criteria_hash(criteria).to_hash
|
38
|
+
updates = keys.inject({}) { |hash, key| hash[key] = 1; hash }
|
39
|
+
modifier_update('$unset', [criteria, updates, options])
|
40
|
+
end
|
41
|
+
|
42
|
+
def push(*args)
|
43
|
+
modifier_update('$push', args)
|
44
|
+
end
|
45
|
+
|
46
|
+
def push_all(*args)
|
47
|
+
modifier_update('$pushAll', args)
|
48
|
+
end
|
49
|
+
|
50
|
+
def add_to_set(*args)
|
51
|
+
modifier_update('$addToSet', args)
|
52
|
+
end
|
53
|
+
alias push_uniq add_to_set
|
54
|
+
|
55
|
+
def pull(*args)
|
56
|
+
modifier_update('$pull', args)
|
57
|
+
end
|
58
|
+
|
59
|
+
def pull_all(*args)
|
60
|
+
modifier_update('$pullAll', args)
|
61
|
+
end
|
62
|
+
|
63
|
+
def pop(*args)
|
64
|
+
modifier_update('$pop', args)
|
65
|
+
end
|
66
|
+
|
67
|
+
def find_and_modify(args)
|
68
|
+
args[:query] = dealias_keys(args[:query]) if args.key? :query
|
69
|
+
args[:update] = dealias_keys(args[:update]) if args.key? :update
|
70
|
+
collection.find_and_modify(args)
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
def modifier_update(modifier, args)
|
75
|
+
criteria, updates, options = criteria_and_keys_from_args(args)
|
76
|
+
if options
|
77
|
+
collection.update(criteria, {modifier => updates}, options)
|
78
|
+
else
|
79
|
+
collection.update(criteria, {modifier => updates})
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def criteria_and_keys_from_args(args)
|
84
|
+
if args[0].is_a?(Hash)
|
85
|
+
criteria = args[0]
|
86
|
+
updates = args[1]
|
87
|
+
options = args[2]
|
88
|
+
else
|
89
|
+
criteria, (updates, options) = args.partition { |a| !a.is_a?(Hash) }
|
90
|
+
criteria = { :id => criteria }
|
91
|
+
end
|
92
|
+
updates = dealias_keys updates
|
93
|
+
|
94
|
+
[criteria_hash(criteria).to_hash, updates, options]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def unset(*args)
|
99
|
+
self.class.unset({:_id => id}, *args)
|
100
|
+
end
|
101
|
+
|
102
|
+
def increment(hash, options=nil)
|
103
|
+
self.class.increment({:_id => id}, hash, options)
|
104
|
+
end
|
105
|
+
|
106
|
+
def decrement(hash, options=nil)
|
107
|
+
self.class.decrement({:_id => id}, hash, options)
|
108
|
+
end
|
109
|
+
|
110
|
+
def set(hash, options=nil)
|
111
|
+
self.class.set({:_id => id}, hash, options)
|
112
|
+
end
|
113
|
+
|
114
|
+
def push(hash, options=nil)
|
115
|
+
self.class.push({:_id => id}, hash, options)
|
116
|
+
end
|
117
|
+
|
118
|
+
def push_all(hash, options=nil)
|
119
|
+
self.class.push_all({:_id => id}, hash, options)
|
120
|
+
end
|
121
|
+
|
122
|
+
def pull(hash, options=nil)
|
123
|
+
self.class.pull({:_id => id}, hash, options)
|
124
|
+
end
|
125
|
+
|
126
|
+
def pull_all(hash, options=nil)
|
127
|
+
self.class.pull_all({:_id => id}, hash, options)
|
128
|
+
end
|
129
|
+
|
130
|
+
def add_to_set(hash, options=nil)
|
131
|
+
self.class.push_uniq({:_id => id}, hash, options)
|
132
|
+
end
|
133
|
+
alias push_uniq add_to_set
|
134
|
+
|
135
|
+
def pop(hash, options=nil)
|
136
|
+
self.class.pop({:_id => id}, hash, options)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MarkMapper
|
3
|
+
module Plugins
|
4
|
+
module Pagination
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def per_page; 25 end
|
9
|
+
|
10
|
+
def paginate(opts={})
|
11
|
+
query.paginate({:per_page => per_page}.merge(opts))
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module MarkMapper
|
2
|
+
module Plugins
|
3
|
+
module PartialUpdates
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
class PartialUpdatesDisabledError < StandardError; end
|
7
|
+
|
8
|
+
included do
|
9
|
+
class_attribute :partial_updates
|
10
|
+
self.partial_updates = false
|
11
|
+
|
12
|
+
self.after_find :_reset_partial_updates_callback
|
13
|
+
self.after_save :_reset_partial_updates_callback
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(*)
|
17
|
+
_reset_partial_updates_callback
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
21
|
+
def fields_for_partial_update
|
22
|
+
raise PartialUpdatesDisabledError if !partial_updates
|
23
|
+
|
24
|
+
Hash.new.tap do |hash|
|
25
|
+
attrs = _dealiased_attributes
|
26
|
+
|
27
|
+
hash[:set_fields] = Array.new.tap do |array|
|
28
|
+
attrs.each do |key, value|
|
29
|
+
if !@_last_saved_attributes.include?(key) ||
|
30
|
+
@_last_saved_attributes[key] != value
|
31
|
+
array << key
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
hash[:unset_fields] = @_last_saved_attributes.keys - attrs.keys
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def _reset_partial_updates_callback
|
43
|
+
_reset_attributes_for_partial_update if partial_updates
|
44
|
+
true
|
45
|
+
end
|
46
|
+
|
47
|
+
def update(options={})
|
48
|
+
if partial_updates
|
49
|
+
updates = fields_for_partial_update
|
50
|
+
|
51
|
+
set_fields = updates[:set_fields]
|
52
|
+
unset_fields = updates[:unset_fields]
|
53
|
+
|
54
|
+
if set_fields.any? || unset_fields.any?
|
55
|
+
set_fields.push("_id") if !set_fields.include?("_id")
|
56
|
+
end
|
57
|
+
|
58
|
+
super(options.merge({
|
59
|
+
:persistence_method => :update,
|
60
|
+
:set_fields => set_fields,
|
61
|
+
:unset_fields => unset_fields
|
62
|
+
}))
|
63
|
+
else
|
64
|
+
super
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def _dealiased_attributes
|
69
|
+
self.class.dealias_keys(attributes)
|
70
|
+
end
|
71
|
+
|
72
|
+
def _reset_attributes_for_partial_update
|
73
|
+
@_last_saved_attributes = _dealiased_attributes._mark_mapper_deep_copy_
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MarkMapper
|
3
|
+
module Plugins
|
4
|
+
module Persistence
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def inherited(subclass)
|
9
|
+
unless subclass.embeddable?
|
10
|
+
subclass.connection(connection)
|
11
|
+
subclass.database = database
|
12
|
+
subclass.set_collection_name(collection_name) unless subclass.explicit_collection_defined?
|
13
|
+
end
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
def connection(marklogic_connection=nil)
|
18
|
+
assert_supported
|
19
|
+
if marklogic_connection.nil? && MarkMapper.connection?
|
20
|
+
@connection ||= MarkMapper.connection
|
21
|
+
else
|
22
|
+
@connection = marklogic_connection
|
23
|
+
end
|
24
|
+
@connection
|
25
|
+
end
|
26
|
+
|
27
|
+
def database_name
|
28
|
+
assert_supported
|
29
|
+
@database.database_name
|
30
|
+
end
|
31
|
+
|
32
|
+
def database=(database)
|
33
|
+
assert_supported
|
34
|
+
@database = database
|
35
|
+
end
|
36
|
+
|
37
|
+
def database
|
38
|
+
assert_supported
|
39
|
+
@database ||= MarkMapper.application.content_databases[0]
|
40
|
+
end
|
41
|
+
|
42
|
+
def set_collection_name(name)
|
43
|
+
assert_supported
|
44
|
+
@collection_name = name
|
45
|
+
end
|
46
|
+
|
47
|
+
def collection_name
|
48
|
+
assert_supported
|
49
|
+
@collection_name ||= begin
|
50
|
+
name = self.to_s.tableize.gsub(/\//, '.')
|
51
|
+
name = self.class.to_s.downcase if name[0] == '#'
|
52
|
+
name
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def collection
|
57
|
+
assert_supported
|
58
|
+
database.collection(collection_name)
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
def assert_supported
|
63
|
+
@embeddable ||= embeddable?
|
64
|
+
if @embeddable
|
65
|
+
raise MarkMapper::NotSupported.new('This is not supported for embeddable documents at this time.')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def collection
|
71
|
+
_root_document.class.collection
|
72
|
+
end
|
73
|
+
|
74
|
+
def database
|
75
|
+
_root_document.class.database
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|