uorm 0.0.10 → 0.0.11
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/Gemfile.lock +10 -17
- data/lib/uorm.rb +20 -17
- data/lib/uorm/attributes.rb +4 -3
- data/lib/uorm/attributes/field.rb +30 -0
- data/lib/uorm/attributes/field_collection.rb +9 -0
- data/lib/uorm/attributes/type.rb +68 -0
- data/lib/uorm/crud.rb +72 -0
- data/lib/uorm/crud/callbacks.rb +13 -0
- data/lib/uorm/crud/persistance_helper.rb +21 -0
- data/lib/uorm/hash.rb +13 -0
- data/lib/uorm/model.rb +2 -2
- data/lib/uorm/mongo.rb +3 -13
- data/lib/uorm/mongo/object_id.rb +10 -8
- data/lib/uorm/mongo/persistance.rb +30 -26
- data/lib/uorm/redis.rb +5 -14
- data/lib/uorm/redis/adapter.rb +8 -0
- data/lib/uorm/redis/persistance.rb +6 -16
- data/spec/mongo_spec.rb +258 -0
- data/spec/redis_spec.rb +161 -0
- data/spec/spec_helper.rb +9 -21
- data/spec/support/test_persistance.rb +51 -0
- data/uorm.gemspec +4 -6
- metadata +25 -33
- data/lib/uorm/callbacks.rb +0 -11
- data/lib/uorm/dsl.rb +0 -51
- data/lib/uorm/field.rb +0 -13
- data/lib/uorm/field_collection.rb +0 -7
- data/lib/uorm/mongo/db.rb +0 -27
- data/lib/uorm/redis/db.rb +0 -19
- data/lib/uorm/type.rb +0 -65
- data/lib/uorm/version.rb +0 -3
- data/spec/em-mongo_spec.rb +0 -176
- data/spec/redis_synchrony_spec.rb +0 -117
data/lib/uorm/redis.rb
CHANGED
@@ -1,26 +1,17 @@
|
|
1
|
+
require 'redis'
|
2
|
+
require 'hiredis'
|
3
|
+
|
1
4
|
module Uorm
|
2
5
|
module Redis
|
3
6
|
def self.included base
|
4
7
|
base.instance_eval do
|
5
|
-
field :id, type:
|
6
|
-
|
7
|
-
def persistance
|
8
|
-
@persistance ||= Persistance.new self
|
9
|
-
end
|
10
|
-
|
11
|
-
def collection
|
12
|
-
persistance.collection
|
13
|
-
end
|
8
|
+
field :id, type: :String
|
14
9
|
end
|
15
10
|
|
16
11
|
def initialize values = {}
|
17
|
-
values[:id] ||= values['id']
|
12
|
+
values[:id] ||= values['id']
|
18
13
|
super values
|
19
14
|
end
|
20
|
-
|
21
|
-
def persistance
|
22
|
-
self.class.persistance
|
23
|
-
end
|
24
15
|
end
|
25
16
|
end
|
26
17
|
end
|
@@ -1,29 +1,19 @@
|
|
1
1
|
module Uorm
|
2
2
|
module Redis
|
3
|
-
class Persistance
|
4
|
-
attr_reader :collection, :model
|
5
|
-
|
6
|
-
def initialize model
|
7
|
-
@model = model
|
8
|
-
@collection = DB.client
|
9
|
-
end
|
10
|
-
|
11
|
-
def new? object
|
12
|
-
object.id ? false : true
|
13
|
-
end
|
3
|
+
class Persistance < Struct.new :model, :client
|
14
4
|
|
15
5
|
def all options = {}
|
16
|
-
ids =
|
6
|
+
ids = client.keys
|
17
7
|
return [] if ids.empty?
|
18
8
|
ids.map { |id| find id }
|
19
9
|
end
|
20
10
|
|
21
11
|
def find id
|
22
|
-
|
12
|
+
client.mapped_hmget id, *model.fields.map(&:name)
|
23
13
|
end
|
24
14
|
|
25
15
|
def create object
|
26
|
-
object.id = SecureRandom.uuid
|
16
|
+
object.id = ::SecureRandom.uuid
|
27
17
|
write object
|
28
18
|
end
|
29
19
|
|
@@ -32,13 +22,13 @@ module Uorm
|
|
32
22
|
end
|
33
23
|
|
34
24
|
def delete object
|
35
|
-
|
25
|
+
client.del object.id
|
36
26
|
end
|
37
27
|
|
38
28
|
private
|
39
29
|
|
40
30
|
def write object
|
41
|
-
|
31
|
+
client.mapped_hmset object.id, object.attributes
|
42
32
|
end
|
43
33
|
end
|
44
34
|
end
|
data/spec/mongo_spec.rb
ADDED
@@ -0,0 +1,258 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
|
4
|
+
class AMongoModel
|
5
|
+
include Uorm::Model
|
6
|
+
include Uorm::Mongo
|
7
|
+
|
8
|
+
field :reference, type: :ObjectId
|
9
|
+
field :name, type: :String
|
10
|
+
field :count, type: :Integer
|
11
|
+
field :dollars, type: :Float
|
12
|
+
field :favorite, type: :Boolean
|
13
|
+
field :created, type: :Time
|
14
|
+
end
|
15
|
+
|
16
|
+
describe AMongoModel do
|
17
|
+
|
18
|
+
let!(:attributes) do
|
19
|
+
{
|
20
|
+
reference: '50995b8c15529d4676000001',
|
21
|
+
name: 'whatever',
|
22
|
+
count: 5.to_s,
|
23
|
+
dollars: 2.3.to_s,
|
24
|
+
favorite: true.to_s,
|
25
|
+
created: Time.utc(0).to_s
|
26
|
+
}
|
27
|
+
end
|
28
|
+
let(:collection) { EM::Mongo::Collection.new('uorm', 'test').tap(&:remove) }
|
29
|
+
let(:persistance) { AMongoModel.persistance = Uorm::Mongo::Persistance.new AMongoModel, collection }
|
30
|
+
let(:test_persistance) { AMongoModel.persistance = Uorm::Mongo::TestPerstistance.new }
|
31
|
+
|
32
|
+
before { test_persistance }
|
33
|
+
|
34
|
+
describe '.new' do
|
35
|
+
subject { AMongoModel.new attributes }
|
36
|
+
|
37
|
+
its(:reference) { should == BSON::ObjectId('50995b8c15529d4676000001') }
|
38
|
+
its(:name) { should == 'whatever' }
|
39
|
+
its(:count) { should == 5 }
|
40
|
+
its(:dollars) { should == 2.3 }
|
41
|
+
its(:favorite) { should be_true }
|
42
|
+
its(:created) { should == Time.utc(0) }
|
43
|
+
|
44
|
+
its(:as_json) do
|
45
|
+
should == {
|
46
|
+
reference: '50995b8c15529d4676000001',
|
47
|
+
name: "whatever",
|
48
|
+
count: 5,
|
49
|
+
dollars: 2.3,
|
50
|
+
favorite: true,
|
51
|
+
created: Time.utc(0).to_i,
|
52
|
+
id: nil
|
53
|
+
}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '.all' do
|
58
|
+
it 'returns a collection of all objects' do
|
59
|
+
EM.synchrony do
|
60
|
+
test_persistance.create AMongoModel.new name: 'findme'
|
61
|
+
|
62
|
+
AMongoModel.all.should be_collection_of AMongoModel
|
63
|
+
|
64
|
+
EM.stop
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'returns a collection of objects with the query' do
|
69
|
+
EM.synchrony do
|
70
|
+
persistance.create AMongoModel.new name: 'findme'
|
71
|
+
|
72
|
+
AMongoModel.all(name: 'findme').should be_collection_of AMongoModel
|
73
|
+
|
74
|
+
EM.stop
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'returns an empty array if the client is empty' do
|
79
|
+
EM.synchrony do
|
80
|
+
AMongoModel.all.should =~ []
|
81
|
+
|
82
|
+
EM.stop
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'converts time strings into time objects' do
|
87
|
+
EM.synchrony do
|
88
|
+
persistance.create AMongoModel.new created: Time.parse('2001-01-02')
|
89
|
+
|
90
|
+
AMongoModel.all(created: { '$gt' => '2001-01-01' }).
|
91
|
+
should be_collection_of AMongoModel
|
92
|
+
|
93
|
+
AMongoModel.all(created: { '$lt' => Time.parse('2001-01-01')}).
|
94
|
+
should be_empty
|
95
|
+
|
96
|
+
EM.stop
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'converts reference strings into BSON::ObjectId objects' do
|
101
|
+
EM.synchrony do
|
102
|
+
persistance.create AMongoModel.new reference: BSON::ObjectId('50995b8c15529d4676000001')
|
103
|
+
|
104
|
+
AMongoModel.all(reference: '50995b8c15529d4676000001').
|
105
|
+
should be_collection_of AMongoModel
|
106
|
+
|
107
|
+
EM.stop
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'converts multiple query parameters' do
|
112
|
+
EM.synchrony do
|
113
|
+
persistance.create AMongoModel.new reference: BSON::ObjectId('50995b8c15529d4676000001'), created: Time.parse('2003-01-01')
|
114
|
+
|
115
|
+
AMongoModel.all(reference: '50995b8c15529d4676000001', created: '2003-01-01').
|
116
|
+
should be_collection_of AMongoModel
|
117
|
+
|
118
|
+
EM.stop
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'runs async given a block' do
|
123
|
+
EM.synchrony do
|
124
|
+
persistance.create AMongoModel.new reference: BSON::ObjectId('50995b8c15529d4676000001')
|
125
|
+
fail_in 1
|
126
|
+
|
127
|
+
AMongoModel.all do |model|
|
128
|
+
model.should be_instance_of AMongoModel
|
129
|
+
|
130
|
+
EM.stop
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
describe '.find' do
|
137
|
+
it 'returns the first object with the given id' do
|
138
|
+
EM.synchrony do
|
139
|
+
AMongoModel.find(subject.save.id).should be_instance_of AMongoModel
|
140
|
+
|
141
|
+
EM.stop
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'converts id BSON::ObjectId' do
|
146
|
+
EM.synchrony do
|
147
|
+
AMongoModel.find(subject.save.id.to_s).should be_instance_of AMongoModel
|
148
|
+
|
149
|
+
EM.stop
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'runs async given a block' do
|
154
|
+
EM.synchrony do
|
155
|
+
id = persistance.create AMongoModel.new attributes
|
156
|
+
fail_in 1
|
157
|
+
|
158
|
+
AMongoModel.find(id) do |found|
|
159
|
+
found.should be_instance_of AMongoModel
|
160
|
+
|
161
|
+
EM.stop
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
describe '.create' do
|
168
|
+
it 'adds the object to the collection' do
|
169
|
+
EM.synchrony do
|
170
|
+
expect { subject.save }.to change { test_persistance.size }
|
171
|
+
|
172
|
+
EM.stop
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'returns an object with the newly created attributes' do
|
177
|
+
EM.synchrony do
|
178
|
+
AMongoModel.create(attributes).should be_instance_of AMongoModel
|
179
|
+
|
180
|
+
EM.stop
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'runs async given a block' do
|
185
|
+
EM.synchrony do
|
186
|
+
persistance
|
187
|
+
fail_in 1
|
188
|
+
|
189
|
+
AMongoModel.create(attributes) do |model|
|
190
|
+
model.should be_instance_of AMongoModel
|
191
|
+
|
192
|
+
EM.stop
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
describe '#save' do
|
200
|
+
subject { AMongoModel.new attributes }
|
201
|
+
|
202
|
+
it 'creates the object if it does not have an id' do
|
203
|
+
EM.synchrony do
|
204
|
+
persistance
|
205
|
+
|
206
|
+
expect { subject.save }.to change { subject.id }
|
207
|
+
EM.stop
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'maintains the same id of the record if it exists' do
|
212
|
+
EM.synchrony do
|
213
|
+
persistance
|
214
|
+
subject.save
|
215
|
+
|
216
|
+
expect { subject.save }.to_not change { subject.id }
|
217
|
+
EM.stop
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
describe '#update' do
|
223
|
+
subject { AMongoModel.new attributes }
|
224
|
+
|
225
|
+
it 'updates the object with the given attributes' do
|
226
|
+
EM.synchrony do
|
227
|
+
persistance
|
228
|
+
|
229
|
+
expect { subject.update name: 'new' }.to change { subject.name }
|
230
|
+
|
231
|
+
EM.stop
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
it 'updates the collection with the given attributes' do
|
236
|
+
EM.synchrony do
|
237
|
+
persistance
|
238
|
+
|
239
|
+
expect { subject.update name: 'another' }.to_not change { persistance.count }
|
240
|
+
|
241
|
+
EM.stop
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
describe '#delete' do
|
247
|
+
subject { AMongoModel.new attributes }
|
248
|
+
it 'removes the object from the collection' do
|
249
|
+
EM.synchrony do
|
250
|
+
test_persistance.create subject
|
251
|
+
|
252
|
+
expect { subject.delete }.to change { test_persistance.size }
|
253
|
+
|
254
|
+
EM.stop
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
data/spec/redis_spec.rb
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class ARedisModel
|
4
|
+
include Uorm::Model
|
5
|
+
include Uorm::Redis
|
6
|
+
|
7
|
+
field :reference, type: :String
|
8
|
+
field :name, type: :String
|
9
|
+
field :count, type: :Integer
|
10
|
+
field :dollars, type: :Float
|
11
|
+
field :favorite, type: :Boolean
|
12
|
+
field :created, type: :Time
|
13
|
+
end
|
14
|
+
|
15
|
+
describe ARedisModel do
|
16
|
+
|
17
|
+
let(:attributes) do
|
18
|
+
{
|
19
|
+
reference: '2d931510-d99f-494a-8c67-87feb05e1594',
|
20
|
+
name: 'whatever',
|
21
|
+
count: 5.to_s,
|
22
|
+
dollars: 2.3.to_s,
|
23
|
+
favorite: true.to_s,
|
24
|
+
created: Time.utc(0).to_s
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
let(:client) { Redis.new(db: 15, driver: :synchrony).tap(&:flushdb) }
|
29
|
+
let(:persistance) { AMongoModel.persistance = Uorm::Redis::Persistance.new ARedisModel, client }
|
30
|
+
let(:test_persistance) { AMongoModel.persistance = Uorm::Mongo::TestPerstistance.new }
|
31
|
+
|
32
|
+
before { test_persistance }
|
33
|
+
|
34
|
+
describe '.new' do
|
35
|
+
subject { ARedisModel.new attributes }
|
36
|
+
|
37
|
+
its(:reference) { should == '2d931510-d99f-494a-8c67-87feb05e1594' }
|
38
|
+
its(:name) { should == 'whatever' }
|
39
|
+
its(:count) { should == 5 }
|
40
|
+
its(:dollars) { should == 2.3 }
|
41
|
+
its(:favorite) { should be_true }
|
42
|
+
its(:created) { should == Time.utc(0) }
|
43
|
+
|
44
|
+
its(:as_json) do
|
45
|
+
should == {
|
46
|
+
reference: '2d931510-d99f-494a-8c67-87feb05e1594',
|
47
|
+
name: "whatever",
|
48
|
+
count: 5,
|
49
|
+
dollars: 2.3,
|
50
|
+
favorite: true,
|
51
|
+
created: Time.utc(0).to_i,
|
52
|
+
id: nil
|
53
|
+
}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '.all' do
|
58
|
+
it 'returns a client of all objects' do
|
59
|
+
EM.synchrony do
|
60
|
+
test_persistance.create ARedisModel.new attributes
|
61
|
+
ARedisModel.all.should be_collection_of ARedisModel
|
62
|
+
|
63
|
+
EM.stop
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'returns an empty array if the client is empty' do
|
68
|
+
EM.synchrony do
|
69
|
+
ARedisModel.all.should =~ []
|
70
|
+
|
71
|
+
EM.stop
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe '.find' do
|
77
|
+
it 'returns the first object with the given id' do
|
78
|
+
EM.synchrony do
|
79
|
+
id = persistance.create ARedisModel.new attributes
|
80
|
+
ARedisModel.find(id).should be_instance_of ARedisModel
|
81
|
+
|
82
|
+
EM.stop
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe '.create' do
|
88
|
+
it 'adds the object to the client' do
|
89
|
+
EM.synchrony do
|
90
|
+
|
91
|
+
expect { ARedisModel.create attributes }.to change { test_persistance.size }
|
92
|
+
|
93
|
+
EM.stop
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'returns an object with the newly created attributes' do
|
98
|
+
EM.synchrony do
|
99
|
+
ARedisModel.create(attributes).should be_instance_of ARedisModel
|
100
|
+
|
101
|
+
EM.stop
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe '#save' do
|
107
|
+
it 'creates the object if it does not have an id' do
|
108
|
+
EM.synchrony do
|
109
|
+
persistance
|
110
|
+
|
111
|
+
model = ARedisModel.new attributes
|
112
|
+
expect { model.save }.to change { model.id }
|
113
|
+
|
114
|
+
EM.stop
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'updates the object if it does exist' do
|
119
|
+
EM.synchrony do
|
120
|
+
persistance
|
121
|
+
|
122
|
+
model = ARedisModel.create attributes
|
123
|
+
expect { model.save }.to_not change { model.id }
|
124
|
+
|
125
|
+
EM.stop
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe '#update' do
|
131
|
+
it 'updates the object with the given attributes' do
|
132
|
+
EM.synchrony do
|
133
|
+
model = ARedisModel.create attributes
|
134
|
+
expect { model.update name: 'new' }.to change { model.name }
|
135
|
+
|
136
|
+
EM.stop
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'updates the client with the given attributes' do
|
141
|
+
EM.synchrony do
|
142
|
+
model = ARedisModel.create attributes
|
143
|
+
expect { model.update name: 'another' }.
|
144
|
+
to change { ARedisModel.find(model.id).name }
|
145
|
+
|
146
|
+
EM.stop
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe '#delete' do
|
152
|
+
it 'removes the object from the client' do
|
153
|
+
EM.synchrony do
|
154
|
+
model = ARedisModel.create attributes
|
155
|
+
expect { model.delete }.to change { test_persistance.size }
|
156
|
+
|
157
|
+
EM.stop
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|