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,61 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MarkMapper
|
3
|
+
module Plugins
|
4
|
+
module Dirty
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
include ::ActiveModel::Dirty
|
8
|
+
|
9
|
+
def initialize(*)
|
10
|
+
# never register initial id assignment as a change
|
11
|
+
# Chaining super into tap breaks implicit block passing in Ruby 1.8
|
12
|
+
doc = super
|
13
|
+
doc.tap { changed_attributes.delete('_id') }
|
14
|
+
end
|
15
|
+
|
16
|
+
def save(*)
|
17
|
+
clear_changes { super }
|
18
|
+
end
|
19
|
+
|
20
|
+
def reload(*)
|
21
|
+
doc = super
|
22
|
+
doc.tap { clear_changes }
|
23
|
+
end
|
24
|
+
|
25
|
+
def clear_changes
|
26
|
+
previous = changes
|
27
|
+
(block_given? ? yield : true).tap do |result|
|
28
|
+
unless result == false #failed validation; nil is OK.
|
29
|
+
@previously_changed = previous
|
30
|
+
changed_attributes.clear
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
protected
|
36
|
+
|
37
|
+
# We don't call super here to avoid invoking #attributes, which builds a whole new hash per call.
|
38
|
+
def attribute_method?(attr_name)
|
39
|
+
keys.key?(attr_name) || !embedded_associations.detect {|a| a.name == attr_name }.nil?
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def write_key(key, value)
|
45
|
+
key = unalias_key(key)
|
46
|
+
if !keys.key?(key)
|
47
|
+
super
|
48
|
+
else
|
49
|
+
attribute_will_change!(key) unless attribute_changed?(key)
|
50
|
+
super.tap do
|
51
|
+
changed_attributes.delete(key) unless attribute_value_changed?(key)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def attribute_value_changed?(key_name)
|
57
|
+
changed_attributes[key_name] != read_key(key_name)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MarkMapper
|
3
|
+
module Plugins
|
4
|
+
module Document
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def embeddable?
|
9
|
+
false
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def new?
|
14
|
+
!!(@_new ||= false)
|
15
|
+
end
|
16
|
+
|
17
|
+
def destroyed?
|
18
|
+
!!(@_destroyed ||= false)
|
19
|
+
end
|
20
|
+
|
21
|
+
def reload
|
22
|
+
if doc = collection.find_one(:_id => id)
|
23
|
+
self.class.associations.each_value do |association|
|
24
|
+
get_proxy(association).reset
|
25
|
+
end
|
26
|
+
instance_variables.each { |ivar| remove_instance_variable(ivar) }
|
27
|
+
initialize_from_database(doc)
|
28
|
+
self
|
29
|
+
else
|
30
|
+
raise DocumentNotFound, "Document match #{_id.inspect} does not exist in #{collection.name} collection"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Used by embedded docs to find root easily without if/respond_to? stuff.
|
35
|
+
# Documents are always root documents.
|
36
|
+
def _root_document
|
37
|
+
self
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module MarkMapper
|
4
|
+
module Plugins
|
5
|
+
module Dumpable
|
6
|
+
DUMP_BLACKLIST = Set.new([:@errors])
|
7
|
+
|
8
|
+
def marshal_dump
|
9
|
+
instance_variables.map(&:to_sym).inject({}) do |h, var|
|
10
|
+
h[var] = instance_variable_get(var) unless DUMP_BLACKLIST.include?(var) or var.to_s.start_with?("@__")
|
11
|
+
h
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def marshal_load(data)
|
16
|
+
data.each do |k, v|
|
17
|
+
instance_variable_set(k, v)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'mark_mapper/plugins/dynamic_querying/dynamic_finder'
|
3
|
+
|
4
|
+
module MarkMapper
|
5
|
+
module Plugins
|
6
|
+
module DynamicQuerying
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def dynamic_find(finder, args)
|
11
|
+
attributes = {}
|
12
|
+
|
13
|
+
finder.attributes.each_with_index do |attr, index|
|
14
|
+
attributes[attr] = args[index]
|
15
|
+
end
|
16
|
+
|
17
|
+
options = args.extract_options!.merge(attributes)
|
18
|
+
|
19
|
+
if result = send(finder.finder, options)
|
20
|
+
result
|
21
|
+
else
|
22
|
+
if finder.raise?
|
23
|
+
raise DocumentNotFound, "Couldn't find Document with #{attributes.inspect} in collection named #{collection.name}"
|
24
|
+
end
|
25
|
+
|
26
|
+
if finder.instantiator
|
27
|
+
self.send(finder.instantiator, attributes)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
protected
|
33
|
+
def method_missing(method, *args, &block)
|
34
|
+
finder = DynamicFinder.new(method)
|
35
|
+
|
36
|
+
if finder.found?
|
37
|
+
dynamic_find(finder, args)
|
38
|
+
else
|
39
|
+
super
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MarkMapper
|
3
|
+
module Plugins
|
4
|
+
module DynamicQuerying
|
5
|
+
class DynamicFinder
|
6
|
+
attr_reader :method, :attributes, :finder, :bang, :instantiator
|
7
|
+
|
8
|
+
def initialize(method)
|
9
|
+
@method = method
|
10
|
+
@finder = :first
|
11
|
+
@bang = false
|
12
|
+
match
|
13
|
+
end
|
14
|
+
|
15
|
+
def found?
|
16
|
+
@finder.present?
|
17
|
+
end
|
18
|
+
|
19
|
+
def raise?
|
20
|
+
bang == true
|
21
|
+
end
|
22
|
+
|
23
|
+
protected
|
24
|
+
def match
|
25
|
+
case method.to_s
|
26
|
+
when /^find_(all_by|by)_([_a-zA-Z]\w*)$/
|
27
|
+
@finder = :all if $1 == 'all_by'
|
28
|
+
names = $2
|
29
|
+
when /^find_by_([_a-zA-Z]\w*)\!$/
|
30
|
+
@bang = true
|
31
|
+
names = $1
|
32
|
+
when /^find_or_(initialize|create)_by_([_a-zA-Z]\w*)$/
|
33
|
+
@instantiator = $1 == 'initialize' ? :new : :create
|
34
|
+
names = $2
|
35
|
+
else
|
36
|
+
@finder = nil
|
37
|
+
end
|
38
|
+
|
39
|
+
@attributes = names && names.split('_and_')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MarkMapper
|
3
|
+
module Plugins
|
4
|
+
module EmbeddedCallbacks
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
extend ::ActiveModel::Callbacks
|
9
|
+
|
10
|
+
define_model_callbacks :save, :create, :update, :destroy, :only => [:before, :after]
|
11
|
+
define_model_callbacks :initialize, :find, :touch, :only => [:after]
|
12
|
+
|
13
|
+
proxy_callbacks(
|
14
|
+
:before => [:save, :create, :update, :destroy],
|
15
|
+
:after => [:save, :create, :update, :destroy, :touch]
|
16
|
+
)
|
17
|
+
|
18
|
+
@embedded_callbacks_status = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
module ClassMethods
|
22
|
+
def define_callbacks(*args)
|
23
|
+
embedded_callbacks_on if @embedded_callbacks_status.nil?
|
24
|
+
super
|
25
|
+
end
|
26
|
+
|
27
|
+
def embedded_callbacks_on
|
28
|
+
@embedded_callbacks_status = true
|
29
|
+
end
|
30
|
+
|
31
|
+
def embedded_callbacks_off
|
32
|
+
@embedded_callbacks_status = false
|
33
|
+
end
|
34
|
+
|
35
|
+
def embedded_callbacks_on?
|
36
|
+
!!@embedded_callbacks_status
|
37
|
+
end
|
38
|
+
|
39
|
+
def embedded_callbacks_off?
|
40
|
+
!@embedded_callbacks_status
|
41
|
+
end
|
42
|
+
|
43
|
+
def proxy_callbacks(definition)
|
44
|
+
definition.each do |prefix, suffixes|
|
45
|
+
suffixes.each do |suffix|
|
46
|
+
callback = "%s_%s" % [prefix, suffix]
|
47
|
+
class_eval <<-CALLBACK, __FILE__, __LINE__ + 1
|
48
|
+
class << self
|
49
|
+
alias_method :__original_#{callback}, :#{callback}
|
50
|
+
|
51
|
+
def #{callback}(*args, &block)
|
52
|
+
embedded_callbacks_on if @embedded_callbacks_status.nil?
|
53
|
+
__original_#{callback}(*args, &block)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
CALLBACK
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def run_callbacks(callback, *args, &block)
|
63
|
+
if self.class.embedded_callbacks_on? and embedded_associations.length > 0
|
64
|
+
embedded_docs = embedded_associations.map do |association|
|
65
|
+
Array(get_proxy(association).send(:load_target))
|
66
|
+
end.flatten(1)
|
67
|
+
|
68
|
+
block = embedded_docs.inject(block) do |chain, doc|
|
69
|
+
if doc.class.respond_to?("_#{callback}_callbacks")
|
70
|
+
lambda { doc.run_callbacks(callback, *args, &chain) }
|
71
|
+
else
|
72
|
+
chain
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
super callback, *args, &block
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MarkMapper
|
3
|
+
module Plugins
|
4
|
+
module EmbeddedDocument
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
attr_accessor :_parent_document
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
def embeddable?
|
13
|
+
true
|
14
|
+
end
|
15
|
+
|
16
|
+
def embedded_in(owner_name)
|
17
|
+
alias_method owner_name, :_parent_document
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def new?
|
22
|
+
_root_document.try(:new?) || @_new
|
23
|
+
end
|
24
|
+
|
25
|
+
def destroyed?
|
26
|
+
!!_root_document.try(:destroyed?)
|
27
|
+
end
|
28
|
+
|
29
|
+
def save(options={})
|
30
|
+
_root_document.try(:save, options).tap do |result|
|
31
|
+
persist(options) if result
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def save!(options={})
|
36
|
+
valid? || raise(DocumentNotValid.new(self))
|
37
|
+
_root_document.try(:save!, options).tap do |result|
|
38
|
+
persist(options) if result
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def persist(options={})
|
43
|
+
@_new = false
|
44
|
+
clear_changes if respond_to?(:clear_changes)
|
45
|
+
save_to_collection(options)
|
46
|
+
end
|
47
|
+
|
48
|
+
def _root_document
|
49
|
+
@_root_document ||= _parent_document.try(:_root_document)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MarkMapper
|
3
|
+
module Plugins
|
4
|
+
module Equality
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def ===(other)
|
9
|
+
other.is_a?(self)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def eql?(other)
|
14
|
+
other.is_a?(self.class) && _id == other._id
|
15
|
+
end
|
16
|
+
alias :== :eql?
|
17
|
+
|
18
|
+
def hash
|
19
|
+
_id.hash
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'set'
|
3
|
+
|
4
|
+
module MarkMapper
|
5
|
+
module Plugins
|
6
|
+
module IdentityMap
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
def self.enabled=(flag)
|
10
|
+
Thread.current[:mark_mapper_identity_map_enabled] = flag
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.enabled
|
14
|
+
Thread.current[:mark_mapper_identity_map_enabled]
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.enabled?
|
18
|
+
enabled == true
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.repository
|
22
|
+
Thread.current[:mark_mapper_identity_map] ||= {}
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.clear
|
26
|
+
repository.clear
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.include?(document)
|
30
|
+
repository.key?(IdentityMap.key(document.class, document._id))
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.key(model, id)
|
34
|
+
"#{model.single_collection_root.name}:#{id}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.use
|
38
|
+
old, self.enabled = enabled, true
|
39
|
+
|
40
|
+
yield if block_given?
|
41
|
+
ensure
|
42
|
+
self.enabled = old
|
43
|
+
clear
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.without
|
47
|
+
old, self.enabled = enabled, false
|
48
|
+
|
49
|
+
yield if block_given?
|
50
|
+
ensure
|
51
|
+
self.enabled = old
|
52
|
+
end
|
53
|
+
|
54
|
+
module ClassMethods
|
55
|
+
# Private - Looks for a document in the identity map
|
56
|
+
def get_from_identity_map(id)
|
57
|
+
IdentityMap.repository[IdentityMap.key(self, id)]
|
58
|
+
end
|
59
|
+
|
60
|
+
def query(opts={})
|
61
|
+
super.tap do |query|
|
62
|
+
query.identity_map = self if Thread.current[:mark_mapper_identity_map_enabled]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def remove_documents_from_map(*documents)
|
67
|
+
documents.flatten.compact.each do |document|
|
68
|
+
document.remove_from_identity_map
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def load(attrs, with_cast = false)
|
73
|
+
return super unless Thread.current[:mark_mapper_identity_map_enabled]
|
74
|
+
return nil unless attrs
|
75
|
+
document = get_from_identity_map(attrs['_id'])
|
76
|
+
|
77
|
+
if !document
|
78
|
+
document = super
|
79
|
+
document.add_to_identity_map
|
80
|
+
end
|
81
|
+
|
82
|
+
document
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def save(*args)
|
87
|
+
super.tap { |result| add_to_identity_map if result }
|
88
|
+
end
|
89
|
+
|
90
|
+
def delete
|
91
|
+
super.tap { remove_from_identity_map }
|
92
|
+
end
|
93
|
+
|
94
|
+
def add_to_identity_map
|
95
|
+
if IdentityMap.enabled?
|
96
|
+
key = IdentityMap.key(self.class, _id)
|
97
|
+
IdentityMap.repository[key] = self
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def remove_from_identity_map
|
102
|
+
if IdentityMap.enabled?
|
103
|
+
key = IdentityMap.key(self.class, _id)
|
104
|
+
IdentityMap.repository.delete(key)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
module MarkMapperMethods
|
112
|
+
module ClassMethods
|
113
|
+
extend ActiveSupport::Concern
|
114
|
+
|
115
|
+
included do
|
116
|
+
attr_accessor :identity_map
|
117
|
+
|
118
|
+
alias_method :first, :find_one
|
119
|
+
alias_method :each, :find_each
|
120
|
+
end
|
121
|
+
|
122
|
+
def find_one(opts={})
|
123
|
+
query = clone.amend(opts)
|
124
|
+
|
125
|
+
if identity_map && query.simple? && (document = identity_map.get_from_identity_map(query[:_id]))
|
126
|
+
document
|
127
|
+
else
|
128
|
+
super.tap do |doc|
|
129
|
+
doc.remove_from_identity_map if doc && query.fields?
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def find_each(opts={})
|
135
|
+
query = clone.amend(opts)
|
136
|
+
super(opts) do |doc|
|
137
|
+
doc.remove_from_identity_map if doc && query.fields?
|
138
|
+
yield doc if block_given?
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
::MarkMapper::Plugins::Querying::DecoratedMarkMapperQuery.send :include, ::MarkMapperMethods::ClassMethods
|