mongo_collection 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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: []