lookout-mongo_mapper 0.11.3
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.
- data/LICENSE +20 -0
- data/README.rdoc +33 -0
- data/UPGRADES +26 -0
- data/bin/mmconsole +59 -0
- data/examples/attr_accessible.rb +22 -0
- data/examples/attr_protected.rb +22 -0
- data/examples/cache_key.rb +24 -0
- data/examples/custom_types.rb +24 -0
- data/examples/identity_map.rb +33 -0
- data/examples/identity_map/automatic.rb +2 -0
- data/examples/keys.rb +40 -0
- data/examples/modifiers/set.rb +25 -0
- data/examples/plugins.rb +38 -0
- data/examples/querying.rb +35 -0
- data/examples/safe.rb +43 -0
- data/examples/scopes.rb +52 -0
- data/examples/validating/embedded_docs.rb +29 -0
- data/lib/mongo_mapper.rb +94 -0
- data/lib/mongo_mapper/connection.rb +96 -0
- data/lib/mongo_mapper/document.rb +42 -0
- data/lib/mongo_mapper/embedded_document.rb +32 -0
- data/lib/mongo_mapper/exceptions.rb +30 -0
- data/lib/mongo_mapper/extensions/array.rb +19 -0
- data/lib/mongo_mapper/extensions/binary.rb +22 -0
- data/lib/mongo_mapper/extensions/boolean.rb +44 -0
- data/lib/mongo_mapper/extensions/date.rb +25 -0
- data/lib/mongo_mapper/extensions/float.rb +14 -0
- data/lib/mongo_mapper/extensions/hash.rb +14 -0
- data/lib/mongo_mapper/extensions/integer.rb +19 -0
- data/lib/mongo_mapper/extensions/kernel.rb +9 -0
- data/lib/mongo_mapper/extensions/nil_class.rb +18 -0
- data/lib/mongo_mapper/extensions/object.rb +26 -0
- data/lib/mongo_mapper/extensions/object_id.rb +32 -0
- data/lib/mongo_mapper/extensions/set.rb +20 -0
- data/lib/mongo_mapper/extensions/string.rb +18 -0
- data/lib/mongo_mapper/extensions/time.rb +28 -0
- data/lib/mongo_mapper/locale/en.yml +5 -0
- data/lib/mongo_mapper/middleware/identity_map.rb +16 -0
- data/lib/mongo_mapper/plugins.rb +22 -0
- data/lib/mongo_mapper/plugins/accessible.rb +52 -0
- data/lib/mongo_mapper/plugins/active_model.rb +18 -0
- data/lib/mongo_mapper/plugins/associations.rb +90 -0
- data/lib/mongo_mapper/plugins/associations/base.rb +92 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_association.rb +54 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +34 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +52 -0
- data/lib/mongo_mapper/plugins/associations/collection.rb +27 -0
- data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +44 -0
- data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +133 -0
- data/lib/mongo_mapper/plugins/associations/many_association.rb +63 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +118 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +32 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +24 -0
- data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +14 -0
- data/lib/mongo_mapper/plugins/associations/one_as_proxy.rb +22 -0
- data/lib/mongo_mapper/plugins/associations/one_association.rb +48 -0
- data/lib/mongo_mapper/plugins/associations/one_embedded_polymorphic_proxy.rb +30 -0
- data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +44 -0
- data/lib/mongo_mapper/plugins/associations/one_proxy.rb +95 -0
- data/lib/mongo_mapper/plugins/associations/proxy.rb +134 -0
- data/lib/mongo_mapper/plugins/associations/single_association.rb +46 -0
- data/lib/mongo_mapper/plugins/caching.rb +21 -0
- data/lib/mongo_mapper/plugins/callbacks.rb +29 -0
- data/lib/mongo_mapper/plugins/clone.rb +22 -0
- data/lib/mongo_mapper/plugins/dirty.rb +60 -0
- data/lib/mongo_mapper/plugins/document.rb +41 -0
- data/lib/mongo_mapper/plugins/dynamic_querying.rb +45 -0
- data/lib/mongo_mapper/plugins/dynamic_querying/dynamic_finder.rb +44 -0
- data/lib/mongo_mapper/plugins/embedded_callbacks.rb +56 -0
- data/lib/mongo_mapper/plugins/embedded_document.rb +53 -0
- data/lib/mongo_mapper/plugins/equality.rb +23 -0
- data/lib/mongo_mapper/plugins/identity_map.rb +128 -0
- data/lib/mongo_mapper/plugins/indexes.rb +13 -0
- data/lib/mongo_mapper/plugins/inspect.rb +16 -0
- data/lib/mongo_mapper/plugins/keys.rb +313 -0
- data/lib/mongo_mapper/plugins/keys/key.rb +61 -0
- data/lib/mongo_mapper/plugins/logger.rb +18 -0
- data/lib/mongo_mapper/plugins/modifiers.rb +134 -0
- data/lib/mongo_mapper/plugins/pagination.rb +16 -0
- data/lib/mongo_mapper/plugins/persistence.rb +69 -0
- data/lib/mongo_mapper/plugins/protected.rb +45 -0
- data/lib/mongo_mapper/plugins/querying.rb +165 -0
- data/lib/mongo_mapper/plugins/querying/decorator.rb +36 -0
- data/lib/mongo_mapper/plugins/rails.rb +58 -0
- data/lib/mongo_mapper/plugins/rails/active_record_association_adapter.rb +33 -0
- data/lib/mongo_mapper/plugins/safe.rb +28 -0
- data/lib/mongo_mapper/plugins/sci.rb +36 -0
- data/lib/mongo_mapper/plugins/scopes.rb +27 -0
- data/lib/mongo_mapper/plugins/serialization.rb +109 -0
- data/lib/mongo_mapper/plugins/timestamps.rb +22 -0
- data/lib/mongo_mapper/plugins/touch.rb +18 -0
- data/lib/mongo_mapper/plugins/userstamps.rb +18 -0
- data/lib/mongo_mapper/plugins/validations.rb +86 -0
- data/lib/mongo_mapper/railtie.rb +48 -0
- data/lib/mongo_mapper/railtie/database.rake +65 -0
- data/lib/mongo_mapper/translation.rb +10 -0
- data/lib/mongo_mapper/version.rb +4 -0
- data/lib/rails/generators/mongo_mapper/config/config_generator.rb +24 -0
- data/lib/rails/generators/mongo_mapper/config/templates/mongo.yml +18 -0
- data/lib/rails/generators/mongo_mapper/model/model_generator.rb +23 -0
- data/lib/rails/generators/mongo_mapper/model/templates/model.rb +13 -0
- data/test/_NOTE_ON_TESTING +1 -0
- data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +64 -0
- data/test/functional/associations/test_belongs_to_proxy.rb +238 -0
- data/test/functional/associations/test_in_array_proxy.rb +349 -0
- data/test/functional/associations/test_many_documents_as_proxy.rb +231 -0
- data/test/functional/associations/test_many_documents_proxy.rb +866 -0
- data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +239 -0
- data/test/functional/associations/test_many_embedded_proxy.rb +289 -0
- data/test/functional/associations/test_many_polymorphic_proxy.rb +303 -0
- data/test/functional/associations/test_one_as_proxy.rb +491 -0
- data/test/functional/associations/test_one_embedded_polymorphic_proxy.rb +208 -0
- data/test/functional/associations/test_one_embedded_proxy.rb +100 -0
- data/test/functional/associations/test_one_proxy.rb +383 -0
- data/test/functional/test_accessible.rb +198 -0
- data/test/functional/test_associations.rb +46 -0
- data/test/functional/test_binary.rb +27 -0
- data/test/functional/test_caching.rb +77 -0
- data/test/functional/test_callbacks.rb +232 -0
- data/test/functional/test_dirty.rb +301 -0
- data/test/functional/test_document.rb +282 -0
- data/test/functional/test_dynamic_querying.rb +75 -0
- data/test/functional/test_embedded_document.rb +288 -0
- data/test/functional/test_equality.rb +20 -0
- data/test/functional/test_identity_map.rb +513 -0
- data/test/functional/test_indexes.rb +50 -0
- data/test/functional/test_logger.rb +20 -0
- data/test/functional/test_modifiers.rb +537 -0
- data/test/functional/test_pagination.rb +91 -0
- data/test/functional/test_protected.rb +201 -0
- data/test/functional/test_querying.rb +935 -0
- data/test/functional/test_safe.rb +76 -0
- data/test/functional/test_sci.rb +240 -0
- data/test/functional/test_scopes.rb +171 -0
- data/test/functional/test_timestamps.rb +62 -0
- data/test/functional/test_touch.rb +125 -0
- data/test/functional/test_userstamps.rb +44 -0
- data/test/functional/test_validations.rb +414 -0
- data/test/models.rb +261 -0
- data/test/support/railtie.rb +4 -0
- data/test/support/railtie/autoloaded.rb +2 -0
- data/test/support/railtie/not_autoloaded.rb +3 -0
- data/test/support/railtie/parent.rb +3 -0
- data/test/test_active_model_lint.rb +18 -0
- data/test/test_helper.rb +93 -0
- data/test/unit/associations/test_base.rb +146 -0
- data/test/unit/associations/test_belongs_to_association.rb +29 -0
- data/test/unit/associations/test_many_association.rb +63 -0
- data/test/unit/associations/test_one_association.rb +47 -0
- data/test/unit/associations/test_proxy.rb +100 -0
- data/test/unit/serializers/test_json_serializer.rb +216 -0
- data/test/unit/serializers/test_xml_serializer.rb +196 -0
- data/test/unit/test_clone.rb +69 -0
- data/test/unit/test_document.rb +249 -0
- data/test/unit/test_dynamic_finder.rb +125 -0
- data/test/unit/test_embedded_document.rb +682 -0
- data/test/unit/test_equality.rb +38 -0
- data/test/unit/test_exceptions.rb +12 -0
- data/test/unit/test_extensions.rb +380 -0
- data/test/unit/test_identity_map_middleware.rb +34 -0
- data/test/unit/test_inspect.rb +47 -0
- data/test/unit/test_key.rb +205 -0
- data/test/unit/test_keys.rb +65 -0
- data/test/unit/test_mongo_mapper.rb +143 -0
- data/test/unit/test_pagination.rb +11 -0
- data/test/unit/test_plugins.rb +89 -0
- data/test/unit/test_rails.rb +183 -0
- data/test/unit/test_rails_compatibility.rb +38 -0
- data/test/unit/test_rails_reflect_on_association.rb +118 -0
- data/test/unit/test_railtie.rb +66 -0
- data/test/unit/test_serialization.rb +166 -0
- data/test/unit/test_time_zones.rb +44 -0
- data/test/unit/test_translation.rb +27 -0
- data/test/unit/test_validations.rb +562 -0
- metadata +285 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
require 'forwardable'
|
|
3
|
+
module MongoMapper
|
|
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 mongomapper 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
|
+
def replace(v)
|
|
80
|
+
raise NotImplementedError
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def reset
|
|
84
|
+
@loaded = false
|
|
85
|
+
@target = nil
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def respond_to?(*args)
|
|
89
|
+
proxy_respond_to?(*args) || (load_target && target.respond_to?(*args))
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def send(method, *args)
|
|
93
|
+
if proxy_respond_to?(method)
|
|
94
|
+
super
|
|
95
|
+
else
|
|
96
|
+
load_target
|
|
97
|
+
target.send(method, *args)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
protected
|
|
102
|
+
def method_missing(method, *args, &block)
|
|
103
|
+
if load_target
|
|
104
|
+
target.send(method, *args, &block)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def load_target
|
|
109
|
+
unless loaded?
|
|
110
|
+
if @target.is_a?(Array) && @target.any?
|
|
111
|
+
@target = find_target + @target.find_all { |record| !record.persisted? }
|
|
112
|
+
else
|
|
113
|
+
@target = find_target
|
|
114
|
+
end
|
|
115
|
+
loaded
|
|
116
|
+
end
|
|
117
|
+
@target
|
|
118
|
+
rescue MongoMapper::DocumentNotFound
|
|
119
|
+
reset
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def find_target
|
|
123
|
+
raise NotImplementedError
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def flatten_deeper(array)
|
|
127
|
+
array.collect do |element|
|
|
128
|
+
(element.respond_to?(:flatten) && !element.is_a?(Hash)) ? element.flatten : element
|
|
129
|
+
end.flatten
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
module MongoMapper
|
|
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={})
|
|
31
|
+
get_proxy(associations[#{name.inspect}]).build(attrs)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def create_#{name}(attrs={})
|
|
35
|
+
get_proxy(associations[#{name.inspect}]).create(attrs)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def create_#{name}!(attrs={})
|
|
39
|
+
get_proxy(associations[#{name.inspect}]).create!(attrs)
|
|
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 MongoMapper
|
|
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,29 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
module MongoMapper
|
|
3
|
+
module Plugins
|
|
4
|
+
module Callbacks
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
def destroy
|
|
8
|
+
run_callbacks(:destroy) { super }
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def touch(*)
|
|
12
|
+
run_callbacks(:touch) { super }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
def create_or_update(*)
|
|
17
|
+
run_callbacks(:save) { super }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def create(*)
|
|
21
|
+
run_callbacks(:create) { super }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def update(*)
|
|
25
|
+
run_callbacks(:update) { super }
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
module MongoMapper
|
|
3
|
+
module Plugins
|
|
4
|
+
module Clone
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
def initialize_copy(other)
|
|
8
|
+
@_new = true
|
|
9
|
+
@_destroyed = false
|
|
10
|
+
@_id = nil
|
|
11
|
+
associations.each do |name, association|
|
|
12
|
+
instance_variable_set(association.ivar, nil)
|
|
13
|
+
end
|
|
14
|
+
self.attributes = other.attributes.clone.except(:_id).inject({}) do |hash, entry|
|
|
15
|
+
key, value = entry
|
|
16
|
+
hash[key] = value.duplicable? ? value.clone : value
|
|
17
|
+
hash
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
module MongoMapper
|
|
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
|
+
super.tap { changed_attributes.delete('_id') }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def initialize_from_database(*)
|
|
15
|
+
super.tap { changed_attributes.clear }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def save(*)
|
|
19
|
+
clear_changes { super }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def reload(*)
|
|
23
|
+
super.tap { clear_changes }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
protected
|
|
27
|
+
|
|
28
|
+
def attribute_method?(attr)
|
|
29
|
+
# This overrides ::ActiveSupport::Dirty#attribute_method? to allow attributes to be any key
|
|
30
|
+
# in the attributes hash ( default ) or any key defined on the model that may not yet have
|
|
31
|
+
# had a value stored in the attributes collection.
|
|
32
|
+
super || key_names.include?(attr)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def clear_changes
|
|
36
|
+
previous = changes
|
|
37
|
+
(block_given? ? yield : true).tap do |result|
|
|
38
|
+
unless result == false #failed validation; nil is OK.
|
|
39
|
+
@previously_changed = previous
|
|
40
|
+
changed_attributes.clear
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def write_key(key, value)
|
|
48
|
+
key = key.to_s
|
|
49
|
+
attribute_will_change!(key) unless attribute_changed?(key)
|
|
50
|
+
super(key, value).tap do
|
|
51
|
+
changed_attributes.delete(key) unless attribute_value_changed?(key)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def attribute_value_changed?(key_name)
|
|
56
|
+
attribute_was(key_name) != read_key(key_name)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
module MongoMapper
|
|
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
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def destroyed?
|
|
18
|
+
@_destroyed == true
|
|
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| instance_variable_set(ivar, nil) }
|
|
27
|
+
load_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,45 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
require 'mongo_mapper/plugins/dynamic_querying/dynamic_finder'
|
|
3
|
+
|
|
4
|
+
module MongoMapper
|
|
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 MongoMapper
|
|
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
|