modis 1.3.0 → 1.4.0
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 +7 -0
- data/.ruby-version +1 -1
- data/.travis.yml +10 -5
- data/Gemfile +8 -4
- data/Gemfile.lock +42 -48
- data/README.md +2 -2
- data/benchmark/bench.rb +65 -0
- data/benchmark/find.rb +62 -0
- data/benchmark/persistence.rb +82 -0
- data/benchmark/redis/connection/fakedis.rb +90 -0
- data/lib/modis.rb +2 -1
- data/lib/modis/attribute.rb +47 -27
- data/lib/modis/configuration.rb +5 -3
- data/lib/modis/finder.rb +31 -19
- data/lib/modis/index.rb +19 -27
- data/lib/modis/model.rb +2 -3
- data/lib/modis/persistence.rb +87 -56
- data/lib/modis/version.rb +1 -1
- data/lib/tasks/quality.rake +19 -12
- data/modis.gemspec +12 -4
- data/spec/attribute_spec.rb +5 -5
- data/spec/finder_spec.rb +27 -1
- data/spec/persistence_spec.rb +57 -4
- data/spec/spec_helper.rb +8 -6
- data/spec/support/simplecov_helper.rb +9 -5
- metadata +35 -4
- data/.coveralls.yml +0 -1
data/lib/modis/version.rb
CHANGED
data/lib/tasks/quality.rake
CHANGED
@@ -1,17 +1,23 @@
|
|
1
1
|
begin
|
2
|
-
|
2
|
+
if ENV['TRAVIS']
|
3
|
+
namespace :spec do
|
4
|
+
task cane: ['spec']
|
5
|
+
end
|
6
|
+
else
|
7
|
+
require 'cane/rake_task'
|
3
8
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
desc 'Run cane to check quality metrics'
|
10
|
+
Cane::RakeTask.new(:cane_quality) do |cane|
|
11
|
+
cane.add_threshold 'coverage/covered_percent', :>=, 99
|
12
|
+
cane.no_style = false
|
13
|
+
cane.style_measure = 1000
|
14
|
+
cane.no_doc = true
|
15
|
+
cane.abc_max = 25
|
16
|
+
end
|
12
17
|
|
13
|
-
|
14
|
-
|
18
|
+
namespace :spec do
|
19
|
+
task cane: %w(spec cane_quality)
|
20
|
+
end
|
15
21
|
end
|
16
22
|
rescue LoadError
|
17
23
|
warn "cane not available."
|
@@ -23,7 +29,8 @@ end
|
|
23
29
|
|
24
30
|
begin
|
25
31
|
require 'rubocop/rake_task'
|
26
|
-
RuboCop::RakeTask.new
|
32
|
+
t = RuboCop::RakeTask.new
|
33
|
+
t.options << '-D'
|
27
34
|
rescue LoadError
|
28
35
|
warn 'rubocop not available.'
|
29
36
|
task rubocop: ['spec']
|
data/modis.gemspec
CHANGED
@@ -17,8 +17,16 @@ Gem::Specification.new do |gem|
|
|
17
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
18
|
gem.require_paths = ["lib"]
|
19
19
|
|
20
|
-
gem.
|
21
|
-
gem.
|
22
|
-
gem.
|
23
|
-
gem.
|
20
|
+
gem.add_runtime_dependency 'activemodel', '>= 3.0'
|
21
|
+
gem.add_runtime_dependency 'activesupport', '>= 3.0'
|
22
|
+
gem.add_runtime_dependency 'redis', '>= 3.0'
|
23
|
+
gem.add_runtime_dependency 'hiredis', '>= 0.5'
|
24
|
+
gem.add_runtime_dependency 'connection_pool', '>= 2'
|
25
|
+
|
26
|
+
if defined? JRUBY_VERSION
|
27
|
+
gem.platform = 'java'
|
28
|
+
gem.add_runtime_dependency 'msgpack-jruby'
|
29
|
+
else
|
30
|
+
gem.add_runtime_dependency 'msgpack', '>= 0.5'
|
31
|
+
end
|
24
32
|
end
|
data/spec/attribute_spec.rb
CHANGED
@@ -93,12 +93,12 @@ describe Modis::Attribute do
|
|
93
93
|
|
94
94
|
describe ':timestamp type' do
|
95
95
|
it 'is coerced' do
|
96
|
-
|
97
|
-
model.created_at =
|
96
|
+
time = Time.new(2014, 12, 11, 17, 31, 50, '-02:00')
|
97
|
+
model.created_at = time
|
98
98
|
model.save!
|
99
99
|
found = AttributeSpec::MockModel.find(model.id)
|
100
100
|
expect(found.created_at).to be_kind_of(Time)
|
101
|
-
expect(found.created_at.to_s).to eq(
|
101
|
+
expect(found.created_at.to_s).to eq(time.to_s)
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
@@ -144,7 +144,7 @@ describe Modis::Attribute do
|
|
144
144
|
model.hash = { foo: :bar }
|
145
145
|
model.save!
|
146
146
|
found = AttributeSpec::MockModel.find(model.id)
|
147
|
-
expect(found.hash).to eq(foo
|
147
|
+
expect(found.hash).to eq('foo' => 'bar')
|
148
148
|
end
|
149
149
|
|
150
150
|
it 'raises an error when assigned another type' do
|
@@ -157,7 +157,7 @@ describe Modis::Attribute do
|
|
157
157
|
model.string_or_hash = { foo: :bar }
|
158
158
|
model.save!
|
159
159
|
found = AttributeSpec::MockModel.find(model.id)
|
160
|
-
expect(found.string_or_hash).to eq(foo
|
160
|
+
expect(found.string_or_hash).to eq('foo' => 'bar')
|
161
161
|
|
162
162
|
model.string_or_hash = 'test'
|
163
163
|
model.save!
|
data/spec/finder_spec.rb
CHANGED
@@ -7,12 +7,15 @@ module FindersSpec
|
|
7
7
|
|
8
8
|
attribute :name, :string
|
9
9
|
attribute :age, :integer
|
10
|
+
attribute :parent_default, :string, default: 'omg'
|
10
11
|
end
|
11
12
|
|
12
13
|
class Consumer < User
|
14
|
+
attribute :consumed, :boolean
|
13
15
|
end
|
14
16
|
|
15
17
|
class Producer < User
|
18
|
+
attribute :child_default, :string, default: 'derp'
|
16
19
|
end
|
17
20
|
end
|
18
21
|
|
@@ -26,10 +29,22 @@ describe Modis::Finder do
|
|
26
29
|
expect(found.age).to eq(model.age)
|
27
30
|
end
|
28
31
|
|
29
|
-
it '
|
32
|
+
it 'finds multiple by ID' do
|
33
|
+
model1 = FindersSpec::User.create!(name: 'Ian', age: 28)
|
34
|
+
model2 = FindersSpec::User.create!(name: 'Tanya', age: 32)
|
35
|
+
model3 = FindersSpec::User.create!(name: 'Kyle', age: 35)
|
36
|
+
models = FindersSpec::User.find(model1.id, model2.id, model3.id)
|
37
|
+
expect(models).to eq([model1, model2, model3])
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'raises an error a record could not be found' do
|
30
41
|
expect do
|
31
42
|
FindersSpec::User.find(model.id + 1)
|
32
43
|
end.to raise_error(Modis::RecordNotFound, "Couldn't find FindersSpec::User with id=#{model.id + 1}")
|
44
|
+
|
45
|
+
expect do
|
46
|
+
FindersSpec::User.find(model.id, model.id + 1)
|
47
|
+
end.to raise_error(Modis::RecordNotFound, "Couldn't find FindersSpec::User with id=#{model.id + 1}")
|
33
48
|
end
|
34
49
|
|
35
50
|
it 'does not flag an attribute as dirty on a found instance' do
|
@@ -79,5 +94,16 @@ describe Modis::Finder do
|
|
79
94
|
expect(FindersSpec::User.find(kyle.id)).to be_kind_of(FindersSpec::Consumer)
|
80
95
|
expect(FindersSpec::User.find(tanya.id)).to be_kind_of(FindersSpec::Producer)
|
81
96
|
end
|
97
|
+
|
98
|
+
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(consumed id name parent_default type))
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'inherits default attribute values from the parent' do
|
104
|
+
producer = FindersSpec::Producer.create!(name: 'Kyle')
|
105
|
+
expect(producer.parent_default).to eq('omg')
|
106
|
+
expect(producer.child_default).to eq('derp')
|
107
|
+
end
|
82
108
|
end
|
83
109
|
end
|
data/spec/persistence_spec.rb
CHANGED
@@ -93,11 +93,23 @@ describe Modis::Persistence do
|
|
93
93
|
expect(model.name_changed?).to be false
|
94
94
|
end
|
95
95
|
|
96
|
+
it 'does not identify an attribute as changed if the value is the default' do
|
97
|
+
expect(model.class.attributes_with_defaults).to eq('name' => 'Ian')
|
98
|
+
expect(model.name).to eq('Ian')
|
99
|
+
expect(model.name_changed?).to be false
|
100
|
+
end
|
101
|
+
|
96
102
|
it 'is persisted' do
|
97
103
|
expect(model.persisted?).to be true
|
98
104
|
end
|
99
105
|
|
100
|
-
it 'does not track the ID if the underlying Redis command failed'
|
106
|
+
it 'does not track the ID if the underlying Redis command failed' do
|
107
|
+
redis = double(hmset: double(value: nil), sadd: nil)
|
108
|
+
expect(model.class).to receive(:transaction).and_yield(redis)
|
109
|
+
expect(redis).to receive(:pipelined).and_yield
|
110
|
+
model.save
|
111
|
+
expect { model.class.find(model.id) }.to raise_error(Modis::RecordNotFound)
|
112
|
+
end
|
101
113
|
|
102
114
|
it 'does not perform validation if validate: false' do
|
103
115
|
model.name = nil
|
@@ -110,7 +122,18 @@ describe Modis::Persistence do
|
|
110
122
|
end
|
111
123
|
|
112
124
|
describe 'an existing record' do
|
113
|
-
it 'only updates dirty attributes'
|
125
|
+
it 'only updates dirty attributes' do
|
126
|
+
model.name = 'Ian'
|
127
|
+
model.age = 10
|
128
|
+
model.save!
|
129
|
+
model.age = 11
|
130
|
+
redis = double
|
131
|
+
expect(redis).to receive(:hmset).with("modis:persistence_spec:mock_model:1", ["age", "\v"]).and_return(double(value: 'OK'))
|
132
|
+
expect(model.class).to receive(:transaction).and_yield(redis)
|
133
|
+
expect(redis).to receive(:pipelined).and_yield
|
134
|
+
model.save!
|
135
|
+
expect(model.age).to eq(11)
|
136
|
+
end
|
114
137
|
end
|
115
138
|
|
116
139
|
describe 'reload' do
|
@@ -183,11 +206,19 @@ describe Modis::Persistence do
|
|
183
206
|
end
|
184
207
|
|
185
208
|
describe 'a valid model' do
|
186
|
-
it 'returns the created model'
|
209
|
+
it 'returns the created model' do
|
210
|
+
model = PersistenceSpec::MockModel.create(name: 'Ian')
|
211
|
+
expect(model.valid?).to be true
|
212
|
+
expect(model.new_record?).to be false
|
213
|
+
end
|
187
214
|
end
|
188
215
|
|
189
216
|
describe 'an invalid model' do
|
190
|
-
it 'returns the unsaved model'
|
217
|
+
it 'returns the unsaved model' do
|
218
|
+
model = PersistenceSpec::MockModel.create(name: nil)
|
219
|
+
expect(model.valid?).to be false
|
220
|
+
expect(model.new_record?).to be true
|
221
|
+
end
|
191
222
|
end
|
192
223
|
end
|
193
224
|
|
@@ -263,4 +294,26 @@ describe Modis::Persistence do
|
|
263
294
|
expect(model.update_attributes(name: nil)).to be false
|
264
295
|
end
|
265
296
|
end
|
297
|
+
|
298
|
+
describe 'YAML backward compatability' do
|
299
|
+
it 'loads a YAML serialized value' do
|
300
|
+
Modis.with_connection do |redis|
|
301
|
+
model.save!
|
302
|
+
key = model.class.key_for(model.id)
|
303
|
+
record = redis.hgetall(key)
|
304
|
+
record['age'] = YAML.dump(30)
|
305
|
+
redis.hmset(key, *record.to_a)
|
306
|
+
record = redis.hgetall(key)
|
307
|
+
|
308
|
+
expect(record['age']).to eq("--- 30\n...\n")
|
309
|
+
|
310
|
+
model.reload
|
311
|
+
expect(model.age).to eq(30)
|
312
|
+
|
313
|
+
model.save!(yaml_sucks: true)
|
314
|
+
record = redis.hgetall(key)
|
315
|
+
expect(record['age']).to eq("\x1E")
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
266
319
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
unless ENV['TRAVIS']
|
2
|
+
begin
|
3
|
+
require './spec/support/simplecov_helper'
|
4
|
+
include SimpleCovHelper
|
5
|
+
start_simple_cov('unit')
|
6
|
+
rescue LoadError
|
7
|
+
puts "Coverage disabled."
|
8
|
+
end
|
7
9
|
end
|
8
10
|
|
9
11
|
require 'modis'
|
@@ -7,13 +7,17 @@ module SimpleCovHelper
|
|
7
7
|
add_filter '/spec/'
|
8
8
|
command_name name
|
9
9
|
|
10
|
+
formatters = [SimpleCov::Formatter::QualityFormatter]
|
11
|
+
|
10
12
|
if ENV['TRAVIS']
|
11
|
-
require '
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
require 'codeclimate-test-reporter'
|
14
|
+
|
15
|
+
if CodeClimate::TestReporter.run?
|
16
|
+
formatters << CodeClimate::TestReporter::Formatter
|
17
|
+
end
|
16
18
|
end
|
19
|
+
|
20
|
+
formatter SimpleCov::Formatter::MultiFormatter[*formatters]
|
17
21
|
end
|
18
22
|
end
|
19
23
|
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
|
+
version: 1.4.0
|
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: 2015-01-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: hiredis
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.5'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.5'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: connection_pool
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,6 +80,20 @@ dependencies:
|
|
66
80
|
- - ">="
|
67
81
|
- !ruby/object:Gem::Version
|
68
82
|
version: '2'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: msgpack
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.5'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.5'
|
69
97
|
description: ActiveModel + Redis
|
70
98
|
email:
|
71
99
|
- port001@gmail.com
|
@@ -73,7 +101,6 @@ executables: []
|
|
73
101
|
extensions: []
|
74
102
|
extra_rdoc_files: []
|
75
103
|
files:
|
76
|
-
- ".coveralls.yml"
|
77
104
|
- ".gitignore"
|
78
105
|
- ".rubocop.yml"
|
79
106
|
- ".ruby-gemset"
|
@@ -84,6 +111,10 @@ files:
|
|
84
111
|
- LICENSE.txt
|
85
112
|
- README.md
|
86
113
|
- Rakefile
|
114
|
+
- benchmark/bench.rb
|
115
|
+
- benchmark/find.rb
|
116
|
+
- benchmark/persistence.rb
|
117
|
+
- benchmark/redis/connection/fakedis.rb
|
87
118
|
- lib/modis.rb
|
88
119
|
- lib/modis/attribute.rb
|
89
120
|
- lib/modis/configuration.rb
|
@@ -125,7 +156,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
125
156
|
version: '0'
|
126
157
|
requirements: []
|
127
158
|
rubyforge_project:
|
128
|
-
rubygems_version: 2.
|
159
|
+
rubygems_version: 2.4.5
|
129
160
|
signing_key:
|
130
161
|
specification_version: 4
|
131
162
|
summary: ActiveModel + Redis
|
data/.coveralls.yml
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
service-name: travis-ci
|