mongo_db 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/mongo_db/driver/core/collection.rb +92 -43
- data/lib/mongo_db/driver/core.rb +2 -3
- data/lib/mongo_db/driver/more/{collection.rb → collection_finders.rb} +16 -20
- data/lib/mongo_db/driver/more.rb +5 -2
- data/lib/mongo_db/driver/spec.rb +8 -8
- data/lib/mongo_db/model/model_helper.rb +154 -0
- data/lib/mongo_db/model/model_serializer.rb +3 -0
- data/lib/mongo_db/model.rb +13 -1
- data/lib/mongo_db/support.rb +4 -4
- data/readme.md +78 -17
- data/spec/driver/core/collection_spec.rb +11 -11
- data/spec/driver/core/crud_spec.rb +11 -11
- data/spec/driver/core/hash_helper_spec.rb +7 -2
- data/spec/{driver_example_spec.rb → driver/example_spec.rb} +25 -28
- data/spec/driver/fixes_spec.rb +12 -0
- data/spec/driver/more/querying_spec.rb +16 -16
- data/spec/driver/spec_helper.rb +2 -2
- data/spec/model/{object/callbacks.rb → callbacks.rb} +13 -13
- data/spec/model/{model/query.rb → example.rb} +0 -0
- data/spec/model/{model/crud.rb → model_crud.rb} +25 -25
- data/spec/model/{object/validation.rb → validation.rb} +18 -18
- data/spec/{model/object → object}/crud_shared.rb +8 -8
- data/spec/object/example_spec.rb +64 -0
- data/spec/{model/object/crud.rb → object/object_crud_spec.rb} +17 -17
- data/spec/object/spec_helper.rb +3 -0
- data/spec/test.rb +9 -4
- metadata +17 -17
- data/lib/mongo_db/driver/core/hash_helper.rb +0 -67
- data/lib/old/advanced_finders.rb +0 -26
- data/lib/old/query.rb +0 -91
- data/lib/old/query_spec.rb +0 -77
- data/spec/model/spec_helper.rb +0 -1
@@ -1,27 +1,33 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'date'
|
3
|
+
|
1
4
|
module Mongo::Ext::Collection
|
2
|
-
#
|
5
|
+
#
|
3
6
|
# CRUD
|
4
|
-
#
|
7
|
+
#
|
5
8
|
def save_with_ext doc, opts = {}
|
6
9
|
save_without_ext doc, reverse_merge_defaults(opts, :safe)
|
7
10
|
end
|
8
|
-
|
9
|
-
def insert_with_ext
|
10
|
-
insert_without_ext
|
11
|
+
|
12
|
+
def insert_with_ext args, opts = {}
|
13
|
+
result = insert_without_ext args, reverse_merge_defaults(opts, :safe)
|
14
|
+
|
15
|
+
# fix for mongodriver, it will return single result if we supply [doc] as args
|
16
|
+
(args.is_a?(Array) and !result.is_a?(Array)) ? [result] : result
|
11
17
|
end
|
12
|
-
|
13
|
-
def update_with_ext selector,
|
18
|
+
|
19
|
+
def update_with_ext selector, doc, opts = {}
|
14
20
|
selector = convert_underscore_to_dollar_in_selector selector
|
15
|
-
|
16
|
-
|
17
|
-
# because :multi works only with $ operators, we need to check it
|
18
|
-
opts = if
|
21
|
+
doc = convert_underscore_to_dollar_in_update doc
|
22
|
+
|
23
|
+
# because :multi works only with $ operators, we need to check if it's applicable
|
24
|
+
opts = if doc.keys.any?{|k| k =~ /^\$/}
|
19
25
|
reverse_merge_defaults(opts, :safe, :multi)
|
20
26
|
else
|
21
27
|
reverse_merge_defaults(opts, :safe)
|
22
28
|
end
|
23
|
-
|
24
|
-
update_without_ext selector,
|
29
|
+
|
30
|
+
update_without_ext selector, doc, opts
|
25
31
|
end
|
26
32
|
|
27
33
|
def remove_with_ext selector = {}, opts = {}
|
@@ -32,64 +38,107 @@ module Mongo::Ext::Collection
|
|
32
38
|
def destroy *args
|
33
39
|
remove *args
|
34
40
|
end
|
35
|
-
|
36
|
-
#
|
41
|
+
|
42
|
+
#
|
37
43
|
# Querying
|
38
|
-
#
|
39
|
-
def first
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
o
|
44
|
+
#
|
45
|
+
def first selector = nil, opts = {}
|
46
|
+
selector = convert_underscore_to_dollar_in_selector selector if selector.is_a? Hash
|
47
|
+
|
48
|
+
h = find_one selector, opts
|
49
|
+
symbolize_doc h
|
45
50
|
end
|
46
|
-
|
51
|
+
|
47
52
|
def all *args, &block
|
48
53
|
if block
|
49
54
|
each *args, &block
|
50
55
|
else
|
51
56
|
list = []
|
52
|
-
each(*args){|
|
57
|
+
each(*args){|doc| list << doc}
|
53
58
|
list
|
54
59
|
end
|
55
60
|
end
|
56
|
-
|
61
|
+
|
57
62
|
def each selector = {}, opts = {}, &block
|
58
63
|
selector = convert_underscore_to_dollar_in_selector selector
|
59
|
-
|
64
|
+
|
60
65
|
cursor = nil
|
61
66
|
begin
|
62
67
|
cursor = find selector, reverse_merge_defaults(opts, :batch_size)
|
63
|
-
cursor.each do |
|
64
|
-
|
65
|
-
block.call
|
68
|
+
cursor.each do |doc|
|
69
|
+
doc = symbolize_doc doc
|
70
|
+
block.call doc
|
66
71
|
end
|
67
72
|
nil
|
68
73
|
ensure
|
69
74
|
cursor.close if cursor
|
70
75
|
end
|
76
|
+
nil
|
71
77
|
end
|
72
|
-
|
78
|
+
|
73
79
|
protected
|
80
|
+
QUERY_KEYWORDS = [
|
81
|
+
:_lt, :_lte, :_gt, :_gte,
|
82
|
+
:_all, :_exists, :_mod, :_ne, :_in, :_nin,
|
83
|
+
:_nor, :_or, :_and,
|
84
|
+
:_size, :_type
|
85
|
+
].to_set
|
86
|
+
|
87
|
+
UPDATE_KEYWORDS = [
|
88
|
+
:_inc, :_set, :_unset, :_push, :_pushAll, :_addToSet, :_pop, :_pull, :_pullAll, :_rename, :_bit
|
89
|
+
].to_set
|
90
|
+
|
91
|
+
def reverse_merge_defaults opts, *keys
|
92
|
+
h = opts.clone
|
93
|
+
keys.each do |k|
|
94
|
+
h[k] = Mongo.defaults[k] if Mongo.defaults.include?(k) and !h.include?(k)
|
95
|
+
end
|
96
|
+
h
|
97
|
+
end
|
98
|
+
|
99
|
+
# symbolizing hashes
|
100
|
+
def symbolize_doc doc
|
101
|
+
return doc unless Mongo.defaults[:symbolize]
|
102
|
+
|
103
|
+
Mongo::Ext::Collection.convert_doc doc do |k, v, result|
|
104
|
+
k = k.to_sym if k.is_a? String
|
105
|
+
result[k] = v
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# replaces :_lt to :$lt in query
|
74
110
|
def convert_underscore_to_dollar_in_selector selector
|
75
|
-
|
76
|
-
|
111
|
+
return selector unless Mongo.defaults[:convert_underscore_to_dollar]
|
112
|
+
|
113
|
+
Mongo::Ext::Collection.convert_doc selector do |k, v, result|
|
114
|
+
k = "$#{k.to_s[1..-1]}".to_sym if QUERY_KEYWORDS.include?(k)
|
115
|
+
result[k] = v
|
77
116
|
end
|
78
|
-
selector
|
79
117
|
end
|
80
|
-
|
118
|
+
|
119
|
+
# replaces :_set to :$set in query
|
81
120
|
def convert_underscore_to_dollar_in_update update
|
82
|
-
|
83
|
-
|
121
|
+
return update unless Mongo.defaults[:convert_underscore_to_dollar]
|
122
|
+
|
123
|
+
Mongo::Ext::Collection.convert_doc update do |k, v, result|
|
124
|
+
k = "$#{k.to_s[1..-1]}".to_sym if UPDATE_KEYWORDS.include?(k)
|
125
|
+
result[k] = v
|
84
126
|
end
|
85
|
-
update
|
86
127
|
end
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
128
|
+
|
129
|
+
# walks on hash and creates another (also works with nested & arrays)
|
130
|
+
def self.convert_doc doc, &block
|
131
|
+
if doc.is_a? Hash
|
132
|
+
result = {}
|
133
|
+
doc.each do |k, v|
|
134
|
+
v = convert_doc v, &block
|
135
|
+
block.call k, v, result
|
136
|
+
end
|
137
|
+
result
|
138
|
+
elsif doc.is_a? Array
|
139
|
+
doc.collect{|v| convert_doc v, &block}
|
140
|
+
else
|
141
|
+
doc
|
92
142
|
end
|
93
|
-
h
|
94
143
|
end
|
95
144
|
end
|
data/lib/mongo_db/driver/core.rb
CHANGED
@@ -7,8 +7,7 @@ class Mongo::Ext; end
|
|
7
7
|
|
8
8
|
%w(
|
9
9
|
database
|
10
|
-
collection
|
11
|
-
hash_helper
|
10
|
+
collection
|
12
11
|
).each{|f| require "mongo_db/driver/core/#{f}"}
|
13
12
|
|
14
13
|
# defaults
|
@@ -25,7 +24,7 @@ Mongo::DB.send :include, Mongo::Ext::DB
|
|
25
24
|
# collection
|
26
25
|
Mongo::Collection.class_eval do
|
27
26
|
include Mongo::Ext::Collection
|
28
|
-
|
27
|
+
|
29
28
|
%w(insert update remove save).each do |method|
|
30
29
|
alias_method "#{method}_without_ext", method
|
31
30
|
alias_method method, "#{method}_with_ext"
|
@@ -1,7 +1,7 @@
|
|
1
|
-
module Mongo::Ext::
|
2
|
-
#
|
1
|
+
module Mongo::Ext::CollectionFinders
|
2
|
+
#
|
3
3
|
# first_by_id, special case
|
4
|
-
#
|
4
|
+
#
|
5
5
|
def first_by_id id
|
6
6
|
first _id: id
|
7
7
|
end
|
@@ -11,31 +11,27 @@ module Mongo::Ext::Collection
|
|
11
11
|
first_by_id(id) || raise(Mongo::NotFound, "document with id #{id} not found!")
|
12
12
|
end
|
13
13
|
alias_method :by_id!, :first_by_id!
|
14
|
-
|
15
|
-
def where &block
|
16
|
-
Mongo::Ext::Query.new self, &block
|
17
|
-
end
|
18
|
-
|
14
|
+
|
19
15
|
protected
|
20
|
-
#
|
16
|
+
#
|
21
17
|
# first_by_field, all_by_field
|
22
|
-
#
|
18
|
+
#
|
23
19
|
def method_missing clause, *a, &b
|
24
|
-
if clause =~ /^([a-z]_by_[a-z_])|(by_[a-z_])/
|
25
|
-
clause = clause.to_s
|
26
|
-
|
20
|
+
if clause =~ /^([a-z]_by_[a-z_])|(by_[a-z_])/
|
21
|
+
clause = clause.to_s
|
22
|
+
|
27
23
|
bang = clause =~ /!$/
|
28
24
|
clause = clause[0..-2] if bang
|
29
|
-
|
30
|
-
finder, field = if clause =~ /^by_/
|
25
|
+
|
26
|
+
finder, field = if clause =~ /^by_/
|
31
27
|
['first', clause.sub(/by_/, '')]
|
32
|
-
else
|
33
|
-
clause.split(/_by_/, 2)
|
34
|
-
end
|
28
|
+
else
|
29
|
+
clause.split(/_by_/, 2)
|
30
|
+
end
|
35
31
|
finder = 'first' if finder == 'find'
|
36
|
-
|
32
|
+
|
37
33
|
raise "You can't use bang version with :#{finder}!" if bang and finder != 'first'
|
38
|
-
|
34
|
+
|
39
35
|
raise "invalid arguments for finder (#{a})!" unless a.size == 1
|
40
36
|
field_value = a.first
|
41
37
|
|
data/lib/mongo_db/driver/more.rb
CHANGED
@@ -3,5 +3,8 @@ require 'mongo_db/driver/core'
|
|
3
3
|
class Mongo::NotFound < StandardError; end
|
4
4
|
|
5
5
|
%w(
|
6
|
-
|
7
|
-
).each{|f| require "mongo_db/driver/more/#{f}"}
|
6
|
+
collection_finders
|
7
|
+
).each{|f| require "mongo_db/driver/more/#{f}"}
|
8
|
+
|
9
|
+
Mongo::Collection.send :include, Mongo::Ext::CollectionFinders
|
10
|
+
|
data/lib/mongo_db/driver/spec.rb
CHANGED
@@ -1,31 +1,31 @@
|
|
1
1
|
MONGO_TEST_DATABASE_NAME = 'default_test'
|
2
2
|
|
3
|
-
rspec do
|
3
|
+
rspec do
|
4
4
|
def mongo
|
5
5
|
$mongo || raise('Mongo not defined (use :with_mongo helper)!')
|
6
6
|
end
|
7
|
-
|
7
|
+
|
8
8
|
def clear_mongo name = MONGO_TEST_DATABASE_NAME
|
9
9
|
mongo.db.collection_names.each do |name|
|
10
10
|
next if name =~ /^system\./
|
11
11
|
mongo.db.collection(name).drop
|
12
12
|
end
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
class << self
|
16
16
|
def with_mongo
|
17
17
|
before :all do
|
18
18
|
require 'ostruct'
|
19
|
-
|
19
|
+
|
20
20
|
$mongo = OpenStruct.new.tap do |m|
|
21
21
|
m.connection = Mongo::Connection.new
|
22
22
|
m.db = m.connection.db MONGO_TEST_DATABASE_NAME
|
23
23
|
end
|
24
|
-
end
|
24
|
+
end
|
25
25
|
after(:all){$mongo = nil}
|
26
|
-
|
27
|
-
before do
|
28
|
-
clear_mongo
|
26
|
+
|
27
|
+
before do
|
28
|
+
clear_mongo
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
module Mongo::Ext::ModelHelper
|
2
|
+
#
|
3
|
+
# CRUD
|
4
|
+
#
|
5
|
+
def save_with_model doc, opts = {}
|
6
|
+
if doc.is_a? Hash
|
7
|
+
save_without_model doc, opts
|
8
|
+
else
|
9
|
+
if id = doc.instance_variable_get(:@_id)
|
10
|
+
update({:_id => id}, doc, opts.merge(upsert: true))
|
11
|
+
else
|
12
|
+
insert doc, opts
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def insert_with_model args, opts = {}
|
18
|
+
docs = args.is_a?(Array) ? args : [args]
|
19
|
+
result = _insert_with_model docs, opts
|
20
|
+
args.is_a?(Array) ? result : result.first
|
21
|
+
end
|
22
|
+
|
23
|
+
def update_with_model selector, doc, opts = {}
|
24
|
+
doc = Mongo::Ext::ModelHelper.convert_object_to_doc doc unless doc.is_a?(Hash)
|
25
|
+
update_without_model selector, doc, opts
|
26
|
+
end
|
27
|
+
|
28
|
+
def remove_with_model arg = {}, opts = {}
|
29
|
+
if arg.is_a? Hash
|
30
|
+
remove_without_model arg, opts
|
31
|
+
else
|
32
|
+
id = arg.instance_variable_get(:@_id) || "can't remove object without _id (#{arg})!"
|
33
|
+
remove_without_model({_id: id}, opts)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
#
|
39
|
+
# Querying
|
40
|
+
#
|
41
|
+
def first *args, &block
|
42
|
+
doc = super *args, &block
|
43
|
+
Mongo::Ext::ModelHelper.convert_doc_to_object doc
|
44
|
+
end
|
45
|
+
|
46
|
+
def each *args, &block
|
47
|
+
super *args do |doc|
|
48
|
+
doc = Mongo::Ext::ModelHelper.convert_doc_to_object(doc)
|
49
|
+
block.call doc
|
50
|
+
end
|
51
|
+
nil
|
52
|
+
end
|
53
|
+
|
54
|
+
protected
|
55
|
+
def _insert_with_model docs, opts
|
56
|
+
hashes = docs.collect do |doc|
|
57
|
+
doc.is_a?(Hash) ? doc : Mongo::Ext::ModelHelper.convert_object_to_doc(doc)
|
58
|
+
end
|
59
|
+
result = insert_without_model hashes, opts
|
60
|
+
hashes.each_with_index do |h, i|
|
61
|
+
Mongo::Ext::ModelHelper.update_object_after_insertion docs[i], h
|
62
|
+
end
|
63
|
+
result
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
SIMPLE_TYPES = [
|
68
|
+
Fixnum, Float,
|
69
|
+
TrueClass, FalseClass,
|
70
|
+
String, Symbol,
|
71
|
+
Array, Hash, Set,
|
72
|
+
Data, DateTime,
|
73
|
+
NilClass, Time,
|
74
|
+
BSON::ObjectId
|
75
|
+
].to_set
|
76
|
+
|
77
|
+
class << self
|
78
|
+
def update_object_after_insertion doc, hash
|
79
|
+
return if doc.is_a? Hash
|
80
|
+
if id = hash[:_id] || hash['_id']
|
81
|
+
doc.instance_variable_set :@_id, id
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# converts object to hash (also works with nested & arrays)
|
86
|
+
def convert_object_to_doc obj
|
87
|
+
return obj.to_mongo if obj.respond_to? :to_mongo
|
88
|
+
|
89
|
+
if obj.is_a? Hash
|
90
|
+
doc = {}
|
91
|
+
obj.each do |k, v|
|
92
|
+
doc[k] = convert_object_to_doc v
|
93
|
+
end
|
94
|
+
doc
|
95
|
+
elsif obj.is_a? Array
|
96
|
+
obj.collect{|v| convert_object_to_doc v}
|
97
|
+
elsif SIMPLE_TYPES.include? obj.class
|
98
|
+
obj
|
99
|
+
else
|
100
|
+
doc = {}
|
101
|
+
|
102
|
+
# copying instance variables to hash
|
103
|
+
obj.instance_variables.each do |iv_name|
|
104
|
+
# skipping variables starting with _xx, usually they
|
105
|
+
# have specific meaning and used for example for cache
|
106
|
+
next if iv_name =~ /^@_/ and iv_name != :@_id
|
107
|
+
|
108
|
+
k = iv_name.to_s[1..-1]
|
109
|
+
k = k.to_sym if Mongo.defaults[:symbolize]
|
110
|
+
v = obj.instance_variable_get iv_name
|
111
|
+
doc[k] = convert_object_to_doc v
|
112
|
+
end
|
113
|
+
|
114
|
+
# setting class
|
115
|
+
class_name = '_class'
|
116
|
+
class_name = class_name.to_sym if Mongo.defaults[:symbolize]
|
117
|
+
doc[class_name] = obj.class.name
|
118
|
+
|
119
|
+
doc
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def convert_doc_to_object doc
|
124
|
+
if doc.is_a? Hash
|
125
|
+
if class_name = doc[:_class] || doc['_class']
|
126
|
+
klass = constantize class_name
|
127
|
+
obj = klass.new
|
128
|
+
doc.each do |k, v|
|
129
|
+
next if k.to_sym == :_class
|
130
|
+
|
131
|
+
v = convert_doc_to_object v
|
132
|
+
obj.instance_variable_set "@#{k}", v
|
133
|
+
end
|
134
|
+
obj
|
135
|
+
else
|
136
|
+
doc
|
137
|
+
end
|
138
|
+
elsif doc.is_a? Array
|
139
|
+
doc.collect{|v| convert_doc_to_object v}
|
140
|
+
else
|
141
|
+
doc
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def constantize class_name
|
146
|
+
@constantize_cache ||= {}
|
147
|
+
unless klass = @constantize_cache[class_name]
|
148
|
+
klass = eval class_name, TOPLEVEL_BINDING, __FILE__, __LINE__
|
149
|
+
@constantize_cache[class_name] = klass
|
150
|
+
end
|
151
|
+
klass
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
data/lib/mongo_db/model.rb
CHANGED
@@ -1,4 +1,16 @@
|
|
1
1
|
require 'mongo_db/driver'
|
2
2
|
|
3
3
|
%w(
|
4
|
-
|
4
|
+
model_serializer
|
5
|
+
model_helper
|
6
|
+
).each{|f| require "mongo_db/model/#{f}"}
|
7
|
+
|
8
|
+
# collection
|
9
|
+
Mongo::Collection.class_eval do
|
10
|
+
include Mongo::Ext::ModelHelper
|
11
|
+
|
12
|
+
%w(insert update remove save).each do |method|
|
13
|
+
alias_method "#{method}_without_model", method
|
14
|
+
alias_method method, "#{method}_with_model"
|
15
|
+
end
|
16
|
+
end
|
data/lib/mongo_db/support.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# unless defined_method? :subset
|
5
5
|
# def subset *keys, &block
|
6
6
|
# keys = keys.first if keys.first.is_a? Array
|
7
|
-
# h = {}
|
7
|
+
# h = {}
|
8
8
|
# if keys
|
9
9
|
# self.each do |k, v|
|
10
10
|
# h[k] = v if keys.include? k
|
@@ -17,14 +17,14 @@
|
|
17
17
|
# h
|
18
18
|
# end
|
19
19
|
# end
|
20
|
-
#
|
20
|
+
#
|
21
21
|
# unless defined_method? :reverse_merge
|
22
22
|
# def reverse_merge(other_hash)
|
23
23
|
# other_hash.merge(self)
|
24
24
|
# end
|
25
|
-
#
|
25
|
+
#
|
26
26
|
# def reverse_merge!(other_hash)
|
27
27
|
# merge!(other_hash){|k,o,n| o }
|
28
28
|
# end
|
29
|
-
# end
|
29
|
+
# end
|
30
30
|
# end
|
data/readme.md
CHANGED
@@ -1,18 +1,20 @@
|
|
1
1
|
Object Model & Ruby driver enhancements for MongoDB.
|
2
2
|
|
3
|
+
- Driver enchancements
|
4
|
+
- Persistence for pure Ruby objects
|
5
|
+
- Migrations (work in progress)
|
6
|
+
- Object Model (callbacks, validations, mass-assignment, finders, ...) (work in progress)
|
7
|
+
|
3
8
|
# MongoDB driver enhancements
|
4
9
|
|
5
|
-
MongoDB itself is very powerful, flexible and simple tool, but it's Ruby driver
|
6
|
-
This enhancements alter
|
10
|
+
MongoDB itself is very powerful, flexible and simple tool, but it's Ruby driver has a little complicated API.
|
11
|
+
This enhancements alter this API to be more simple and intuitive.
|
7
12
|
|
8
13
|
- Makes API of mongo-ruby-driver friendly & handy.
|
9
14
|
- No extra abstraction or complexities introduced, all things are exactly the same as in MongoDB.
|
10
|
-
- Simple migrations support (work in progress).
|
11
|
-
|
12
|
-
Note: By default it also adds a little magic and alters some default values of standard driver to be more useful, but You can omit it and require only the core stuff: use *requre 'mongo_db/driver/core'* instead of *requre 'mongo_db/driver'*
|
13
15
|
|
14
16
|
``` ruby
|
15
|
-
require 'mongo_db/driver'
|
17
|
+
require 'mongo_db/driver/core'
|
16
18
|
|
17
19
|
# changing some defaults
|
18
20
|
Mongo.defaults.merge! symbolize: true, multi: true, safe: true
|
@@ -35,33 +37,92 @@ db.units.save tassadar
|
|
35
37
|
# querying - first & all, there's also :each, the same as :all
|
36
38
|
db.units.first name: 'Zeratul' # => zeratul
|
37
39
|
db.units.all name: 'Zeratul' # => [zeratul]
|
38
|
-
db.units.all name: 'Zeratul' do |
|
39
|
-
|
40
|
+
db.units.all name: 'Zeratul' do |unit|
|
41
|
+
unit # => zeratul
|
40
42
|
end
|
41
43
|
```
|
42
44
|
|
43
45
|
Optionall stuff:
|
44
46
|
|
47
|
+
- Simple query enchancements
|
48
|
+
|
45
49
|
``` ruby
|
50
|
+
require 'mongo_db/driver/more'
|
51
|
+
|
46
52
|
# simple finders (bang versions also availiable)
|
47
53
|
db.units.by_name 'Zeratul' # => zeratul
|
48
54
|
db.units.first_by_name 'Zeratul' # => zeratul
|
49
55
|
db.units.all_by_name 'Zeratul' # => [zeratul]
|
50
56
|
|
51
57
|
# query sugar, use {life: {_lt: 100}} instead of {life: {:$lt => 100}}
|
52
|
-
|
53
|
-
|
54
|
-
Mongo.defaults.merge! convert_underscore_to_dollar: true
|
55
|
-
db.units.all life: {_lt: 100} # => [tassadar]
|
56
|
-
|
57
|
-
# it's also trivial to add support for {:life.lt => 100} notion, but
|
58
|
-
# it uses ugly '=>' hash notation instead of ':' and it differs from
|
59
|
-
# how it looks in native MongoDB JSON query.
|
58
|
+
Mongo.defaults.merge! convert_underscore_to_dollar: true
|
59
|
+
db.units.all 'stats.life' => {_lt: 100} # => [tassadar]
|
60
60
|
```
|
61
61
|
|
62
|
-
More docs - there's no need for more docs, the whole point of this extension is to be small, intuitive, 100% compatible with official driver (at least should be), and require no extra knowledge.
|
62
|
+
More docs - there's no need for more docs, the whole point of this extension is to be small, intuitive, 100% compatible with the official driver (at least should be), and require no extra knowledge.
|
63
63
|
So, please use standard Ruby driver documentation.
|
64
64
|
|
65
|
+
# Persistence for pure Ruby objects
|
66
|
+
|
67
|
+
Save any Ruby object to MongoDB, as if it's hash. Object can be any type, simple or composite with other objects / arrays / hashes inside.
|
68
|
+
|
69
|
+
Note: the :initialize method should allow to create object without arguments.
|
70
|
+
|
71
|
+
``` ruby
|
72
|
+
# let's define the game unit
|
73
|
+
class Unit
|
74
|
+
attr_reader :name, :stats
|
75
|
+
|
76
|
+
# don't forget to allow creating object with no arguments
|
77
|
+
def initialize name = nil, stats = nil
|
78
|
+
@name, @stats = name, stats
|
79
|
+
end
|
80
|
+
|
81
|
+
class Stats
|
82
|
+
attr_accessor :attack, :life, :shield
|
83
|
+
|
84
|
+
def initialize attack = nil, life = nil, shield = nil
|
85
|
+
@attack, @life, @shield = attack, life, shield
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# connecting to MongoDB
|
91
|
+
require 'mongo_db/model'
|
92
|
+
Mongo.defaults.merge! symbolize: true, multi: true, safe: true
|
93
|
+
connection = Mongo::Connection.new
|
94
|
+
db = connection.db 'default_test'
|
95
|
+
|
96
|
+
# create
|
97
|
+
zeratul = Unit.new('Zeratul', Unit::Stats.new(85, 300, 100))
|
98
|
+
tassadar = Unit.new('Tassadar', Unit::Stats.new(0, 80, 300))
|
99
|
+
|
100
|
+
db.units.save zeratul
|
101
|
+
db.units.save tassadar
|
102
|
+
|
103
|
+
# udate (we made error - mistakenly set Tassadar's attack as zero, let's fix it)
|
104
|
+
tassadar.stats.attack = 20
|
105
|
+
db.units.save tassadar
|
106
|
+
|
107
|
+
# querying first & all, there's also :each, the same as :all
|
108
|
+
db.units.first name: 'Zeratul' # => zeratul
|
109
|
+
db.units.all name: 'Zeratul' # => [zeratul]
|
110
|
+
db.units.all name: 'Zeratul' do |unit|
|
111
|
+
unit # => zeratul
|
112
|
+
end
|
113
|
+
|
114
|
+
# simple finders (bang versions also availiable)
|
115
|
+
db.units.by_name 'Zeratul' # => zeratul
|
116
|
+
db.units.first_by_name 'Zeratul' # => zeratul
|
117
|
+
db.units.all_by_name 'Zeratul' # => [zeratul]
|
118
|
+
|
119
|
+
# query sugar, use {life: {_lt: 100}} instead of {life: {:$lt => 100}}
|
120
|
+
Mongo.defaults.merge! convert_underscore_to_dollar: true
|
121
|
+
db.units.all('stats.life' => {_lt: 100}) # => [tassadar]
|
122
|
+
```
|
123
|
+
|
124
|
+
# Migrations (work in progress)
|
125
|
+
|
65
126
|
# Object Model (work in progress)
|
66
127
|
|
67
128
|
Model designed after the excellent "Domain-Driven Design" book by Eric Evans.
|