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 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