modis 1.4.1 → 1.4.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a53daa02a9a6c4cc8463b7d7bd340a0581fe4748
4
- data.tar.gz: fa9efc54e2ff9d4e7947e1deee4313ed59a6f345
3
+ metadata.gz: 774c89b8695921821cc449741a450f77f69f649f
4
+ data.tar.gz: 941a15b53b91e8c955a1599199867a0595b58b5a
5
5
  SHA512:
6
- metadata.gz: 129daf466455122c27dddd64bd4c3196de3b7cb227753e12c62a9cdda1e91410239823464c14ff8c94b1754af4b186588ed9deae38d5f479a8a53318ca0d71fb
7
- data.tar.gz: 5055dd9c6e2bdc13c49d59423385009d8d528ec06358b7a9f06ee2632ac870bc421e678093f376e9d71b2a23b32fdea73c68c70af7caf1f7beba710c383055c9
6
+ metadata.gz: 47964396569527b5f809150eaf9c6a82353226e66bfd05b49f5295cf520ed57ba84a07c63b7bdf52c181c4adbf6fc459e0f1f5b2207994f96992d067b220eff6
7
+ data.tar.gz: 8a4b7f80c4c39593c8de11c457c1bd6430bbc3f559a739c3dab7b11282750bd29a53fb0f88d9deb4748983d9641f8d0699fcd45afdcf0094c52c7b3ef26b1d4f
@@ -29,3 +29,9 @@ Style/NumericLiterals:
29
29
 
30
30
  Metrics/AbcSize:
31
31
  Max: 25
32
+
33
+ Style/StructInheritance:
34
+ Enabled: false
35
+
36
+ Metrics/ModuleLength:
37
+ Enabled: false
@@ -1 +1 @@
1
- ruby-2.2.0
1
+ ruby-2.2.2
@@ -12,10 +12,10 @@ PATH
12
12
  GEM
13
13
  remote: https://rubygems.org/
14
14
  specs:
15
- activemodel (4.2.0)
16
- activesupport (= 4.2.0)
15
+ activemodel (4.2.3)
16
+ activesupport (= 4.2.3)
17
17
  builder (~> 3.1)
18
- activesupport (4.2.0)
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.5)
30
+ codeclimate-test-reporter (0.4.7)
31
31
  simplecov (>= 0.7.1, < 1.0.0)
32
- connection_pool (2.1.0)
32
+ connection_pool (2.2.0)
33
33
  diff-lcs (1.2.5)
34
34
  docile (1.1.5)
35
- hiredis (0.5.2)
35
+ hiredis (0.6.0)
36
+ hiredis (0.6.0-java)
36
37
  i18n (0.7.0)
37
- json (1.8.2)
38
- minitest (5.5.1)
39
- msgpack (0.5.10)
40
- multi_json (1.10.1)
41
- parallel (1.3.3)
42
- parser (2.2.0.2)
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.0.9)
46
+ powerpack (0.1.1)
45
47
  rainbow (2.0.0)
46
48
  rake (10.4.2)
47
- redis (3.2.0)
48
- rspec (3.1.0)
49
- rspec-core (~> 3.1.0)
50
- rspec-expectations (~> 3.1.0)
51
- rspec-mocks (~> 3.1.0)
52
- rspec-core (3.1.7)
53
- rspec-support (~> 3.1.0)
54
- rspec-expectations (3.1.2)
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.1.0)
57
- rspec-mocks (3.1.3)
58
- rspec-support (~> 3.1.0)
59
- rspec-support (3.1.2)
60
- rubocop (0.28.0)
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.0.pre.7, < 3.0)
63
- powerpack (~> 0.0.6)
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.1)
67
- simplecov (0.9.1)
69
+ ruby-progressbar (1.7.5)
70
+ simplecov (0.10.0)
68
71
  docile (~> 1.1.0)
69
- multi_json (~> 1.0)
70
- simplecov-html (~> 0.8.0)
71
- simplecov-html (0.8.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.4)
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
@@ -60,11 +60,14 @@ module Modis
60
60
  end
61
61
 
62
62
  def model_for(attributes)
63
- model_class(attributes).new(attributes, new_record: false)
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
- redis.hgetall(key_for(id))
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)
@@ -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
- return sti_parent.namespace if sti_child?
34
- @namespace ||= name.split('::').map(&:underscore).join(':')
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
- new_record? ? nil : self.class.key_for(id)
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
- future = attrs.any? ? redis.hmset(self.class.key_for(id), attrs) : :unchanged
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) # rubocop:disable Metrics/AbcSize
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("#{self.class.absolute_namespace}_id_seq")
246
+ self.id = redis.incr("#{namespace}_id_seq")
230
247
  end
231
248
  end
232
249
  end
@@ -1,3 +1,3 @@
1
1
  module Modis
2
- VERSION = '1.4.1'
2
+ VERSION = '1.4.2'
3
3
  end
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  module FindersSpec
4
4
  class User
5
5
  include Modis::Model
6
- self.namespace = 'users'
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('users')
74
- expect(FindersSpec::Consumer.absolute_namespace).to eq('modis:users')
75
- expect(FindersSpec::Producer.namespace).to eq('users')
76
- expect(FindersSpec::Producer.absolute_namespace).to eq('modis:users')
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
- consumer = FindersSpec::Consumer.create!(name: 'Kyle', consumed: true)
100
- expect(consumer.attributes.keys.sort).to eq(%w(age consumed id name parent_default type))
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.1
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: 2015-01-20 00:00:00.000000000 Z
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.4.5
159
+ rubygems_version: 2.6.11
160
160
  signing_key:
161
161
  specification_version: 4
162
162
  summary: ActiveModel + Redis