mongo_collection 0.0.4
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/lib/mongo_collection.rb +479 -0
- metadata +44 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8d57196d59c0c6e82eda6db662c906704be9f887
|
4
|
+
data.tar.gz: 5a06d4350e25e36549f5670c86d8d0e7915f7ded
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 95c2734d9832225cd8b3de686b72305ebfb9871fa62a2dd5a168091962c2badea0571a90ca953a3ab1ea60ff89849d41e1f4c8513b9faf95e01188712cc5d404
|
7
|
+
data.tar.gz: 27490be6d563224211e94b1242d692949856dc35c2b71b80510f9f72bb726893583fe4ccd70e26e827f8d48bed89f67d8066cfe2656f62b71bc408db783af1d9
|
@@ -0,0 +1,479 @@
|
|
1
|
+
module MongoCollection
|
2
|
+
def self.included base
|
3
|
+
base.extend ClassMethods
|
4
|
+
end
|
5
|
+
class MongoCollectionProxy
|
6
|
+
def initialize(collection, klass)
|
7
|
+
@class = klass
|
8
|
+
@target = collection
|
9
|
+
end
|
10
|
+
|
11
|
+
def method_missing(method, *args, &block)
|
12
|
+
result = @target.send(method, *args, &block)
|
13
|
+
if result.is_a?(BSON::Document)
|
14
|
+
return @class.from_bson(result)
|
15
|
+
elsif result.is_a?(Fixnum)
|
16
|
+
return result
|
17
|
+
elsif result.is_a?(Array)
|
18
|
+
return result.map{|bson| @class.from_bson(bson)}
|
19
|
+
elsif result.is_a?(TrueClass) || result.is_a?(FalseClass)
|
20
|
+
return result
|
21
|
+
end
|
22
|
+
@target = result
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
def all
|
27
|
+
self.to_a
|
28
|
+
end
|
29
|
+
|
30
|
+
def sort_by(&block)
|
31
|
+
self.to_a.sort_by(&block)
|
32
|
+
end
|
33
|
+
|
34
|
+
def map(&block)
|
35
|
+
self.to_a.map(&block)
|
36
|
+
end
|
37
|
+
|
38
|
+
def each_cursor
|
39
|
+
@target.each
|
40
|
+
end
|
41
|
+
|
42
|
+
def each(&block)
|
43
|
+
self.to_a.each(&block)
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_h
|
47
|
+
self.map{|x| x.to_h}
|
48
|
+
end
|
49
|
+
|
50
|
+
def blank?
|
51
|
+
self.to_a.blank?
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
module InstanceMethods
|
57
|
+
def initialize(args=nil)
|
58
|
+
self.class.defaults.each do |k, v|
|
59
|
+
self.send(k.to_s+"=", v)
|
60
|
+
end
|
61
|
+
if !args.is_a?(Hash)
|
62
|
+
return
|
63
|
+
end
|
64
|
+
args.each do |k,v|
|
65
|
+
if v == nil
|
66
|
+
next
|
67
|
+
end
|
68
|
+
k_sym = k.to_sym
|
69
|
+
k_str = k.to_s
|
70
|
+
new_val = v
|
71
|
+
|
72
|
+
if self.class.has_one_assosiations.has_key?(k_sym)
|
73
|
+
klass = self.class.has_one_assosiations[k_sym].constantize
|
74
|
+
if v.is_a?(Hash)
|
75
|
+
new_val = klass.new(v)
|
76
|
+
elsif !v.is_a?(klass)
|
77
|
+
raise "Value should be a hash or #{klass.to_s}"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
if self.class.has_many_assosiations.has_key?(k_sym)
|
81
|
+
klass = self.class.has_many_assosiations[k_sym].constantize
|
82
|
+
if !v.is_a?(Array)
|
83
|
+
raise "Has many assosiations should be in form of Array"
|
84
|
+
end
|
85
|
+
|
86
|
+
new_val = v.map do |obj|
|
87
|
+
new_obj = obj
|
88
|
+
if obj.is_a?(Hash)
|
89
|
+
new_obj = klass.new(obj)
|
90
|
+
elsif !obj.is_a?(klass)
|
91
|
+
raise "Value should be a hash or #{klass.to_s}"
|
92
|
+
end
|
93
|
+
new_obj
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
instance_variable_set "@#{k_str}", new_val if self.class.props.member?(k_sym)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def new?
|
102
|
+
if self._id.blank?
|
103
|
+
return true
|
104
|
+
end
|
105
|
+
!BSON::ObjectId.legal?(self._id)
|
106
|
+
end
|
107
|
+
|
108
|
+
def destroy
|
109
|
+
if self.new?
|
110
|
+
return false
|
111
|
+
end
|
112
|
+
r = self.class.collection.delete_one(_id: BSON::ObjectId(self._id))
|
113
|
+
if !self.class.after_destroy_block.nil?
|
114
|
+
self.class.after_destroy_block.call(self)
|
115
|
+
end
|
116
|
+
r
|
117
|
+
end
|
118
|
+
|
119
|
+
def save
|
120
|
+
|
121
|
+
if !self.class.before_save_block.nil?
|
122
|
+
self.class.before_save_block.call(self)
|
123
|
+
end
|
124
|
+
|
125
|
+
self.class.has_one_assosiations.each do |k,v|
|
126
|
+
val = self.send(k)
|
127
|
+
if !val
|
128
|
+
next
|
129
|
+
end
|
130
|
+
if val.new?
|
131
|
+
if !val.save
|
132
|
+
raise "Unable to save assosiation #{v}"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
self.class.has_many_assosiations.each do |k,v|
|
138
|
+
val = self.send(k)
|
139
|
+
if !val
|
140
|
+
next
|
141
|
+
end
|
142
|
+
val.each do |obj|
|
143
|
+
if obj.new? && !obj.save
|
144
|
+
raise "Unable to save assosiation #{v}"
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
if self.new?
|
150
|
+
self._id = nil
|
151
|
+
result = DB[self.class.mongo_collection]
|
152
|
+
.insert_one(self.class.to_bson(self))
|
153
|
+
if result.ok?
|
154
|
+
self._id = result.inserted_id.to_s
|
155
|
+
end
|
156
|
+
ok = result.ok?
|
157
|
+
else
|
158
|
+
ok = DB[self.class.mongo_collection]
|
159
|
+
.update_one({_id: BSON::ObjectId(self._id)}, self.class.to_bson(self))
|
160
|
+
.ok?
|
161
|
+
end
|
162
|
+
if ok && !self.class.after_save_block.nil?
|
163
|
+
self.class.after_save_block.call(self)
|
164
|
+
end
|
165
|
+
ok
|
166
|
+
end
|
167
|
+
|
168
|
+
def to_h
|
169
|
+
result = {}
|
170
|
+
|
171
|
+
self.class.props.each do |prop|
|
172
|
+
value = self.send(prop)
|
173
|
+
if value.nil?
|
174
|
+
next
|
175
|
+
end
|
176
|
+
|
177
|
+
if self.class.has_one_assosiations.has_key?(prop)
|
178
|
+
value = value.to_h
|
179
|
+
end
|
180
|
+
|
181
|
+
if self.class.has_many_assosiations.has_key?(prop)
|
182
|
+
value = value.map{|x| x.to_h}
|
183
|
+
end
|
184
|
+
result[prop] = value
|
185
|
+
end
|
186
|
+
return result
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
module ClassMethods
|
191
|
+
attr_accessor :mongo_collection
|
192
|
+
attr_accessor :props
|
193
|
+
attr_accessor :simple_props
|
194
|
+
attr_accessor :has_one_assosiations
|
195
|
+
attr_accessor :has_many_assosiations
|
196
|
+
attr_accessor :before_save_block
|
197
|
+
attr_accessor :after_save_block
|
198
|
+
attr_accessor :after_destroy_block
|
199
|
+
attr_accessor :references_one_assosiations, :references_many_assosiations
|
200
|
+
attr_accessor :referenced_one_assosiations, :referenced_many_assosiations
|
201
|
+
attr_accessor :defaults
|
202
|
+
|
203
|
+
def has_mongo_collection (*args)
|
204
|
+
|
205
|
+
class_eval <<-EOV
|
206
|
+
include MongoCollection::InstanceMethods
|
207
|
+
EOV
|
208
|
+
|
209
|
+
collection = args[0]
|
210
|
+
properties = args[1..-1]
|
211
|
+
|
212
|
+
@props = [:_id] + properties
|
213
|
+
|
214
|
+
@simple_props = @props.clone
|
215
|
+
@has_one_assosiations = {}
|
216
|
+
@has_many_assosiations = {}
|
217
|
+
@references_one_assosiations = {}
|
218
|
+
@references_many_assosiations = {}
|
219
|
+
@referenced_one_assosiations = {}
|
220
|
+
@referenced_many_assosiations = {}
|
221
|
+
@before_save_block = nil
|
222
|
+
@after_save_block = nil
|
223
|
+
@after_destroy_block = nil
|
224
|
+
@defaults = {}
|
225
|
+
instance_eval { attr_accessor *@props }
|
226
|
+
|
227
|
+
@mongo_collection = collection
|
228
|
+
|
229
|
+
def find_by_id(id)
|
230
|
+
if id.is_a?(String)
|
231
|
+
id = BSON::ObjectId(id)
|
232
|
+
end
|
233
|
+
|
234
|
+
bson = DB[mongo_collection].find(_id: id).limit(1).first
|
235
|
+
|
236
|
+
if !bson
|
237
|
+
return nil
|
238
|
+
end
|
239
|
+
|
240
|
+
self.from_bson(bson)
|
241
|
+
end
|
242
|
+
|
243
|
+
def before_save(&block)
|
244
|
+
@before_save_block = block
|
245
|
+
end
|
246
|
+
|
247
|
+
def after_save(&block)
|
248
|
+
@after_save_block = block
|
249
|
+
end
|
250
|
+
|
251
|
+
def after_destroy(&block)
|
252
|
+
@after_destroy = block
|
253
|
+
end
|
254
|
+
|
255
|
+
def count(*args)
|
256
|
+
self.collection.count(*args)
|
257
|
+
end
|
258
|
+
def all
|
259
|
+
self.collection.find().all
|
260
|
+
end
|
261
|
+
|
262
|
+
def first
|
263
|
+
self.collection.find().first
|
264
|
+
end
|
265
|
+
|
266
|
+
def find_all(limit=nil, sort=nil, direction=1)
|
267
|
+
req = DB[self.mongo_collection].find()
|
268
|
+
if sort
|
269
|
+
req = req.sort({sort.to_sym => direction})
|
270
|
+
end
|
271
|
+
if limit
|
272
|
+
req = req.limit(limit)
|
273
|
+
end
|
274
|
+
req.map{|bson| self.from_bson(bson)}
|
275
|
+
end
|
276
|
+
|
277
|
+
def find_all_by_children_ids(fields={})
|
278
|
+
query = Hash[fields.map{|k,_| [k.to_s+"._id",_]}]
|
279
|
+
self.collection.find(query).all
|
280
|
+
end
|
281
|
+
|
282
|
+
def find_one_by_children_ids(fields={})
|
283
|
+
query = Hash[fields.map{|k,_| [k.to_s+"._id",_]}]
|
284
|
+
self.collection.find(query).first
|
285
|
+
end
|
286
|
+
|
287
|
+
def count_all_by_children_ids(fields={})
|
288
|
+
query = Hash[fields.map{|k,_| [k.to_s+"._id",_]}]
|
289
|
+
self.collection.find(query).count
|
290
|
+
end
|
291
|
+
|
292
|
+
def find_or_create_by_name(name)
|
293
|
+
existing_obj = self.find_by_name(name)
|
294
|
+
if existing_obj
|
295
|
+
return existing_obj
|
296
|
+
end
|
297
|
+
new_obj = self.new(name: name)
|
298
|
+
new_obj.save
|
299
|
+
new_obj
|
300
|
+
end
|
301
|
+
|
302
|
+
def collection
|
303
|
+
MongoCollectionProxy.new(DB[self.mongo_collection], self)
|
304
|
+
end
|
305
|
+
|
306
|
+
def db(&block)
|
307
|
+
collection = DB[self.mongo_collection]
|
308
|
+
result = block.call(collection)
|
309
|
+
if result.is_a?(Array) || result.is_a?(Mongo::Collection::View)
|
310
|
+
return result.map{|bson| self.from_bson(bson)}
|
311
|
+
end
|
312
|
+
|
313
|
+
if result.is_a?(Fixnum)
|
314
|
+
return result
|
315
|
+
end
|
316
|
+
return self.from_bson(result)
|
317
|
+
end
|
318
|
+
|
319
|
+
properties.each do |property|
|
320
|
+
method = "find_by_" + property.to_s
|
321
|
+
metaclass.send(:define_method, method) do |query|
|
322
|
+
bson = DB[self.mongo_collection].find({property.to_sym => query}).limit(1).first
|
323
|
+
if bson
|
324
|
+
return self.from_bson(bson)
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
|
330
|
+
end
|
331
|
+
|
332
|
+
def has_one(*args)
|
333
|
+
assosiation, class_name = args
|
334
|
+
@props << assosiation
|
335
|
+
class_name ||= assosiation.to_s.camelize
|
336
|
+
self.has_one_assosiations[assosiation.to_sym] = class_name
|
337
|
+
instance_eval { attr_accessor assosiation}
|
338
|
+
end
|
339
|
+
|
340
|
+
def has_many(*args)
|
341
|
+
assosiation, class_name = args
|
342
|
+
@props << assosiation
|
343
|
+
class_name ||= assosiation.to_s.sub(/s$/, "").camelize
|
344
|
+
self.has_many_assosiations[assosiation.to_sym] = class_name
|
345
|
+
instance_eval { attr_accessor assosiation}
|
346
|
+
end
|
347
|
+
|
348
|
+
# def references_one(*args)
|
349
|
+
# assosiation, class_name = args
|
350
|
+
# if assosiation.blank? || class_name.blank?
|
351
|
+
# raise "references_one: should have both assosiation and class_name"
|
352
|
+
# end
|
353
|
+
# self.references_one_assosiations[assosiation.to_sym] = class_name
|
354
|
+
# assosiation_id = assosiation.to_s + "_id"
|
355
|
+
# @props << assosiation_id.to_sym
|
356
|
+
|
357
|
+
# child_id_accessor = assosiation.to_s + "_" + class_name.downcase + "_id"
|
358
|
+
|
359
|
+
# instance_eval do
|
360
|
+
# attr_accessor assosiation_id.to_sym
|
361
|
+
|
362
|
+
# define_method(assosiation) do
|
363
|
+
# id = self.send(assosiation_id)
|
364
|
+
# if id.nil?
|
365
|
+
# return nil
|
366
|
+
# end
|
367
|
+
|
368
|
+
# result = instance_variable_get("@" + assosiation.to_s)
|
369
|
+
# if result
|
370
|
+
# return result
|
371
|
+
# end
|
372
|
+
# result = class_name.constantize.find_by_id(id)
|
373
|
+
# instance_variable_set("@" + assosiation.to_s, result)
|
374
|
+
# return result
|
375
|
+
# end
|
376
|
+
|
377
|
+
# define_method((assosiation.to_s+"=").to_sym) do |ref_obj|
|
378
|
+
# klass = class_name.constantize
|
379
|
+
# current_id = self.send(assosiation_id)
|
380
|
+
# if ref_obj.nil?
|
381
|
+
# if current_id
|
382
|
+
# child = klass.find_by_id(current_id)
|
383
|
+
# if child
|
384
|
+
# child.send(child_id_accessor + "=", nil)
|
385
|
+
# child.save
|
386
|
+
# end
|
387
|
+
# end
|
388
|
+
# instance_variable_set('@' + assosiation_id, nil)
|
389
|
+
# return
|
390
|
+
# end
|
391
|
+
# if ref_obj.kind_of?(klass) == false
|
392
|
+
# raise "Referenced object shoud be kind_of #{klass}"
|
393
|
+
# end
|
394
|
+
# if ref_obj.new?
|
395
|
+
# raise "Unable to reference not_saved object"
|
396
|
+
# end
|
397
|
+
# if current_id
|
398
|
+
|
399
|
+
# else
|
400
|
+
# instance_variable_set("@" + assosiation.to_s, ref_obj)
|
401
|
+
# end
|
402
|
+
# if ref_obj._id == current_id
|
403
|
+
# return
|
404
|
+
# else
|
405
|
+
|
406
|
+
# end
|
407
|
+
|
408
|
+
|
409
|
+
# instance_variable_set("@" + assosiation.to_s, ref_obj)
|
410
|
+
# end
|
411
|
+
# end
|
412
|
+
# end
|
413
|
+
|
414
|
+
# def referenced_one(*args)
|
415
|
+
# class_name, reference_assoisation = args
|
416
|
+
# if reference_assoisation.blank? || class_name.blank?
|
417
|
+
# raise "referenced_one: should have both reference_assoisation and class_name"
|
418
|
+
# end
|
419
|
+
# self.referenced_one_assosiations[reference_assoisation.to_sym] = class_name
|
420
|
+
|
421
|
+
|
422
|
+
# parent_accessor = reference_assoisation.to_s + '_' + class_name.downcase
|
423
|
+
# parent_id = parent_accessor+ "_id"
|
424
|
+
# @props << parent_id.to_sym
|
425
|
+
|
426
|
+
# instance_eval do
|
427
|
+
# attr_accessor parent_id.to_sym
|
428
|
+
# define_method(parent_accessor.to_sym) do
|
429
|
+
# id = self.send(parent_id.to_sym)
|
430
|
+
# if id.nil?
|
431
|
+
# return nil
|
432
|
+
# end
|
433
|
+
# result = instance_variable_get("@" + parent_accessor.to_s)
|
434
|
+
# if result
|
435
|
+
# return result
|
436
|
+
# end
|
437
|
+
# result = class_name.constantize.find_by_id(id)
|
438
|
+
# instance_variable_set("@" + parent_accessor.to_s, result)
|
439
|
+
# result
|
440
|
+
# end
|
441
|
+
# define_method((parent_accessor + '=').to_sym) do |parent_obj|
|
442
|
+
# if parent_obj.new? || self.new?
|
443
|
+
# raise "Unable to reference not saved objects"
|
444
|
+
# end
|
445
|
+
# current_reference_id = self.send(parent_id)
|
446
|
+
# if current_reference_id
|
447
|
+
# self.send()
|
448
|
+
# end
|
449
|
+
# end
|
450
|
+
# define_method("unref_"+parent_accessor) do
|
451
|
+
# if self.new?
|
452
|
+
# raise "Unable to unref new object"
|
453
|
+
# end
|
454
|
+
# if self.send(parent_id)
|
455
|
+
# self.send(parent_id+"=", nil)
|
456
|
+
# self.save
|
457
|
+
# end
|
458
|
+
# end
|
459
|
+
# end
|
460
|
+
|
461
|
+
# end
|
462
|
+
|
463
|
+
def from_bson(bson)
|
464
|
+
bson["_id"] = bson["_id"].to_s
|
465
|
+
return self.new(bson.to_h)
|
466
|
+
end
|
467
|
+
|
468
|
+
def to_bson(item)
|
469
|
+
bson = item.to_h
|
470
|
+
if !bson[:_id].blank?
|
471
|
+
bson[:_id] = BSON::ObjectId(item._id)
|
472
|
+
end
|
473
|
+
bson
|
474
|
+
end
|
475
|
+
def has_defaults(d)
|
476
|
+
@defaults = d
|
477
|
+
end
|
478
|
+
end
|
479
|
+
end
|
metadata
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mongo_collection
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Pavel Malay
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-12-01 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: A simple ORM for mongodb
|
14
|
+
email: flagmansupport@gmail.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- lib/mongo_collection.rb
|
20
|
+
homepage: ''
|
21
|
+
licenses:
|
22
|
+
- MIT
|
23
|
+
metadata: {}
|
24
|
+
post_install_message:
|
25
|
+
rdoc_options: []
|
26
|
+
require_paths:
|
27
|
+
- lib
|
28
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
34
|
+
requirements:
|
35
|
+
- - ">="
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
requirements: []
|
39
|
+
rubyforge_project:
|
40
|
+
rubygems_version: 2.6.13
|
41
|
+
signing_key:
|
42
|
+
specification_version: 4
|
43
|
+
summary: Mongo Collection
|
44
|
+
test_files: []
|