mongo_db 0.1.5 → 0.1.6
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/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.
|