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,95 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MarkMapper
|
3
|
+
module Plugins
|
4
|
+
module Associations
|
5
|
+
class OneProxy < Proxy
|
6
|
+
def build(attrs={}, &block)
|
7
|
+
instantiate_target(:new, attrs, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
def create(attrs={}, &block)
|
11
|
+
instantiate_target(:create, attrs, &block)
|
12
|
+
end
|
13
|
+
|
14
|
+
def create!(attrs={}, &block)
|
15
|
+
instantiate_target(:create!, attrs, &block)
|
16
|
+
end
|
17
|
+
|
18
|
+
def replace(doc)
|
19
|
+
load_target
|
20
|
+
|
21
|
+
if !target.nil? && target != doc
|
22
|
+
if target.persisted?
|
23
|
+
case options[:dependent]
|
24
|
+
when :delete then target.delete
|
25
|
+
when :destroy then target.destroy
|
26
|
+
else
|
27
|
+
nullify_scope(target)
|
28
|
+
target.save
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
unless doc.nil?
|
34
|
+
proxy_owner.save unless proxy_owner.persisted?
|
35
|
+
doc = klass.new(doc) unless doc.is_a?(klass)
|
36
|
+
apply_scope(doc)
|
37
|
+
doc.save unless doc.persisted?
|
38
|
+
end
|
39
|
+
|
40
|
+
loaded
|
41
|
+
@target = doc
|
42
|
+
end
|
43
|
+
|
44
|
+
def destroy
|
45
|
+
target.destroy
|
46
|
+
reset
|
47
|
+
end
|
48
|
+
|
49
|
+
def delete
|
50
|
+
target.delete
|
51
|
+
reset
|
52
|
+
end
|
53
|
+
|
54
|
+
def nullify
|
55
|
+
nullify_scope(target)
|
56
|
+
target.save
|
57
|
+
reset
|
58
|
+
end
|
59
|
+
|
60
|
+
protected
|
61
|
+
def find_target
|
62
|
+
target_class.first(association.query_options.merge(criteria))
|
63
|
+
end
|
64
|
+
|
65
|
+
def instantiate_target(instantiator, attrs={}, &block)
|
66
|
+
@target = target_class.send(instantiator, attrs.update(criteria), &block)
|
67
|
+
loaded
|
68
|
+
@target
|
69
|
+
end
|
70
|
+
|
71
|
+
def target_class
|
72
|
+
@target_class ||= options[:class] || (options[:class_name] || association.name.to_s.camelize).constantize
|
73
|
+
end
|
74
|
+
|
75
|
+
def foreign_key
|
76
|
+
options[:foreign_key] || proxy_owner.class.name.foreign_key
|
77
|
+
end
|
78
|
+
|
79
|
+
def criteria
|
80
|
+
{self.foreign_key => proxy_owner.id}
|
81
|
+
end
|
82
|
+
|
83
|
+
def nullify_scope(doc)
|
84
|
+
criteria.each { |key, value| doc[key] = nil }
|
85
|
+
doc
|
86
|
+
end
|
87
|
+
|
88
|
+
def apply_scope(doc)
|
89
|
+
criteria.each { |key, value| doc[key] = value }
|
90
|
+
doc
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'forwardable'
|
3
|
+
module MarkMapper
|
4
|
+
module Plugins
|
5
|
+
module Associations
|
6
|
+
class Proxy
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
alias :proxy_respond_to? :respond_to?
|
10
|
+
alias :proxy_extend :extend
|
11
|
+
|
12
|
+
instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|^send$|proxy_|^respond_to_missing\?$|^object_id$)/ }
|
13
|
+
|
14
|
+
attr_reader :proxy_owner, :association, :target
|
15
|
+
|
16
|
+
alias :proxy_target :target
|
17
|
+
alias :proxy_association :association
|
18
|
+
|
19
|
+
def_delegators :proxy_association, :klass, :options
|
20
|
+
def_delegator :klass, :collection
|
21
|
+
|
22
|
+
def initialize(owner, association)
|
23
|
+
@proxy_owner, @association, @loaded = owner, association, false
|
24
|
+
Array(association.options[:extend]).each { |ext| proxy_extend(ext) }
|
25
|
+
reset
|
26
|
+
end
|
27
|
+
|
28
|
+
# Active support in rails 3 beta 4 can override to_json after this is loaded,
|
29
|
+
# at least when run in markmapper tests. The implementation was changed in master
|
30
|
+
# some time after this, so not sure whether this is still a problem.
|
31
|
+
#
|
32
|
+
# In rails 2, this isn't a problem however it also solves an issue where
|
33
|
+
# to_json isn't forwarded because it supports to_json itself
|
34
|
+
def to_json(*options)
|
35
|
+
load_target
|
36
|
+
target.to_json(*options)
|
37
|
+
end
|
38
|
+
|
39
|
+
# see comments to to_json
|
40
|
+
def as_json(*options)
|
41
|
+
load_target
|
42
|
+
target.as_json(*options)
|
43
|
+
end
|
44
|
+
|
45
|
+
def inspect
|
46
|
+
load_target
|
47
|
+
target.inspect
|
48
|
+
end
|
49
|
+
|
50
|
+
def loaded?
|
51
|
+
@loaded
|
52
|
+
end
|
53
|
+
|
54
|
+
def loaded
|
55
|
+
@loaded = true
|
56
|
+
end
|
57
|
+
|
58
|
+
def nil?
|
59
|
+
load_target
|
60
|
+
target.nil?
|
61
|
+
end
|
62
|
+
|
63
|
+
def blank?
|
64
|
+
load_target
|
65
|
+
target.blank?
|
66
|
+
end
|
67
|
+
|
68
|
+
def present?
|
69
|
+
load_target
|
70
|
+
target.present?
|
71
|
+
end
|
72
|
+
|
73
|
+
def reload
|
74
|
+
reset
|
75
|
+
load_target
|
76
|
+
self unless target.nil?
|
77
|
+
end
|
78
|
+
|
79
|
+
# :nocov:
|
80
|
+
def replace(v)
|
81
|
+
raise NotImplementedError
|
82
|
+
end
|
83
|
+
# :nocov:
|
84
|
+
|
85
|
+
def reset
|
86
|
+
@loaded = false
|
87
|
+
@target = nil
|
88
|
+
end
|
89
|
+
|
90
|
+
def respond_to?(*args)
|
91
|
+
proxy_respond_to?(*args) || (load_target && target.respond_to?(*args))
|
92
|
+
end
|
93
|
+
|
94
|
+
def send(method, *args, &block)
|
95
|
+
if proxy_respond_to?(method, true)
|
96
|
+
super
|
97
|
+
else
|
98
|
+
load_target
|
99
|
+
target.send(method, *args, &block)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
protected
|
104
|
+
def method_missing(method, *args, &block)
|
105
|
+
if load_target
|
106
|
+
target.send(method, *args, &block)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def load_target
|
111
|
+
unless loaded?
|
112
|
+
if @target.is_a?(Array) && @target.any?
|
113
|
+
@target = find_target + @target.find_all { |record| !record.persisted? }
|
114
|
+
else
|
115
|
+
@target = find_target
|
116
|
+
end
|
117
|
+
loaded
|
118
|
+
end
|
119
|
+
@target
|
120
|
+
rescue MarkMapper::DocumentNotFound
|
121
|
+
reset
|
122
|
+
end
|
123
|
+
|
124
|
+
# :nocov:
|
125
|
+
def find_target
|
126
|
+
raise NotImplementedError
|
127
|
+
end
|
128
|
+
# :nocov:
|
129
|
+
|
130
|
+
def flatten_deeper(array)
|
131
|
+
array.collect do |element|
|
132
|
+
(element.respond_to?(:flatten) && !element.is_a?(Hash)) ? element.flatten : element
|
133
|
+
end.flatten
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MarkMapper
|
3
|
+
module Plugins
|
4
|
+
module Associations
|
5
|
+
class SingleAssociation < Base
|
6
|
+
def setup(model)
|
7
|
+
@model = model
|
8
|
+
model.associations_module.module_eval <<-end_eval
|
9
|
+
def #{name}
|
10
|
+
proxy = get_proxy(associations[#{name.inspect}])
|
11
|
+
proxy.nil? ? nil : proxy
|
12
|
+
end
|
13
|
+
|
14
|
+
def #{name}=(value)
|
15
|
+
association = associations[#{name.inspect}]
|
16
|
+
proxy = get_proxy(association)
|
17
|
+
|
18
|
+
if proxy.nil? || proxy.target != value
|
19
|
+
proxy = build_proxy(association)
|
20
|
+
end
|
21
|
+
|
22
|
+
proxy.replace(value)
|
23
|
+
value
|
24
|
+
end
|
25
|
+
|
26
|
+
def #{name}?
|
27
|
+
get_proxy(associations[#{name.inspect}]).present?
|
28
|
+
end
|
29
|
+
|
30
|
+
def build_#{name}(attrs={}, &block)
|
31
|
+
get_proxy(associations[#{name.inspect}]).build(attrs, &block)
|
32
|
+
end
|
33
|
+
|
34
|
+
def create_#{name}(attrs={}, &block)
|
35
|
+
get_proxy(associations[#{name.inspect}]).create(attrs, &block)
|
36
|
+
end
|
37
|
+
|
38
|
+
def create_#{name}!(attrs={}, &block)
|
39
|
+
get_proxy(associations[#{name.inspect}]).create!(attrs, &block)
|
40
|
+
end
|
41
|
+
end_eval
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MarkMapper
|
3
|
+
module Plugins
|
4
|
+
module Caching
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
def cache_key(*suffixes)
|
8
|
+
cache_key = case
|
9
|
+
when !persisted?
|
10
|
+
"#{self.class.name}/new"
|
11
|
+
when timestamp = self[:updated_at]
|
12
|
+
"#{self.class.name}/#{id}-#{timestamp.to_s(:number)}"
|
13
|
+
else
|
14
|
+
"#{self.class.name}/#{id}"
|
15
|
+
end
|
16
|
+
cache_key += "/#{suffixes.join('/')}" unless suffixes.empty?
|
17
|
+
cache_key
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MarkMapper
|
3
|
+
module Plugins
|
4
|
+
module Callbacks
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
def initialize(*)
|
8
|
+
run_callbacks(:initialize) { super }
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize_from_database(*)
|
12
|
+
run_callbacks(:initialize) do
|
13
|
+
run_callbacks(:find) do
|
14
|
+
super
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def destroy
|
20
|
+
run_callbacks(:destroy) { super }
|
21
|
+
end
|
22
|
+
|
23
|
+
def touch(*)
|
24
|
+
run_callbacks(:touch) { super }
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def create_or_update(*)
|
30
|
+
run_callbacks(:save) { super }
|
31
|
+
end
|
32
|
+
|
33
|
+
def create(*)
|
34
|
+
run_callbacks(:create) { super }
|
35
|
+
end
|
36
|
+
|
37
|
+
def update(*)
|
38
|
+
run_callbacks(:update) { super }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MarkMapper
|
3
|
+
module Plugins
|
4
|
+
module Clone
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
def initialize_copy(other)
|
8
|
+
@_new = true
|
9
|
+
@_destroyed = false
|
10
|
+
remove_instance_variable :@_id if instance_variable_defined?(:@_id)
|
11
|
+
init_ivars
|
12
|
+
|
13
|
+
associations.each do |name, association|
|
14
|
+
instance_variable_set(association.ivar, nil)
|
15
|
+
end
|
16
|
+
self.attributes = other.attributes.clone.except(:_id).inject({}) do |hash, entry|
|
17
|
+
key, value = entry
|
18
|
+
hash[key] = value.duplicable? ? value.clone : value
|
19
|
+
hash
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module MarkMapper
|
2
|
+
module Plugins
|
3
|
+
# Counter Caching for MarkMapper::Document
|
4
|
+
#
|
5
|
+
# Examples:
|
6
|
+
#
|
7
|
+
# class Post
|
8
|
+
# belongs_to :user
|
9
|
+
# counter_cache :user
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# or:
|
13
|
+
#
|
14
|
+
# class Post
|
15
|
+
# belongs_to :user
|
16
|
+
# counter_cache :user, :custom_posts_count
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# Field names follow rails conventions, so counter_cache :user will increment the Integer field `posts_count' on User
|
20
|
+
#
|
21
|
+
# Alternatively, you can also use the more common ActiveRecord syntax:
|
22
|
+
#
|
23
|
+
# class Post
|
24
|
+
# belongs_to :user, :counter_cache => true
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# Or with an alternative field name:
|
28
|
+
#
|
29
|
+
# class Post
|
30
|
+
# belongs_to :user, :counter_cache => :custom_posts_count
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
module CounterCache
|
34
|
+
class InvalidCounterCacheError < StandardError; end
|
35
|
+
|
36
|
+
extend ActiveSupport::Concern
|
37
|
+
|
38
|
+
module ClassMethods
|
39
|
+
def counter_cache(association_name, options = {})
|
40
|
+
options.symbolize_keys!
|
41
|
+
|
42
|
+
field = options[:field] ?
|
43
|
+
options[:field] :
|
44
|
+
"#{self.collection_name.gsub(/.*\./, '')}_count"
|
45
|
+
|
46
|
+
association = associations[association_name]
|
47
|
+
|
48
|
+
if !association
|
49
|
+
raise InvalidCounterCacheError, "You must define an association with name `#{association_name}' on model #{self}"
|
50
|
+
end
|
51
|
+
|
52
|
+
# make a define-time check to make sure the counter cache field is defined.
|
53
|
+
# note: this can only be done in non-polymorphic classes
|
54
|
+
# (since we may not know the class on the other side of the association)
|
55
|
+
if !association.polymorphic?
|
56
|
+
association_class = association.klass
|
57
|
+
key_names = association_class.keys.keys
|
58
|
+
|
59
|
+
if !key_names.include?(field.to_s)
|
60
|
+
_raise_when_missing_counter_cache_key(association_class, field)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
after_create do
|
65
|
+
if obj = self.send(association_name)
|
66
|
+
if !obj.respond_to?(field)
|
67
|
+
self.class._raise_when_missing_counter_cache_key(obj.class, field)
|
68
|
+
end
|
69
|
+
|
70
|
+
obj.increment(field => 1)
|
71
|
+
obj.write_attribute(field, obj.read_attribute(field) + 1)
|
72
|
+
end
|
73
|
+
|
74
|
+
true
|
75
|
+
end
|
76
|
+
|
77
|
+
after_destroy do
|
78
|
+
if obj = self.send(association_name)
|
79
|
+
if !obj.respond_to?(field)
|
80
|
+
self.class._raise_when_missing_counter_cache_key(obj.class, field)
|
81
|
+
end
|
82
|
+
|
83
|
+
obj.decrement(field => 1)
|
84
|
+
obj.write_attribute(field, obj.read_attribute(field) - 1)
|
85
|
+
end
|
86
|
+
|
87
|
+
true
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def _raise_when_missing_counter_cache_key(klass, field)
|
92
|
+
raise InvalidCounterCacheError, "Missing `key #{field.to_sym.inspect}, Integer, :default => 0' on model #{klass}"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|