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.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/mongo_collection.rb +479 -0
  3. 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: []