mongo_doc_rails2 0.6.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.
- data/.document +5 -0
- data/.gitignore +8 -0
- data/HISTORY.md +11 -0
- data/LICENSE +20 -0
- data/README.textile +185 -0
- data/Rakefile +188 -0
- data/TODO +40 -0
- data/VERSION +1 -0
- data/data/.gitignore +2 -0
- data/examples/simple_document.rb +46 -0
- data/examples/simple_object.rb +34 -0
- data/features/collections.feature +9 -0
- data/features/embed_hash.feature +16 -0
- data/features/finders.feature +76 -0
- data/features/indexes.feature +28 -0
- data/features/mongodb.yml +7 -0
- data/features/mongodoc_base.feature +128 -0
- data/features/new_record.feature +36 -0
- data/features/partial_updates.feature +95 -0
- data/features/removing_documents.feature +68 -0
- data/features/saving_an_object.feature +15 -0
- data/features/scopes.feature +66 -0
- data/features/step_definitions/collection_steps.rb +17 -0
- data/features/step_definitions/document_steps.rb +149 -0
- data/features/step_definitions/documents.rb +40 -0
- data/features/step_definitions/embed_hash_steps.rb +6 -0
- data/features/step_definitions/finder_steps.rb +15 -0
- data/features/step_definitions/index_steps.rb +10 -0
- data/features/step_definitions/json_steps.rb +9 -0
- data/features/step_definitions/object_steps.rb +50 -0
- data/features/step_definitions/objects.rb +24 -0
- data/features/step_definitions/partial_update_steps.rb +31 -0
- data/features/step_definitions/query_steps.rb +66 -0
- data/features/step_definitions/removing_documents_steps.rb +14 -0
- data/features/step_definitions/scope_steps.rb +18 -0
- data/features/step_definitions/string_casting_steps.rb +29 -0
- data/features/step_definitions/util_steps.rb +7 -0
- data/features/string_casting.feature +10 -0
- data/features/support/support.rb +10 -0
- data/features/using_criteria.feature +142 -0
- data/lib/mongo_doc.rb +12 -0
- data/lib/mongo_doc/associations.rb +109 -0
- data/lib/mongo_doc/associations/collection_proxy.rb +121 -0
- data/lib/mongo_doc/associations/document_proxy.rb +65 -0
- data/lib/mongo_doc/associations/hash_proxy.rb +102 -0
- data/lib/mongo_doc/associations/proxy_base.rb +48 -0
- data/lib/mongo_doc/attributes.rb +84 -0
- data/lib/mongo_doc/bson.rb +31 -0
- data/lib/mongo_doc/collection.rb +82 -0
- data/lib/mongo_doc/connection.rb +88 -0
- data/lib/mongo_doc/contexts.rb +31 -0
- data/lib/mongo_doc/contexts/ids.rb +41 -0
- data/lib/mongo_doc/contexts/mongo.rb +272 -0
- data/lib/mongo_doc/criteria.rb +70 -0
- data/lib/mongo_doc/cursor.rb +32 -0
- data/lib/mongo_doc/document.rb +205 -0
- data/lib/mongo_doc/ext.rb +16 -0
- data/lib/mongo_doc/ext/array.rb +5 -0
- data/lib/mongo_doc/ext/binary.rb +7 -0
- data/lib/mongo_doc/ext/boolean_class.rb +17 -0
- data/lib/mongo_doc/ext/date.rb +19 -0
- data/lib/mongo_doc/ext/date_time.rb +17 -0
- data/lib/mongo_doc/ext/dbref.rb +7 -0
- data/lib/mongo_doc/ext/hash.rb +7 -0
- data/lib/mongo_doc/ext/min_max_keys.rb +13 -0
- data/lib/mongo_doc/ext/nil_class.rb +5 -0
- data/lib/mongo_doc/ext/numeric.rb +17 -0
- data/lib/mongo_doc/ext/object.rb +19 -0
- data/lib/mongo_doc/ext/object_id.rb +7 -0
- data/lib/mongo_doc/ext/regexp.rb +5 -0
- data/lib/mongo_doc/ext/string.rb +5 -0
- data/lib/mongo_doc/ext/symbol.rb +5 -0
- data/lib/mongo_doc/ext/time.rb +9 -0
- data/lib/mongo_doc/finders.rb +38 -0
- data/lib/mongo_doc/index.rb +46 -0
- data/lib/mongo_doc/matchers.rb +35 -0
- data/lib/mongo_doc/root.rb +26 -0
- data/lib/mongo_doc/scope.rb +64 -0
- data/lib/mongo_doc/validations.rb +12 -0
- data/lib/mongo_doc/validations/macros.rb +11 -0
- data/lib/mongo_doc/validations/validates_embedded.rb +13 -0
- data/lib/mongoid/contexts/enumerable.rb +151 -0
- data/lib/mongoid/contexts/paging.rb +42 -0
- data/lib/mongoid/criteria.rb +239 -0
- data/lib/mongoid/criterion/complex.rb +21 -0
- data/lib/mongoid/criterion/exclusion.rb +65 -0
- data/lib/mongoid/criterion/inclusion.rb +93 -0
- data/lib/mongoid/criterion/optional.rb +136 -0
- data/lib/mongoid/extensions/hash/criteria_helpers.rb +20 -0
- data/lib/mongoid/extensions/symbol/inflections.rb +36 -0
- data/lib/mongoid/matchers/all.rb +11 -0
- data/lib/mongoid/matchers/default.rb +26 -0
- data/lib/mongoid/matchers/exists.rb +13 -0
- data/lib/mongoid/matchers/gt.rb +11 -0
- data/lib/mongoid/matchers/gte.rb +11 -0
- data/lib/mongoid/matchers/in.rb +11 -0
- data/lib/mongoid/matchers/lt.rb +11 -0
- data/lib/mongoid/matchers/lte.rb +11 -0
- data/lib/mongoid/matchers/ne.rb +11 -0
- data/lib/mongoid/matchers/nin.rb +11 -0
- data/lib/mongoid/matchers/size.rb +11 -0
- data/mongo_doc_rails2.gemspec +237 -0
- data/mongod.example.yml +2 -0
- data/mongodb.example.yml +14 -0
- data/perf/mongo_doc_object.rb +83 -0
- data/perf/mongo_document.rb +84 -0
- data/perf/ruby_driver.rb +49 -0
- data/script/console +8 -0
- data/spec/array_including_argument_matcher.rb +62 -0
- data/spec/associations/collection_proxy_spec.rb +233 -0
- data/spec/associations/document_proxy_spec.rb +45 -0
- data/spec/associations/hash_proxy_spec.rb +181 -0
- data/spec/associations/proxy_base_spec.rb +92 -0
- data/spec/associations_spec.rb +218 -0
- data/spec/attributes_accessor_spec.rb +33 -0
- data/spec/attributes_spec.rb +145 -0
- data/spec/bson_matchers.rb +54 -0
- data/spec/bson_spec.rb +196 -0
- data/spec/collection_spec.rb +169 -0
- data/spec/connection_spec.rb +147 -0
- data/spec/contexts/ids_spec.rb +49 -0
- data/spec/contexts/mongo_spec.rb +235 -0
- data/spec/contexts_spec.rb +56 -0
- data/spec/criteria_spec.rb +69 -0
- data/spec/cursor_spec.rb +91 -0
- data/spec/document_ext.rb +9 -0
- data/spec/document_spec.rb +553 -0
- data/spec/embedded_save_spec.rb +73 -0
- data/spec/ext_spec.rb +89 -0
- data/spec/finders_spec.rb +61 -0
- data/spec/hash_matchers.rb +27 -0
- data/spec/index_spec.rb +79 -0
- data/spec/matchers_spec.rb +342 -0
- data/spec/mongodb.yml +6 -0
- data/spec/mongodb_pairs.yml +8 -0
- data/spec/new_record_spec.rb +128 -0
- data/spec/root_spec.rb +41 -0
- data/spec/scope_spec.rb +79 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/validations_spec.rb +30 -0
- metadata +346 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Thanks Sandro!
|
|
2
|
+
# http://github.com/sandro
|
|
3
|
+
module MongoDoc
|
|
4
|
+
module Associations
|
|
5
|
+
class CollectionProxy
|
|
6
|
+
include ProxyBase
|
|
7
|
+
|
|
8
|
+
# List of array methods (that are not in +Object+) that need to be
|
|
9
|
+
# delegated to +collection+.
|
|
10
|
+
ARRAY_METHODS = (Array.instance_methods - Object.instance_methods).map { |n| n.to_s }
|
|
11
|
+
|
|
12
|
+
# List of additional methods that must be delegated to +collection+.
|
|
13
|
+
MUST_DEFINE = %w[to_a to_ary inspect to_bson ==]
|
|
14
|
+
|
|
15
|
+
DO_NOT_DEFINE = %w[concat insert replace]
|
|
16
|
+
|
|
17
|
+
(ARRAY_METHODS + MUST_DEFINE - DO_NOT_DEFINE).uniq.each do |method|
|
|
18
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
19
|
+
def #{method}(*args, &block) # def each(*args, &block)
|
|
20
|
+
collection.send(:#{method}, *args, &block) # collection.send(:each, *args, &block)
|
|
21
|
+
end # end
|
|
22
|
+
RUBY
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
attr_reader :collection
|
|
26
|
+
|
|
27
|
+
def _modifier_path=(path)
|
|
28
|
+
super
|
|
29
|
+
collection.each do |item|
|
|
30
|
+
item._modifier_path = _modifier_path + '.$' if ProxyBase.is_document?(item)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def _root=(value)
|
|
35
|
+
@_root = value
|
|
36
|
+
collection.each do |item|
|
|
37
|
+
item._root = value if ProxyBase.is_document?(item)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
%w(_root _selector_path).each do |setter|
|
|
42
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
43
|
+
def #{setter}=(val)
|
|
44
|
+
super
|
|
45
|
+
collection.each do |item|
|
|
46
|
+
item.#{setter} = #{setter} if ProxyBase.is_document?(item)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
RUBY
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def initialize(options)
|
|
53
|
+
@collection = []
|
|
54
|
+
super
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
alias _append <<
|
|
58
|
+
def <<(item)
|
|
59
|
+
attach(item)
|
|
60
|
+
_append item
|
|
61
|
+
self
|
|
62
|
+
end
|
|
63
|
+
alias push <<
|
|
64
|
+
|
|
65
|
+
alias add []=
|
|
66
|
+
def []=(index, item)
|
|
67
|
+
attach(item)
|
|
68
|
+
add(index, item)
|
|
69
|
+
end
|
|
70
|
+
alias insert []=
|
|
71
|
+
|
|
72
|
+
def build(attrs)
|
|
73
|
+
item = _assoc_class.new(attrs)
|
|
74
|
+
push(item)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def concat(array)
|
|
78
|
+
array.each do |item|
|
|
79
|
+
push(item)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Lie about our class. Borrowed from Rake::FileList
|
|
84
|
+
# Note: Does not work for case equality (<tt>===</tt>)
|
|
85
|
+
def is_a?(klass)
|
|
86
|
+
klass == Array || super(klass)
|
|
87
|
+
end
|
|
88
|
+
alias kind_of? is_a?
|
|
89
|
+
|
|
90
|
+
def replace(other)
|
|
91
|
+
clear
|
|
92
|
+
concat(other)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
alias _unshift unshift
|
|
96
|
+
def unshift(item)
|
|
97
|
+
attach(item)
|
|
98
|
+
_unshift(item)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def valid?
|
|
102
|
+
all? do |child|
|
|
103
|
+
if ProxyBase.is_document?(child)
|
|
104
|
+
child.valid?
|
|
105
|
+
else
|
|
106
|
+
true
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
protected
|
|
112
|
+
|
|
113
|
+
def attach_document(doc)
|
|
114
|
+
doc._modifier_path = _modifier_path + '.$'
|
|
115
|
+
doc._selector_path = _selector_path
|
|
116
|
+
doc._root = _root
|
|
117
|
+
_root.send(:register_save_observer, doc)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
module MongoDoc
|
|
2
|
+
module Associations
|
|
3
|
+
class DocumentProxy
|
|
4
|
+
include ProxyBase
|
|
5
|
+
|
|
6
|
+
attr_reader :document
|
|
7
|
+
|
|
8
|
+
delegate :to_bson, :id, :to => :document
|
|
9
|
+
|
|
10
|
+
%w(_modifier_path _selector_path).each do |setter|
|
|
11
|
+
class_eval(<<-RUBY, __FILE__, __LINE__)
|
|
12
|
+
def #{setter}=(path)
|
|
13
|
+
super
|
|
14
|
+
document.#{setter} = #{setter} if ProxyBase.is_document?(document)
|
|
15
|
+
end
|
|
16
|
+
RUBY
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def _root=(value)
|
|
20
|
+
@_root = value
|
|
21
|
+
document._root = value if ProxyBase.is_document?(document)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def ==(other)
|
|
25
|
+
if self.class === other
|
|
26
|
+
document == other.document
|
|
27
|
+
else
|
|
28
|
+
document == other
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def build(attrs)
|
|
33
|
+
item = _assoc_class.new(attrs)
|
|
34
|
+
self.document = item
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def document=(doc)
|
|
38
|
+
attach(doc)
|
|
39
|
+
@document = doc
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def valid?
|
|
43
|
+
if ProxyBase.is_document?(document)
|
|
44
|
+
document.valid?
|
|
45
|
+
else
|
|
46
|
+
true
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def method_missing(method, *args)
|
|
53
|
+
unless document.respond_to?(method)
|
|
54
|
+
raise NoMethodError, "undefined method `#{method.to_s}' for proxied \"#{document}\":#{document.class.to_s}"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
if block_given?
|
|
58
|
+
document.send(method, *args) { |*block_args| yield(*block_args) }
|
|
59
|
+
else
|
|
60
|
+
document.send(method, *args)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
module MongoDoc
|
|
2
|
+
class InvalidEmbeddedHashKey < RuntimeError; end
|
|
3
|
+
|
|
4
|
+
module Associations
|
|
5
|
+
class HashProxy
|
|
6
|
+
include ProxyBase
|
|
7
|
+
|
|
8
|
+
HASH_METHODS = (Hash.instance_methods - Object.instance_methods).map { |n| n.to_s }
|
|
9
|
+
|
|
10
|
+
MUST_DEFINE = %w[to_a inspect to_bson ==]
|
|
11
|
+
|
|
12
|
+
DO_NOT_DEFINE = %w[merge! replace store update]
|
|
13
|
+
|
|
14
|
+
(HASH_METHODS + MUST_DEFINE - DO_NOT_DEFINE).uniq.each do |method|
|
|
15
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
16
|
+
def #{method}(*args, &block) # def each(*args, &block)
|
|
17
|
+
hash.send(:#{method}, *args, &block) # hash.send(:each, *args, &block)
|
|
18
|
+
end # end
|
|
19
|
+
RUBY
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
attr_reader :hash
|
|
23
|
+
|
|
24
|
+
%w(_modifier_path _selector_path).each do |setter|
|
|
25
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
26
|
+
def #{setter}=(path)
|
|
27
|
+
super
|
|
28
|
+
hash.each do |key, doc|
|
|
29
|
+
doc.#{setter} = #{setter} + '.' + key.to_s if ProxyBase.is_document?(doc)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
RUBY
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def initialize(options)
|
|
36
|
+
@hash = {}
|
|
37
|
+
super
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
alias put []=
|
|
41
|
+
def []=(key, value)
|
|
42
|
+
raise InvalidEmbeddedHashKey.new("Key name [#{key}] must be a valid element name, see http://www.mongodb.org/display/DOCS/BSON#BSON-noteonelementname") unless valid_key?(key)
|
|
43
|
+
put(key, attach(key, value))
|
|
44
|
+
end
|
|
45
|
+
alias store []=
|
|
46
|
+
|
|
47
|
+
def build(key, attrs)
|
|
48
|
+
item = _assoc_class.new(attrs)
|
|
49
|
+
store(key, item)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Lie about our class. Borrowed from Rake::FileList
|
|
53
|
+
# Note: Does not work for case equality (<tt>===</tt>)
|
|
54
|
+
def is_a?(klass)
|
|
55
|
+
klass == Hash || super(klass)
|
|
56
|
+
end
|
|
57
|
+
alias kind_of? is_a?
|
|
58
|
+
|
|
59
|
+
def merge!(other)
|
|
60
|
+
other.each_pair do |key, value|
|
|
61
|
+
self[key] = if block_given?
|
|
62
|
+
yield key, [key], value
|
|
63
|
+
else
|
|
64
|
+
value
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
alias update merge!
|
|
69
|
+
|
|
70
|
+
def replace(other)
|
|
71
|
+
clear
|
|
72
|
+
merge!(other)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def valid?
|
|
76
|
+
values.all? do |child|
|
|
77
|
+
if ProxyBase.is_document?(child)
|
|
78
|
+
child.valid?
|
|
79
|
+
else
|
|
80
|
+
true
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
protected
|
|
86
|
+
|
|
87
|
+
def attach(key, value)
|
|
88
|
+
if ProxyBase.is_document?(value)
|
|
89
|
+
proxy = DocumentProxy.new(:path => _selector_path, :assoc_name => key, :root => _root, :parent => self)
|
|
90
|
+
proxy.document = value
|
|
91
|
+
proxy
|
|
92
|
+
else
|
|
93
|
+
value
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def valid_key?(key)
|
|
98
|
+
(String === key or Symbol === key) and key.to_s !~ /(_id|query|\$.*|.*\..*)/
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module MongoDoc
|
|
2
|
+
module Associations
|
|
3
|
+
module ProxyBase
|
|
4
|
+
def self.included(klass)
|
|
5
|
+
klass.class_eval do
|
|
6
|
+
attr_reader :_assoc_class, :_assoc_name, :_modifier_path, :_root, :_selector_path
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
%w(_modifier_path _selector_path).each do |setter|
|
|
11
|
+
module_eval(<<-RUBY, __FILE__, __LINE__)
|
|
12
|
+
def #{setter}=(path)
|
|
13
|
+
@#{setter} = (path.blank? ? '' : path + '.') + _assoc_name.to_s
|
|
14
|
+
end
|
|
15
|
+
RUBY
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def _root=(root)
|
|
19
|
+
@_root = root
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def initialize(options)
|
|
23
|
+
@_assoc_name = options[:assoc_name]
|
|
24
|
+
@_assoc_class = options[:assoc_class]
|
|
25
|
+
self._root = options[:root]
|
|
26
|
+
self._selector_path = self._modifier_path = options[:path]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.is_document?(object)
|
|
30
|
+
object.respond_to?(:_root)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
protected
|
|
34
|
+
|
|
35
|
+
def attach(obj)
|
|
36
|
+
attach_document(obj) if ProxyBase.is_document?(obj)
|
|
37
|
+
obj
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def attach_document(doc)
|
|
41
|
+
doc._modifier_path = _modifier_path
|
|
42
|
+
doc._selector_path = _selector_path
|
|
43
|
+
doc._root = _root
|
|
44
|
+
_root.send(:register_save_observer, doc)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
module MongoDoc
|
|
2
|
+
module Attributes
|
|
3
|
+
def self.included(klass)
|
|
4
|
+
klass.class_eval do
|
|
5
|
+
class_inheritable_array :_keys
|
|
6
|
+
self._keys = []
|
|
7
|
+
class_inheritable_array :_associations
|
|
8
|
+
self._associations = []
|
|
9
|
+
|
|
10
|
+
attr_accessor :_id
|
|
11
|
+
|
|
12
|
+
extend ClassMethods
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def attributes
|
|
17
|
+
hash = {}
|
|
18
|
+
self.class._attributes.each do |attr|
|
|
19
|
+
hash[attr] = send(attr)
|
|
20
|
+
end
|
|
21
|
+
hash
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def attributes=(attrs)
|
|
25
|
+
attrs.each do |key, value|
|
|
26
|
+
send("#{key}=", value)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
module ClassMethods
|
|
31
|
+
|
|
32
|
+
def self.extended(klass)
|
|
33
|
+
klass.class_eval do
|
|
34
|
+
singleton_class.alias_method_chain :attr_accessor, :mongo
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def _attributes
|
|
39
|
+
_keys + _associations
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def attr_accessor_with_mongo(*args)
|
|
43
|
+
opts = args.extract_options!
|
|
44
|
+
default = opts.delete(:default)
|
|
45
|
+
type = opts.delete(:type)
|
|
46
|
+
args.each do |name|
|
|
47
|
+
_keys << name unless _keys.include?(name)
|
|
48
|
+
attr_writer name
|
|
49
|
+
|
|
50
|
+
if default
|
|
51
|
+
define_method("_default_#{name}", default.kind_of?(Proc) ? default : proc { default })
|
|
52
|
+
private "_default_#{name}"
|
|
53
|
+
|
|
54
|
+
module_eval(<<-RUBY, __FILE__, __LINE__)
|
|
55
|
+
def #{name} # def birth_date
|
|
56
|
+
unless defined? @#{name} # unless defined? @birth_date
|
|
57
|
+
@#{name} = _default_#{name} # @birth_date = _default_birth_date
|
|
58
|
+
end # end
|
|
59
|
+
class << self; attr_reader :#{name} end # class << self; attr_reader :birth_date end
|
|
60
|
+
@#{name} # @birth_date
|
|
61
|
+
end # end
|
|
62
|
+
RUBY
|
|
63
|
+
else
|
|
64
|
+
attr_reader name
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
if type and type.respond_to?(:cast_from_string)
|
|
68
|
+
module_eval(<<-RUBY, __FILE__, __LINE__)
|
|
69
|
+
def #{name}_with_type=(value) # def birth_date_with_type=(value)
|
|
70
|
+
if value.kind_of?(String) # if value.kind_of?(String)
|
|
71
|
+
value = #{type}.cast_from_string(value) # value = Date.cast_from_string(value)
|
|
72
|
+
end # end
|
|
73
|
+
self.#{name}_without_type = value # self.birth_date_without_type = value
|
|
74
|
+
end # end
|
|
75
|
+
RUBY
|
|
76
|
+
alias_method_chain "#{name}=", :type
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
alias key attr_accessor_with_mongo
|
|
81
|
+
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require 'mongo_doc/ext'
|
|
2
|
+
|
|
3
|
+
module MongoDoc
|
|
4
|
+
module BSON
|
|
5
|
+
CLASS_KEY = "json_class"
|
|
6
|
+
|
|
7
|
+
def self.decode(bson, options = {})
|
|
8
|
+
return bson if options[:raw_json]
|
|
9
|
+
case bson
|
|
10
|
+
when Hash
|
|
11
|
+
bson_create(bson, options)
|
|
12
|
+
when Array
|
|
13
|
+
array_create(bson, options)
|
|
14
|
+
else
|
|
15
|
+
bson
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.bson_create(bson_hash, options = {})
|
|
20
|
+
return bson_hash if options[:raw_json]
|
|
21
|
+
klass = bson_hash.delete(CLASS_KEY)
|
|
22
|
+
return bson_hash.each_pair {|key, value| bson_hash[key] = decode(value, options)} unless klass
|
|
23
|
+
klass.constantize.bson_create(bson_hash, options)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.array_create(bson_array, options = {})
|
|
27
|
+
return bson_array if options[:raw_json]
|
|
28
|
+
bson_array.map {|item| decode(item, options)}
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|