mingo 0.1.3 → 0.1.5
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/mingo.rb +25 -2
- data/lib/mingo/many_proxy.rb +98 -40
- metadata +35 -81
data/lib/mingo.rb
CHANGED
@@ -2,6 +2,10 @@ require 'active_support/core_ext/hash/conversions'
|
|
2
2
|
require 'mongo'
|
3
3
|
require 'active_model'
|
4
4
|
require 'hashie/dash'
|
5
|
+
# for ObjectId:
|
6
|
+
require 'thread'
|
7
|
+
require 'socket'
|
8
|
+
require 'digest/md5'
|
5
9
|
|
6
10
|
BSON::ObjectId.class_eval do
|
7
11
|
def self.[](id)
|
@@ -11,6 +15,25 @@ BSON::ObjectId.class_eval do
|
|
11
15
|
def id
|
12
16
|
self
|
13
17
|
end
|
18
|
+
|
19
|
+
def initialize(time_or_data = nil)
|
20
|
+
if Time === time_or_data or Date === time_or_data
|
21
|
+
@data = generate_from_time(time_or_data)
|
22
|
+
else
|
23
|
+
@data = time_or_data || generate
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def generate_from_time(time)
|
30
|
+
oid = ''
|
31
|
+
oid += [time.to_i].pack("N")
|
32
|
+
oid += Digest::MD5.digest(Socket.gethostname)[0, 3]
|
33
|
+
oid += [Process.pid % 0xFFFF].pack("n")
|
34
|
+
oid += [get_inc].pack("N")[1, 3]
|
35
|
+
oid.unpack("C12")
|
36
|
+
end
|
14
37
|
end
|
15
38
|
|
16
39
|
class Mingo < Hashie::Dash
|
@@ -85,13 +108,13 @@ class Mingo < Hashie::Dash
|
|
85
108
|
end
|
86
109
|
end
|
87
110
|
|
88
|
-
def many(property,
|
111
|
+
def many(property, *args, &block)
|
89
112
|
proxy_class = block_given?? Class.new(ManyProxy, &block) : ManyProxy
|
90
113
|
ivar = "@#{property}"
|
91
114
|
|
92
115
|
define_method(property) {
|
93
116
|
(instance_variable_defined?(ivar) && instance_variable_get(ivar)) ||
|
94
|
-
instance_variable_set(ivar, proxy_class.new(self, property,
|
117
|
+
instance_variable_set(ivar, proxy_class.new(self, property, *args))
|
95
118
|
}
|
96
119
|
end
|
97
120
|
end
|
data/lib/mingo/many_proxy.rb
CHANGED
@@ -16,65 +16,63 @@ class Mingo
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
def initialize(parent, property,
|
19
|
+
def initialize(parent, property, mapping)
|
20
20
|
@parent = parent
|
21
21
|
@property = property
|
22
|
-
|
23
|
-
@
|
24
|
-
@
|
25
|
-
@
|
26
|
-
|
27
|
-
|
28
|
-
def find_options
|
29
|
-
@find_options ||= begin
|
30
|
-
decorator = self.class.decorate_with
|
31
|
-
decorate_block = self.class.decorate_each
|
32
|
-
|
33
|
-
if decorator or decorate_block
|
34
|
-
{:convert => lambda { |doc|
|
35
|
-
@model.new(doc).tap do |obj|
|
36
|
-
obj.extend decorator if decorator
|
37
|
-
decorate_block.call(obj, @embedded) if decorate_block
|
38
|
-
end
|
39
|
-
}}
|
40
|
-
else
|
41
|
-
{}
|
42
|
-
end
|
43
|
-
end
|
22
|
+
# TODO: ugh, improve naming
|
23
|
+
@model, @self_referencing_key, @forward_referencing_key = analyze_mapping mapping
|
24
|
+
@counter_cache_field = "#{@property}_count"
|
25
|
+
@join_loaded = nil
|
26
|
+
@loaded = nil
|
44
27
|
end
|
45
28
|
|
46
29
|
undef :inspect
|
47
30
|
undef :to_a if instance_methods.include? 'to_a'
|
48
31
|
|
49
32
|
def object_ids
|
50
|
-
|
33
|
+
join_docs = load_join
|
34
|
+
join_docs = join_docs.select(&Proc.new) if block_given?
|
35
|
+
join_docs.map { |doc| doc[@forward_referencing_key] }
|
36
|
+
end
|
37
|
+
|
38
|
+
def size
|
39
|
+
(counter_cache? && counter_cache) || (@join_loaded && @join_loaded.size) || join_cursor.count
|
51
40
|
end
|
52
41
|
|
53
42
|
def include?(doc)
|
54
|
-
|
43
|
+
!!find_join_doc(doc.id)
|
55
44
|
end
|
56
45
|
|
57
46
|
def convert(doc)
|
58
|
-
doc.id
|
47
|
+
{@self_referencing_key => @parent.id, @forward_referencing_key => doc.id}
|
59
48
|
end
|
60
49
|
|
61
50
|
def <<(doc)
|
62
51
|
doc = convert(doc)
|
63
|
-
|
52
|
+
doc['_id'] = join_collection.save doc
|
53
|
+
change_counter_cache(1)
|
54
|
+
load_join << doc if @join_loaded
|
64
55
|
unload_collection
|
65
|
-
@embedded << doc
|
66
56
|
self
|
67
57
|
end
|
68
58
|
|
69
59
|
def delete(doc)
|
70
60
|
doc = convert(doc)
|
71
|
-
|
72
|
-
|
73
|
-
|
61
|
+
if join_doc = find_join_doc(doc[@forward_referencing_key])
|
62
|
+
join_collection.remove :_id => join_doc['_id']
|
63
|
+
change_counter_cache(-1)
|
64
|
+
unload_collection
|
65
|
+
@join_loaded.delete join_doc
|
66
|
+
end
|
67
|
+
doc
|
74
68
|
end
|
75
69
|
|
76
70
|
def loaded?
|
77
|
-
!!@
|
71
|
+
!!@loaded
|
72
|
+
end
|
73
|
+
|
74
|
+
def find_by_ids(ids)
|
75
|
+
@model.find_by_ids(ids, {}, find_options)
|
78
76
|
end
|
79
77
|
|
80
78
|
def respond_to?(method, priv = false)
|
@@ -85,21 +83,81 @@ class Mingo
|
|
85
83
|
|
86
84
|
def method_missing(method, *args, &block)
|
87
85
|
load_collection
|
88
|
-
@
|
86
|
+
@loaded.send(method, *args, &block)
|
89
87
|
end
|
90
|
-
|
91
|
-
def
|
92
|
-
@
|
88
|
+
|
89
|
+
def join_collection
|
90
|
+
@join_collection ||= @parent.class.collection[@property.to_s]
|
91
|
+
end
|
92
|
+
|
93
|
+
def counter_cache
|
94
|
+
@counter_cache ||= @parent[@counter_cache_field].to_i
|
95
|
+
end
|
96
|
+
|
97
|
+
def counter_cache?
|
98
|
+
!!@parent[@counter_cache_field]
|
99
|
+
end
|
100
|
+
|
101
|
+
def change_counter_cache(by)
|
102
|
+
@counter_cache = counter_cache + by
|
103
|
+
@parent.update '$inc' => { @counter_cache_field => by }
|
104
|
+
end
|
105
|
+
|
106
|
+
# Example: {self => 'user_id', 'movie_id' => Movie}
|
107
|
+
def analyze_mapping(mapping)
|
108
|
+
model = self_referencing_key = forward_referencing_key = nil
|
109
|
+
mapping.each do |key, value|
|
110
|
+
if key == @parent.class then self_referencing_key = value.to_s
|
111
|
+
elsif value < Mingo
|
112
|
+
forward_referencing_key = key.to_s
|
113
|
+
model = value
|
114
|
+
end
|
115
|
+
end
|
116
|
+
[model, self_referencing_key, forward_referencing_key]
|
117
|
+
end
|
118
|
+
|
119
|
+
def find_options
|
120
|
+
@find_options ||= begin
|
121
|
+
decorator = self.class.decorate_with
|
122
|
+
decorate_block = self.class.decorate_each
|
123
|
+
|
124
|
+
if decorator or decorate_block
|
125
|
+
{:convert => lambda { |doc|
|
126
|
+
@model.new(doc).tap do |obj|
|
127
|
+
obj.extend decorator if decorator
|
128
|
+
if decorate_block
|
129
|
+
join_doc = find_join_doc(doc['_id'])
|
130
|
+
decorate_block.call(obj, join_doc)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
}}
|
134
|
+
else
|
135
|
+
{}
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def load_join
|
141
|
+
@join_loaded ||= join_cursor.to_a
|
142
|
+
end
|
143
|
+
|
144
|
+
def find_join_doc(forward_id)
|
145
|
+
load_join.find { |d| d[@forward_referencing_key] == forward_id }
|
146
|
+
end
|
147
|
+
|
148
|
+
def join_cursor
|
149
|
+
# TODO: make options configurable
|
150
|
+
join_collection.find({@self_referencing_key => @parent.id}, :sort => '_id')
|
93
151
|
end
|
94
152
|
|
95
153
|
def load_collection
|
96
|
-
@
|
154
|
+
@loaded ||= if self.object_ids.empty? then []
|
97
155
|
else find_by_ids(self.object_ids)
|
98
156
|
end
|
99
157
|
end
|
100
|
-
|
101
|
-
def
|
102
|
-
@
|
158
|
+
|
159
|
+
def unload_collection
|
160
|
+
@loaded = nil
|
103
161
|
end
|
104
162
|
end
|
105
163
|
end
|
metadata
CHANGED
@@ -1,81 +1,45 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: mingo
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 1
|
9
|
-
- 3
|
10
|
-
version: 0.1.3
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.5
|
5
|
+
prerelease:
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
13
|
-
-
|
7
|
+
authors:
|
8
|
+
- Mislav Marohnić
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
date: 2010-10-23 00:00:00 +02:00
|
12
|
+
date: 2011-03-07 00:00:00.000000000 +01:00
|
19
13
|
default_executable:
|
20
|
-
dependencies:
|
21
|
-
- !ruby/object:Gem::Dependency
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
22
16
|
name: mongo
|
23
|
-
|
24
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
17
|
+
requirement: &2157373800 !ruby/object:Gem::Requirement
|
25
18
|
none: false
|
26
|
-
requirements:
|
27
|
-
- -
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
|
30
|
-
segments:
|
31
|
-
- 1
|
32
|
-
- 0
|
33
|
-
version: "1.0"
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '1.0'
|
34
23
|
type: :runtime
|
35
|
-
version_requirements: *id001
|
36
|
-
- !ruby/object:Gem::Dependency
|
37
|
-
name: hashie
|
38
24
|
prerelease: false
|
39
|
-
|
25
|
+
version_requirements: *2157373800
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: hashie
|
28
|
+
requirement: &2157373320 !ruby/object:Gem::Requirement
|
40
29
|
none: false
|
41
|
-
requirements:
|
42
|
-
- -
|
43
|
-
- !ruby/object:Gem::Version
|
44
|
-
hash: 15
|
45
|
-
segments:
|
46
|
-
- 0
|
47
|
-
- 4
|
48
|
-
- 0
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
49
33
|
version: 0.4.0
|
50
34
|
type: :runtime
|
51
|
-
version_requirements: *id002
|
52
|
-
- !ruby/object:Gem::Dependency
|
53
|
-
name: rspec
|
54
35
|
prerelease: false
|
55
|
-
|
56
|
-
none: false
|
57
|
-
requirements:
|
58
|
-
- - ~>
|
59
|
-
- !ruby/object:Gem::Version
|
60
|
-
hash: 62196427
|
61
|
-
segments:
|
62
|
-
- 2
|
63
|
-
- 0
|
64
|
-
- 0
|
65
|
-
- beta
|
66
|
-
- 20
|
67
|
-
version: 2.0.0.beta.20
|
68
|
-
type: :development
|
69
|
-
version_requirements: *id003
|
36
|
+
version_requirements: *2157373320
|
70
37
|
description: Mingo is a minimal document-object mapper for MongoDB.
|
71
38
|
email: mislav.marohnic@gmail.com
|
72
39
|
executables: []
|
73
|
-
|
74
40
|
extensions: []
|
75
|
-
|
76
41
|
extra_rdoc_files: []
|
77
|
-
|
78
|
-
files:
|
42
|
+
files:
|
79
43
|
- Rakefile
|
80
44
|
- lib/mingo/cursor.rb
|
81
45
|
- lib/mingo/many_proxy.rb
|
@@ -83,36 +47,26 @@ files:
|
|
83
47
|
has_rdoc: false
|
84
48
|
homepage: http://github.com/mislav/mingo
|
85
49
|
licenses: []
|
86
|
-
|
87
50
|
post_install_message:
|
88
51
|
rdoc_options: []
|
89
|
-
|
90
|
-
require_paths:
|
52
|
+
require_paths:
|
91
53
|
- lib
|
92
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
93
55
|
none: false
|
94
|
-
requirements:
|
95
|
-
- -
|
96
|
-
- !ruby/object:Gem::Version
|
97
|
-
|
98
|
-
|
99
|
-
- 0
|
100
|
-
version: "0"
|
101
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ! '>='
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
61
|
none: false
|
103
|
-
requirements:
|
104
|
-
- -
|
105
|
-
- !ruby/object:Gem::Version
|
106
|
-
|
107
|
-
segments:
|
108
|
-
- 0
|
109
|
-
version: "0"
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
110
66
|
requirements: []
|
111
|
-
|
112
67
|
rubyforge_project:
|
113
|
-
rubygems_version: 1.3
|
68
|
+
rubygems_version: 1.5.3
|
114
69
|
signing_key:
|
115
70
|
specification_version: 3
|
116
71
|
summary: Minimal Mongo
|
117
72
|
test_files: []
|
118
|
-
|