modis 1.4.1 → 1.4.2
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 +4 -4
- data/.rubocop.yml +6 -0
- data/.ruby-version +1 -1
- data/Gemfile.lock +41 -34
- data/lib/modis/finder.rb +5 -2
- data/lib/modis/persistence.rb +24 -7
- data/lib/modis/version.rb +1 -1
- data/spec/finder_spec.rb +78 -7
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 774c89b8695921821cc449741a450f77f69f649f
|
4
|
+
data.tar.gz: 941a15b53b91e8c955a1599199867a0595b58b5a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 47964396569527b5f809150eaf9c6a82353226e66bfd05b49f5295cf520ed57ba84a07c63b7bdf52c181c4adbf6fc459e0f1f5b2207994f96992d067b220eff6
|
7
|
+
data.tar.gz: 8a4b7f80c4c39593c8de11c457c1bd6430bbc3f559a739c3dab7b11282750bd29a53fb0f88d9deb4748983d9641f8d0699fcd45afdcf0094c52c7b3ef26b1d4f
|
data/.rubocop.yml
CHANGED
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
ruby-2.2.
|
1
|
+
ruby-2.2.2
|
data/Gemfile.lock
CHANGED
@@ -12,10 +12,10 @@ PATH
|
|
12
12
|
GEM
|
13
13
|
remote: https://rubygems.org/
|
14
14
|
specs:
|
15
|
-
activemodel (4.2.
|
16
|
-
activesupport (= 4.2.
|
15
|
+
activemodel (4.2.3)
|
16
|
+
activesupport (= 4.2.3)
|
17
17
|
builder (~> 3.1)
|
18
|
-
activesupport (4.2.
|
18
|
+
activesupport (4.2.3)
|
19
19
|
i18n (~> 0.7)
|
20
20
|
json (~> 1.7, >= 1.7.7)
|
21
21
|
minitest (~> 5.1)
|
@@ -27,50 +27,54 @@ GEM
|
|
27
27
|
builder (3.2.2)
|
28
28
|
cane (2.6.2)
|
29
29
|
parallel
|
30
|
-
codeclimate-test-reporter (0.4.
|
30
|
+
codeclimate-test-reporter (0.4.7)
|
31
31
|
simplecov (>= 0.7.1, < 1.0.0)
|
32
|
-
connection_pool (2.
|
32
|
+
connection_pool (2.2.0)
|
33
33
|
diff-lcs (1.2.5)
|
34
34
|
docile (1.1.5)
|
35
|
-
hiredis (0.
|
35
|
+
hiredis (0.6.0)
|
36
|
+
hiredis (0.6.0-java)
|
36
37
|
i18n (0.7.0)
|
37
|
-
json (1.8.
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
38
|
+
json (1.8.3)
|
39
|
+
json (1.8.3-java)
|
40
|
+
minitest (5.7.0)
|
41
|
+
msgpack (0.6.0)
|
42
|
+
msgpack (0.6.0-java)
|
43
|
+
parallel (1.6.0)
|
44
|
+
parser (2.2.2.5)
|
43
45
|
ast (>= 1.1, < 3.0)
|
44
|
-
powerpack (0.
|
46
|
+
powerpack (0.1.1)
|
45
47
|
rainbow (2.0.0)
|
46
48
|
rake (10.4.2)
|
47
|
-
redis (3.2.
|
48
|
-
rspec (3.
|
49
|
-
rspec-core (~> 3.
|
50
|
-
rspec-expectations (~> 3.
|
51
|
-
rspec-mocks (~> 3.
|
52
|
-
rspec-core (3.1
|
53
|
-
rspec-support (~> 3.
|
54
|
-
rspec-expectations (3.
|
49
|
+
redis (3.2.1)
|
50
|
+
rspec (3.3.0)
|
51
|
+
rspec-core (~> 3.3.0)
|
52
|
+
rspec-expectations (~> 3.3.0)
|
53
|
+
rspec-mocks (~> 3.3.0)
|
54
|
+
rspec-core (3.3.1)
|
55
|
+
rspec-support (~> 3.3.0)
|
56
|
+
rspec-expectations (3.3.0)
|
55
57
|
diff-lcs (>= 1.2.0, < 2.0)
|
56
|
-
rspec-support (~> 3.
|
57
|
-
rspec-mocks (3.1
|
58
|
-
|
59
|
-
|
60
|
-
|
58
|
+
rspec-support (~> 3.3.0)
|
59
|
+
rspec-mocks (3.3.1)
|
60
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
61
|
+
rspec-support (~> 3.3.0)
|
62
|
+
rspec-support (3.3.0)
|
63
|
+
rubocop (0.32.1)
|
61
64
|
astrolabe (~> 1.3)
|
62
|
-
parser (>= 2.2.
|
63
|
-
powerpack (~> 0.
|
65
|
+
parser (>= 2.2.2.5, < 3.0)
|
66
|
+
powerpack (~> 0.1)
|
64
67
|
rainbow (>= 1.99.1, < 3.0)
|
65
68
|
ruby-progressbar (~> 1.4)
|
66
|
-
ruby-progressbar (1.7.
|
67
|
-
simplecov (0.
|
69
|
+
ruby-progressbar (1.7.5)
|
70
|
+
simplecov (0.10.0)
|
68
71
|
docile (~> 1.1.0)
|
69
|
-
|
70
|
-
simplecov-html (~> 0.
|
71
|
-
simplecov-html (0.
|
72
|
+
json (~> 1.8)
|
73
|
+
simplecov-html (~> 0.10.0)
|
74
|
+
simplecov-html (0.10.0)
|
72
75
|
stackprof (0.2.7)
|
73
|
-
thread_safe (0.3.
|
76
|
+
thread_safe (0.3.5)
|
77
|
+
thread_safe (0.3.5-java)
|
74
78
|
tzinfo (1.2.2)
|
75
79
|
thread_safe (~> 0.1)
|
76
80
|
|
@@ -87,3 +91,6 @@ DEPENDENCIES
|
|
87
91
|
rubocop
|
88
92
|
simplecov
|
89
93
|
stackprof
|
94
|
+
|
95
|
+
BUNDLED WITH
|
96
|
+
1.10.5
|
data/lib/modis/finder.rb
CHANGED
@@ -60,11 +60,14 @@ module Modis
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def model_for(attributes)
|
63
|
-
model_class(attributes)
|
63
|
+
cls = model_class(attributes)
|
64
|
+
return unless self == cls || cls < self
|
65
|
+
cls.new(attributes, new_record: false)
|
64
66
|
end
|
65
67
|
|
66
68
|
def record_for(redis, id)
|
67
|
-
|
69
|
+
key = sti_child? ? sti_base_key_for(id) : key_for(id)
|
70
|
+
redis.hgetall(key)
|
68
71
|
end
|
69
72
|
|
70
73
|
def model_class(record)
|
data/lib/modis/persistence.rb
CHANGED
@@ -16,13 +16,14 @@ module Modis
|
|
16
16
|
child.instance_eval do
|
17
17
|
parent.instance_eval do
|
18
18
|
class << self
|
19
|
-
attr_accessor :sti_parent
|
19
|
+
attr_accessor :sti_base, :sti_parent
|
20
20
|
end
|
21
21
|
attribute :type, :string unless attributes.key?('type')
|
22
22
|
end
|
23
23
|
|
24
24
|
@sti_child = true
|
25
25
|
@sti_parent = parent
|
26
|
+
@sti_base = parent.sti_base || parent
|
26
27
|
|
27
28
|
bootstrap_attributes(parent)
|
28
29
|
bootstrap_indexes(parent)
|
@@ -30,8 +31,11 @@ module Modis
|
|
30
31
|
end
|
31
32
|
|
32
33
|
def namespace
|
33
|
-
|
34
|
-
|
34
|
+
@namespace ||= if sti_child?
|
35
|
+
"#{sti_parent.namespace}:#{name.split('::').last.underscore}"
|
36
|
+
else
|
37
|
+
name.split('::').map(&:underscore).join(':')
|
38
|
+
end
|
35
39
|
end
|
36
40
|
|
37
41
|
def namespace=(value)
|
@@ -43,10 +47,18 @@ module Modis
|
|
43
47
|
@absolute_namespace ||= [Modis.config.namespace, namespace].compact.join(':')
|
44
48
|
end
|
45
49
|
|
50
|
+
def sti_base_absolute_namespace
|
51
|
+
@sti_base_absolute_namespace ||= [Modis.config.namespace, sti_base.namespace].compact.join(':')
|
52
|
+
end
|
53
|
+
|
46
54
|
def key_for(id)
|
47
55
|
"#{absolute_namespace}:#{id}"
|
48
56
|
end
|
49
57
|
|
58
|
+
def sti_base_key_for(id)
|
59
|
+
"#{sti_base_absolute_namespace}:#{id}"
|
60
|
+
end
|
61
|
+
|
50
62
|
def create(attrs)
|
51
63
|
model = new(attrs)
|
52
64
|
model.save
|
@@ -104,7 +116,8 @@ module Modis
|
|
104
116
|
end
|
105
117
|
|
106
118
|
def key
|
107
|
-
|
119
|
+
return nil if new_record?
|
120
|
+
self.class.sti_child? ? self.class.sti_base_key_for(id) : self.class.key_for(id)
|
108
121
|
end
|
109
122
|
|
110
123
|
def new_record?
|
@@ -127,6 +140,7 @@ module Modis
|
|
127
140
|
redis.pipelined do
|
128
141
|
remove_from_indexes(redis)
|
129
142
|
redis.srem(self.class.key_for(:all), id)
|
143
|
+
redis.srem(self.class.sti_base_key_for(:all), id) if self.class.sti_child?
|
130
144
|
redis.del(key)
|
131
145
|
end
|
132
146
|
end
|
@@ -190,10 +204,12 @@ module Modis
|
|
190
204
|
run_callbacks callback do
|
191
205
|
redis.pipelined do
|
192
206
|
attrs = coerced_attributes(persist_all)
|
193
|
-
|
207
|
+
key = self.class.sti_child? ? self.class.sti_base_key_for(id) : self.class.key_for(id)
|
208
|
+
future = attrs.any? ? redis.hmset(key, attrs) : :unchanged
|
194
209
|
|
195
210
|
if new_record?
|
196
211
|
redis.sadd(self.class.key_for(:all), id)
|
212
|
+
redis.sadd(self.class.sti_base_key_for(:all), id) if self.class.sti_child?
|
197
213
|
add_to_indexes(redis)
|
198
214
|
else
|
199
215
|
update_indexes(redis)
|
@@ -206,7 +222,7 @@ module Modis
|
|
206
222
|
future
|
207
223
|
end
|
208
224
|
|
209
|
-
def coerced_attributes(persist_all)
|
225
|
+
def coerced_attributes(persist_all)
|
210
226
|
attrs = []
|
211
227
|
|
212
228
|
if new_record? || persist_all
|
@@ -225,8 +241,9 @@ module Modis
|
|
225
241
|
end
|
226
242
|
|
227
243
|
def set_id
|
244
|
+
namespace = self.class.sti_child? ? self.class.sti_base_absolute_namespace : self.class.absolute_namespace
|
228
245
|
Modis.with_connection do |redis|
|
229
|
-
self.id = redis.incr("#{
|
246
|
+
self.id = redis.incr("#{namespace}_id_seq")
|
230
247
|
end
|
231
248
|
end
|
232
249
|
end
|
data/lib/modis/version.rb
CHANGED
data/spec/finder_spec.rb
CHANGED
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
module FindersSpec
|
4
4
|
class User
|
5
5
|
include Modis::Model
|
6
|
-
self.namespace = '
|
6
|
+
self.namespace = 'user'
|
7
7
|
|
8
8
|
attribute :name, :string
|
9
9
|
attribute :age, :integer
|
@@ -17,6 +17,9 @@ module FindersSpec
|
|
17
17
|
class Producer < User
|
18
18
|
attribute :child_default, :string, default: 'derp'
|
19
19
|
end
|
20
|
+
|
21
|
+
class Worker < Producer
|
22
|
+
end
|
20
23
|
end
|
21
24
|
|
22
25
|
describe Modis::Finder do
|
@@ -70,40 +73,108 @@ describe Modis::Finder do
|
|
70
73
|
|
71
74
|
describe 'Single Table Inheritance' do
|
72
75
|
it 'returns the correct namespace' do
|
73
|
-
expect(FindersSpec::Consumer.namespace).to eq('
|
74
|
-
expect(FindersSpec::Consumer.absolute_namespace).to eq('modis:
|
75
|
-
expect(FindersSpec::Producer.namespace).to eq('
|
76
|
-
expect(FindersSpec::Producer.absolute_namespace).to eq('modis:
|
76
|
+
expect(FindersSpec::Consumer.namespace).to eq('user:consumer')
|
77
|
+
expect(FindersSpec::Consumer.absolute_namespace).to eq('modis:user:consumer')
|
78
|
+
expect(FindersSpec::Producer.namespace).to eq('user:producer')
|
79
|
+
expect(FindersSpec::Producer.absolute_namespace).to eq('modis:user:producer')
|
80
|
+
expect(FindersSpec::Worker.namespace).to eq('user:producer:worker')
|
81
|
+
expect(FindersSpec::Worker.absolute_namespace).to eq('modis:user:producer:worker')
|
77
82
|
end
|
78
83
|
|
79
84
|
it 'returns instances of the correct class' do
|
80
85
|
FindersSpec::Consumer.create!(name: 'Kyle')
|
81
86
|
FindersSpec::Producer.create!(name: 'Tanya')
|
87
|
+
FindersSpec::Worker.create!(name: 'Max')
|
82
88
|
|
83
89
|
models = FindersSpec::User.all
|
84
90
|
|
85
91
|
ian = models.find { |model| model.name == 'Ian' }
|
86
92
|
kyle = models.find { |model| model.name == 'Kyle' }
|
87
93
|
tanya = models.find { |model| model.name == 'Tanya' }
|
94
|
+
max = models.find { |model| model.name == 'Max' }
|
88
95
|
|
89
96
|
expect(ian).to be_kind_of(FindersSpec::User)
|
90
97
|
expect(kyle).to be_kind_of(FindersSpec::Consumer)
|
91
98
|
expect(tanya).to be_kind_of(FindersSpec::Producer)
|
99
|
+
expect(max).to be_kind_of(FindersSpec::Worker)
|
92
100
|
|
93
101
|
expect(FindersSpec::User.find(ian.id)).to be_kind_of(FindersSpec::User)
|
94
102
|
expect(FindersSpec::User.find(kyle.id)).to be_kind_of(FindersSpec::Consumer)
|
95
103
|
expect(FindersSpec::User.find(tanya.id)).to be_kind_of(FindersSpec::Producer)
|
104
|
+
expect(FindersSpec::User.find(max.id)).to be_kind_of(FindersSpec::Worker)
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'scopes IDs within the parent' do
|
108
|
+
user = FindersSpec::User.create!(name: 'Ian')
|
109
|
+
consumer = FindersSpec::Consumer.create!(name: 'Kyle')
|
110
|
+
producer = FindersSpec::Producer.create!(name: 'Tanya')
|
111
|
+
worker = FindersSpec::Worker.create!(name: 'Max')
|
112
|
+
expect(user.id).to eq(2)
|
113
|
+
expect(consumer.id).to eq(3)
|
114
|
+
expect(producer.id).to eq(4)
|
115
|
+
expect(worker.id).to eq(5)
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'does not return instances of other siblings in all' do
|
119
|
+
producer = FindersSpec::Producer.create!(name: 'Tanya')
|
120
|
+
expect(FindersSpec::Consumer.all).to_not include(producer)
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'does not return instances of subclasses of other siblings in all' do
|
124
|
+
worker = FindersSpec::Worker.create!(name: 'Max')
|
125
|
+
expect(FindersSpec::Consumer.all).to_not include(worker)
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'does not find an instance of a sibling' do
|
129
|
+
consumer = FindersSpec::Consumer.create!(name: 'Kyle')
|
130
|
+
producer = FindersSpec::Producer.create!(name: 'Tanya')
|
131
|
+
expect do
|
132
|
+
FindersSpec::Consumer.find(producer.id)
|
133
|
+
end.to raise_error(Modis::RecordNotFound)
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'does not find an instance of a subclass of a sibling' do
|
137
|
+
producer = FindersSpec::Worker.create!(name: 'Tanya')
|
138
|
+
expect do
|
139
|
+
FindersSpec::Consumer.find(producer.id)
|
140
|
+
end.to raise_error(Modis::RecordNotFound)
|
96
141
|
end
|
97
142
|
|
98
143
|
it 'inherits attributes from the parent' do
|
99
|
-
|
100
|
-
expect(
|
144
|
+
producer = FindersSpec::Producer.create!(name: 'Kyle', consumed: true)
|
145
|
+
expect(producer.attributes.keys.sort).to eq(%w(age child_default id name parent_default type))
|
146
|
+
|
147
|
+
worker = FindersSpec::Worker.create!(name: 'Max')
|
148
|
+
expect(worker.attributes.keys.sort).to eq(%w(age child_default id name parent_default type))
|
101
149
|
end
|
102
150
|
|
103
151
|
it 'inherits default attribute values from the parent' do
|
104
152
|
producer = FindersSpec::Producer.create!(name: 'Kyle')
|
105
153
|
expect(producer.parent_default).to eq('omg')
|
106
154
|
expect(producer.child_default).to eq('derp')
|
155
|
+
|
156
|
+
worker = FindersSpec::Worker.create!(name: 'Max')
|
157
|
+
expect(worker.parent_default).to eq('omg')
|
158
|
+
expect(worker.child_default).to eq('derp')
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'does not find a destroyed child instance on the parent' do
|
162
|
+
consumer = FindersSpec::Consumer.create!(name: 'Ian')
|
163
|
+
expect(FindersSpec::User.find(consumer.id)).to eq(consumer)
|
164
|
+
consumer.destroy
|
165
|
+
expect do
|
166
|
+
FindersSpec::User.find(consumer.id)
|
167
|
+
end.to raise_error(Modis::RecordNotFound)
|
168
|
+
end
|
169
|
+
|
170
|
+
describe('backwards compatibility') do
|
171
|
+
it 'transparently upgrades old data' do
|
172
|
+
consumer = FindersSpec::Consumer.create!(name: 'Ian')
|
173
|
+
Modis.with_connection do |redis|
|
174
|
+
redis.srem(FindersSpec::Consumer.key_for(:all), consumer.id)
|
175
|
+
end
|
176
|
+
expect(FindersSpec::Consumer.find(consumer.id)).to eq(consumer)
|
177
|
+
end
|
107
178
|
end
|
108
179
|
end
|
109
180
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: modis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.4.
|
4
|
+
version: 1.4.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ian Leitch
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-06-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -156,7 +156,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
156
156
|
version: '0'
|
157
157
|
requirements: []
|
158
158
|
rubyforge_project:
|
159
|
-
rubygems_version: 2.
|
159
|
+
rubygems_version: 2.6.11
|
160
160
|
signing_key:
|
161
161
|
specification_version: 4
|
162
162
|
summary: ActiveModel + Redis
|