redis_model 0.1.0.pre3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +187 -0
- data/Rakefile +15 -0
- data/lib/redis_model/adapters/paperclip.rb +51 -0
- data/lib/redis_model/attribute.rb +124 -0
- data/lib/redis_model/base.rb +67 -0
- data/lib/redis_model/belonged_to.rb +27 -0
- data/lib/redis_model/class_attribute.rb +50 -0
- data/lib/redis_model/configurations.rb +15 -0
- data/lib/redis_model/helpers/sorted_set_paginator.rb +80 -0
- data/lib/redis_model/intersected.rb +17 -0
- data/lib/redis_model/schema.rb +114 -0
- data/lib/redis_model/types/base.rb +32 -0
- data/lib/redis_model/types/base_value.rb +26 -0
- data/lib/redis_model/types/counter.rb +25 -0
- data/lib/redis_model/types/float.rb +17 -0
- data/lib/redis_model/types/hash.rb +53 -0
- data/lib/redis_model/types/integer.rb +17 -0
- data/lib/redis_model/types/list.rb +40 -0
- data/lib/redis_model/types/set.rb +59 -0
- data/lib/redis_model/types/sorted_set.rb +184 -0
- data/lib/redis_model/types/string.rb +11 -0
- data/lib/redis_model/types/timestamp.rb +26 -0
- data/lib/redis_model/version.rb +3 -0
- data/lib/redis_model.rb +37 -0
- data/redis_model.gemspec +28 -0
- data/spec/redis_model/attribute_spec.rb +77 -0
- data/spec/redis_model/base_spec.rb +34 -0
- data/spec/redis_model/class_attribute_spec.rb +16 -0
- data/spec/redis_model/helpers/sorted_set_paginator_spec.rb +33 -0
- data/spec/redis_model/schema_spec.rb +118 -0
- data/spec/redis_model/types/base_spec.rb +28 -0
- data/spec/redis_model/types/counter_spec.rb +32 -0
- data/spec/redis_model/types/float_spec.rb +20 -0
- data/spec/redis_model/types/hash_spec.rb +55 -0
- data/spec/redis_model/types/integer_spec.rb +22 -0
- data/spec/redis_model/types/list_spec.rb +55 -0
- data/spec/redis_model/types/set_spec.rb +62 -0
- data/spec/redis_model/types/sorted_set_spec.rb +303 -0
- data/spec/redis_model/types/string_spec.rb +28 -0
- data/spec/redis_model/types/timestamp_spec.rb +22 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/support/dynamic_class.rb +5 -0
- metadata +190 -0
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class TestModel
|
4
|
+
attr_accessor :id, :custom
|
5
|
+
|
6
|
+
def initialize(id, custom = nil)
|
7
|
+
@id = id
|
8
|
+
@custom = custom
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe RedisModel::Attribute do
|
13
|
+
let(:parent_klass) { dynamic_class(TestModel) }
|
14
|
+
|
15
|
+
before { parent_klass.send(:include, RedisModel::Attribute) }
|
16
|
+
|
17
|
+
describe '.redis_model_attribute' do
|
18
|
+
let(:attribute_name) { :my_counter }
|
19
|
+
let(:attribute_type) { :counter }
|
20
|
+
let(:test_id) { 'test' }
|
21
|
+
|
22
|
+
it { expect { parent_klass.redis_model_attribute attribute_name, attribute_type }.to change { parent_klass.new(test_id).respond_to?(attribute_name) } }
|
23
|
+
it { expect { parent_klass.redis_model_attribute attribute_name, attribute_type }.to change { parent_klass.new(test_id).respond_to?(:"#{attribute_name}=") } }
|
24
|
+
|
25
|
+
context 'when belonged_to klass is defined' do
|
26
|
+
let(:key_label) { parent_klass.new(test_id).send(attribute_name).key_label }
|
27
|
+
|
28
|
+
before { parent_klass.redis_model_attribute attribute_name, attribute_type }
|
29
|
+
|
30
|
+
it { expect(parent_klass.new(test_id).send(attribute_name)).to be_kind_of(RedisModel::BelongedTo) }
|
31
|
+
it { expect(parent_klass.new(test_id).send(attribute_name).class.included_modules).to include(RedisModel::Types::Counter) }
|
32
|
+
it { expect(key_label).to end_with(test_id) }
|
33
|
+
it { expect(key_label).to include(parent_klass.to_s.underscore) }
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'when parent klass is inherited' do
|
37
|
+
let(:child_klass) { dynamic_class(parent_klass) }
|
38
|
+
|
39
|
+
it { expect { parent_klass.redis_model_attribute attribute_name, attribute_type }.to change { child_klass.new(test_id).respond_to?(attribute_name) } }
|
40
|
+
it { expect { parent_klass.redis_model_attribute attribute_name, attribute_type }.to change { child_klass.new(test_id).respond_to?(:"#{attribute_name}=") } }
|
41
|
+
|
42
|
+
context 'when belonged_to klass is defined' do
|
43
|
+
before { parent_klass.redis_model_attribute attribute_name, attribute_type }
|
44
|
+
|
45
|
+
it { expect(parent_klass.new(test_id).send(attribute_name).class).to eq(child_klass.new(test_id).send(attribute_name).class) }
|
46
|
+
it { expect(parent_klass.new(test_id).send(attribute_name).key_label).to eq(child_klass.new(test_id).send(attribute_name).key_label) }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'when foreign_key option is specified' do
|
51
|
+
let(:custom_id) { 'customid' }
|
52
|
+
let(:key_label) { parent_klass.new(test_id, custom_id).send(attribute_name).key_label }
|
53
|
+
|
54
|
+
before { parent_klass.redis_model_attribute attribute_name, attribute_type, foreign_key: :custom }
|
55
|
+
|
56
|
+
it { expect(key_label).to end_with(custom_id) }
|
57
|
+
it { expect(key_label).to include(parent_klass.to_s.underscore) }
|
58
|
+
it { expect(key_label).to end_with(custom_id) }
|
59
|
+
it { expect(key_label).not_to end_with(test_id) }
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '.redis_model_attributes' do
|
63
|
+
it { expect(parent_klass.redis_model_attributes).to be_kind_of(RedisModel::Attribute::DefinitionHelper) }
|
64
|
+
it { expect { parent_klass.redis_model_attributes { counter :my_counter } }.to change { parent_klass.new(test_id).methods } }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe RedisModel::Attribute::DefinitionHelper do
|
69
|
+
let(:parent_klass) { dynamic_class(TestModel) }
|
70
|
+
let(:definition_helper) { RedisModel::Attribute::DefinitionHelper.new parent_klass, {} }
|
71
|
+
|
72
|
+
it { expect(definition_helper).to respond_to(:counter) }
|
73
|
+
it { expect(definition_helper).to respond_to(:set) }
|
74
|
+
it { expect(definition_helper).to respond_to(:sorted_set) }
|
75
|
+
it { expect { definition_helper.counter :my_counter }.to change { parent_klass.new('test').methods } }
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RedisModel::Base do
|
4
|
+
let(:klass) { dynamic_class(RedisModel::Base) }
|
5
|
+
let(:another_klass) { dynamic_class(RedisModel::Base, 'Another') }
|
6
|
+
|
7
|
+
describe '.data_type' do
|
8
|
+
it { expect { klass.data_type(:value) }.to change { RedisModel::Schema.collection.keys }.by([klass]) }
|
9
|
+
it { expect { klass.data_type(:string) }.to change { RedisModel::Schema.collection[klass] }.from(nil) }
|
10
|
+
it { expect { klass.data_type(:string) }.to change { klass.included_modules.include?(RedisModel::Types::String) }.from(false).to(true) }
|
11
|
+
|
12
|
+
context 'when child class tries to redefine data type' do
|
13
|
+
let(:child_klass) { dynamic_class(klass, 'Child') }
|
14
|
+
|
15
|
+
before { klass.data_type(:value) }
|
16
|
+
|
17
|
+
it { expect { child_klass.data_type(:value) }.to raise_error(RedisModel::Schema::DuplicateDefinition) }
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'when another class defines its data type' do
|
21
|
+
before { klass.data_type(:value) }
|
22
|
+
|
23
|
+
it { expect { another_klass.data_type(:string) }.not_to change { RedisModel::Schema.find(klass) } }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '.connection' do
|
28
|
+
before { klass.data_type :counter }
|
29
|
+
before { another_klass.data_type :string }
|
30
|
+
|
31
|
+
it { expect(klass.connection).to be_kind_of(Redis) }
|
32
|
+
it { expect(klass.connection).to eq(another_klass.connection) }
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'redis_model/class_attribute'
|
3
|
+
|
4
|
+
class TestClass
|
5
|
+
include RedisModel::ClassAttribute
|
6
|
+
|
7
|
+
redis_class_attribute :something, :set
|
8
|
+
end
|
9
|
+
|
10
|
+
describe RedisModel::ClassAttribute do
|
11
|
+
context '.redis_class_attribue' do
|
12
|
+
it { expect(TestClass).to be_respond_to(:something) }
|
13
|
+
it { expect(TestClass).to be_respond_to(:something=) }
|
14
|
+
it { expect(TestClass.something).to be_kind_of(RedisModel::Base) }
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'redis_model/helpers/sorted_set_paginator'
|
3
|
+
|
4
|
+
describe RedisModel::Helpers::SortedSetPaginator do
|
5
|
+
let(:klass) { dynamic_class(RedisModel::Base) }
|
6
|
+
let(:sorted_set) { klass.new }
|
7
|
+
let(:paginator) { RedisModel::Helpers::SortedSetPaginator.new(sorted_set) }
|
8
|
+
|
9
|
+
before { klass.data_type :sorted_set }
|
10
|
+
before { (1..10).each { |number| sorted_set.put(number, number) } }
|
11
|
+
|
12
|
+
describe '#page' do
|
13
|
+
it { expect(paginator.per(1).page(1).map(&:to_i)).to eq([10]) }
|
14
|
+
it { expect(paginator.per(1).page(2).map(&:to_i)).to eq([9]) }
|
15
|
+
it { expect(paginator.per(1).page(10).map(&:to_i)).to eq([1]) }
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#per' do
|
19
|
+
it { expect(paginator.per(2).page(1).map(&:to_i)).to eq([10, 9]) }
|
20
|
+
it { expect(paginator.per(3).page(1).map(&:to_i)).to eq([10, 9, 8]) }
|
21
|
+
it { expect(paginator.per(4).page(1).map(&:to_i)).to eq([10, 9, 8, 7]) }
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#max_id' do
|
25
|
+
it { expect(paginator.max_id(3).map(&:to_i)).to eq([2, 1]) }
|
26
|
+
it { expect(paginator.max_id(4).map(&:to_i)).to eq([3, 2, 1]) }
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#since_id' do
|
30
|
+
it { expect(paginator.since_id(8).map(&:to_i)).to eq([10, 9]) }
|
31
|
+
it { expect(paginator.since_id(9).map(&:to_i)).to eq([10]) }
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'redis_model/schema'
|
3
|
+
|
4
|
+
describe RedisModel::Schema do
|
5
|
+
let(:random_string) { SecureRandom.base64(4).tr('+/=lIO0', 'pqrsxyz') }
|
6
|
+
|
7
|
+
describe '.collection' do
|
8
|
+
it { expect(RedisModel::Schema.collection).to be_kind_of(Hash) }
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '.find' do
|
12
|
+
let(:parent_klass) { Class.new }
|
13
|
+
let(:child_klass) { Class.new parent_klass }
|
14
|
+
|
15
|
+
before { RedisModel::Schema.collection.clear }
|
16
|
+
|
17
|
+
context 'when there is no entry of direct ancestor' do
|
18
|
+
it { expect(RedisModel::Schema.find(parent_klass)).to be_nil }
|
19
|
+
it { expect(RedisModel::Schema.find(child_klass)).to be_nil }
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'when collection is populated' do
|
23
|
+
let(:value) { 1234 }
|
24
|
+
|
25
|
+
before { RedisModel::Schema.collection[child_klass] = value }
|
26
|
+
|
27
|
+
it { expect(RedisModel::Schema.find(child_klass)).to eq(value) }
|
28
|
+
it { expect(RedisModel::Schema.find(parent_klass)).to be_nil }
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'when collection is populated by both' do
|
32
|
+
let(:parent_value) { 1234 }
|
33
|
+
let(:child_value) { 4321 }
|
34
|
+
|
35
|
+
before { RedisModel::Schema.collection[parent_klass] = parent_value }
|
36
|
+
before { RedisModel::Schema.collection[child_klass] = child_value }
|
37
|
+
|
38
|
+
it { expect(RedisModel::Schema.find(parent_klass)).to eq(parent_value) }
|
39
|
+
it { expect(RedisModel::Schema.find(child_klass)).to eq(child_value) }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '.register' do
|
44
|
+
let(:parent_klass) { Class.new.tap { |k| Object.const_set("Parent#{random_string}", k) } }
|
45
|
+
let(:child_klass) { Class.new parent_klass.tap { |k| Object.const_set("Child#{random_string}", k) } }
|
46
|
+
|
47
|
+
before { RedisModel::Schema.collection.clear }
|
48
|
+
|
49
|
+
context 'when data_type is invalid' do
|
50
|
+
it { expect { RedisModel::Schema.register(parent_klass, data_type: :nothing) }.to raise_error(RedisModel::Schema::UnknownType) }
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'when data_type is valid' do
|
54
|
+
it { expect { RedisModel::Schema.register(parent_klass, data_type: :string) }.not_to raise_error }
|
55
|
+
it { expect(RedisModel::Schema.register(parent_klass, data_type: :string)).to eq(RedisModel::Types::String) }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '#initialize' do
|
60
|
+
context 'when invalid data_type key is given' do
|
61
|
+
it { expect { RedisModel::Schema.new(data_type: :something_i_dont_know) }.to raise_error(RedisModel::Schema::UnknownType) }
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'when valid data_type key is given' do
|
65
|
+
let(:klass) { Class.new.tap { |k| Object.const_set("Parent#{random_string}", k) } }
|
66
|
+
let(:data_type) { :string }
|
67
|
+
let(:schema) { RedisModel::Schema.new(data_type: data_type, klass: klass) }
|
68
|
+
|
69
|
+
it { expect { schema }.not_to raise_error }
|
70
|
+
it { expect(schema.klass).to eq(klass) }
|
71
|
+
it { expect(schema.data_type).to eq(data_type) }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '#custom_key_label' do
|
76
|
+
let(:string_child_klass) { Class.new(String).tap { |k| Object.const_set("String#{random_string}", k) } }
|
77
|
+
let(:schema) { RedisModel::Schema.new data_type: :string, klass: string_child_klass }
|
78
|
+
let(:object) { string_child_klass.new('test') }
|
79
|
+
|
80
|
+
context 'when block is given' do
|
81
|
+
it { expect { schema.custom_key_label { |o| o.reverse } }.not_to raise_error }
|
82
|
+
it { expect { schema.custom_key_label { |o| o.reverse } }.to change { schema.key_label(object).end_with?(':tset') } }
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'when method is given' do
|
86
|
+
it { expect { schema.custom_key_label(&:reverse) }.not_to raise_error }
|
87
|
+
it { expect { schema.custom_key_label(&:reverse) }.to change { schema.key_label(object).end_with?(':tset') } }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe '#key_label' do
|
92
|
+
let(:klass) { Class.new.tap { |k| Object.const_set("Klass#{random_string}", k) } }
|
93
|
+
let(:schema) { RedisModel::Schema.new klass: klass, data_type: :string }
|
94
|
+
let(:object) { klass.new }
|
95
|
+
let(:app_name) { nil }
|
96
|
+
|
97
|
+
before { RedisModel::Configurations.instance.app_name = app_name }
|
98
|
+
|
99
|
+
context 'when no custom key labels and app name present' do
|
100
|
+
it { expect(schema.key_label(object)).to include(klass.name.underscore) }
|
101
|
+
end
|
102
|
+
|
103
|
+
context 'when custom key label presents' do
|
104
|
+
let(:label_text) { 'test' }
|
105
|
+
before { schema.custom_key_label { |o| label_text } }
|
106
|
+
|
107
|
+
it { expect(schema.key_label(object)).to include(klass.name.underscore) }
|
108
|
+
it { expect(schema.key_label(object)).to include(label_text) }
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'when app name presents' do
|
112
|
+
let(:app_name) { 'app' }
|
113
|
+
|
114
|
+
it { expect(schema.key_label(object)).to include(klass.name.underscore) }
|
115
|
+
it { expect(schema.key_label(object)).to include(app_name) }
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RedisModel::Types::Base do
|
4
|
+
let(:klass) { dynamic_class(RedisModel::Base) }
|
5
|
+
let(:object) { klass.new }
|
6
|
+
|
7
|
+
before { RedisModel::Schema.register(klass, data_type: :string) }
|
8
|
+
before { klass.send(:include, RedisModel::Types::Base) }
|
9
|
+
|
10
|
+
describe '#exists?' do
|
11
|
+
it { expect(object.exists?).to be_false }
|
12
|
+
it { expect { RedisModel::Base.connection.set(object.key_label, 'value') }.to change { object.exists? } }
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#del' do
|
16
|
+
context 'when object exists' do
|
17
|
+
before { RedisModel::Base.connection.set(object.key_label, 'value') }
|
18
|
+
|
19
|
+
it { expect { object.del }.to change { object.exists? } }
|
20
|
+
it { expect(object.del).to eq(1) }
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'when object does not exist' do
|
24
|
+
it { expect { object.del }.not_to change { object.exists? } }
|
25
|
+
it { expect(object.del).to eq(0) }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RedisModel::Types::Counter do
|
4
|
+
let(:klass) { dynamic_class(RedisModel::Base) }
|
5
|
+
let(:object) { klass.new }
|
6
|
+
|
7
|
+
before { klass.data_type :counter }
|
8
|
+
|
9
|
+
describe '#incr' do
|
10
|
+
it { expect { object.incr }.to change { object.to_i }.from(0).to(1) }
|
11
|
+
it { expect(object.incr).to eq(1) }
|
12
|
+
|
13
|
+
context 'when argument is given' do
|
14
|
+
let(:by) { 3 }
|
15
|
+
|
16
|
+
it { expect { object.incr(by) }.to change { object.to_i }.from(0).to(by) }
|
17
|
+
it { expect(object.incr(by)).to eq(by) }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#to_i' do
|
22
|
+
it { expect(object.to_i).to eq(0) }
|
23
|
+
|
24
|
+
context 'when value was set previously' do
|
25
|
+
let(:value) { 3 }
|
26
|
+
|
27
|
+
before { RedisModel::Base.connection.set(object.key_label, value) }
|
28
|
+
|
29
|
+
it { expect(object.to_i).to eq(value) }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RedisModel::Types::Float do
|
4
|
+
let(:klass) { dynamic_class(RedisModel::Base) }
|
5
|
+
let(:object) { klass.new }
|
6
|
+
|
7
|
+
before { klass.data_type :float }
|
8
|
+
|
9
|
+
describe '#to_f' do
|
10
|
+
it { expect(object.to_f).to be_nil }
|
11
|
+
|
12
|
+
context 'when value was set before' do
|
13
|
+
let(:value) { 1.23 }
|
14
|
+
|
15
|
+
before { object.set 1.23 }
|
16
|
+
|
17
|
+
it { expect(object.to_f).to eq(1.23) }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RedisModel::Types::Hash do
|
4
|
+
let(:klass) { dynamic_class(RedisModel::Base) }
|
5
|
+
let(:object) { klass.new }
|
6
|
+
|
7
|
+
before { klass.data_type :hash }
|
8
|
+
|
9
|
+
describe '#[]=' do
|
10
|
+
let(:key) { :some_key }
|
11
|
+
let(:value) { 'hello world' }
|
12
|
+
|
13
|
+
it { expect(object.[]=(key, value)).to eq(value) }
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#[]' do
|
17
|
+
let(:key) { :some_key }
|
18
|
+
|
19
|
+
context 'when value was not set before' do
|
20
|
+
it { expect(object[key]).to be_nil }
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'when value was set before' do
|
24
|
+
let(:value) { 'hello world' }
|
25
|
+
|
26
|
+
before { object[key] = value }
|
27
|
+
|
28
|
+
it { expect(object[key]).to eq(value) }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#incr' do
|
33
|
+
let(:key) { :some_key }
|
34
|
+
|
35
|
+
context 'when key does not exist before' do
|
36
|
+
it { expect(object.incr(key)).to eq(1) }
|
37
|
+
it { expect { object.incr(key) }.to change { object[key] }.from(nil).to(1.to_s) }
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'when amount is given' do
|
41
|
+
let(:by) { 3 }
|
42
|
+
|
43
|
+
it { expect(object.incr(key, by)).to eq(by) }
|
44
|
+
it { expect { object.incr(key, by) }.to change { object[key] }.from(nil).to(by.to_s) }
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'when key was set before' do
|
48
|
+
let(:initial) { 2 }
|
49
|
+
|
50
|
+
before { object[key] = initial }
|
51
|
+
|
52
|
+
it { expect { object.incr(key) }.to change { object[key] }.from(initial.to_s).to((initial + 1).to_s) }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RedisModel::Types::Integer do
|
4
|
+
let(:klass) { dynamic_class(RedisModel::Base) }
|
5
|
+
let(:object) { klass.new }
|
6
|
+
|
7
|
+
before { klass.data_type :integer }
|
8
|
+
|
9
|
+
describe '#to_i' do
|
10
|
+
context 'when no value was set before' do
|
11
|
+
it { expect(object.to_i).to be_nil }
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'when value was set before' do
|
15
|
+
let(:value) { 2 }
|
16
|
+
|
17
|
+
before { RedisModel::Base.connection.set(object.key_label, value) }
|
18
|
+
|
19
|
+
it { expect(object.to_i).to eq(value) }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RedisModel::Types::List do
|
4
|
+
let(:klass) { dynamic_class(RedisModel::Base) }
|
5
|
+
let(:object) { klass.new }
|
6
|
+
|
7
|
+
before { klass.data_type :list }
|
8
|
+
|
9
|
+
describe '#to_a' do
|
10
|
+
context 'when list does not exist' do
|
11
|
+
it { expect(object.to_a).to eq([]) }
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'when list has been populated before' do
|
15
|
+
let(:elements) { ['testelement1', 'testelement2'] }
|
16
|
+
|
17
|
+
before { elements.each { |element| RedisModel::Base.connection.rpush(object.key_label, element) } }
|
18
|
+
|
19
|
+
it { expect(object.to_a).to eq(elements) }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#count' do
|
24
|
+
context 'when list does not exist' do
|
25
|
+
it { expect(object.count).to eq(0) }
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'when list has been populated before' do
|
29
|
+
let(:elements) { ['testelement1', 'testelement2'] }
|
30
|
+
|
31
|
+
before { elements.each { |element| RedisModel::Base.connection.rpush object.key_label, element } }
|
32
|
+
|
33
|
+
it { expect(object.count).to eq(elements.length) }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#[]' do
|
38
|
+
context 'when list does not exist' do
|
39
|
+
it { expect(object[1]).to be_nil }
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'when list has been populated before' do
|
43
|
+
let(:elements) { ['testelement1', 'testelement2'] }
|
44
|
+
|
45
|
+
before { elements.each { |element| RedisModel::Base.connection.rpush object.key_label, element } }
|
46
|
+
|
47
|
+
it { expect(object[0]).to eq(elements[0]) }
|
48
|
+
it { expect(object[1]).to eq(elements[1]) }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#<<' do
|
53
|
+
it { expect { object << 1 }.to change { object.count }.by(1) }
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RedisModel::Types::Set do
|
4
|
+
let(:klass) { dynamic_class(RedisModel::Base) }
|
5
|
+
let(:object) { klass.new }
|
6
|
+
|
7
|
+
before { klass.data_type :set }
|
8
|
+
|
9
|
+
describe '#to_a' do
|
10
|
+
context 'when set does not exist' do
|
11
|
+
it { expect(object.to_a).to eq([]) }
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'when set has been populated before' do
|
15
|
+
let(:elements) { ['testelement1', 'testelement2'] }
|
16
|
+
|
17
|
+
before { elements.each { |element| RedisModel::Base.connection.sadd(object.key_label, element) } }
|
18
|
+
|
19
|
+
it { expect(object.to_a.sort).to eq(elements.sort) }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#count' do
|
24
|
+
context 'when set does not exist' do
|
25
|
+
it { expect(object.count).to eq(0) }
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'when set has been populated before' do
|
29
|
+
let(:elements) { ['testelement1', 'testelement2'] }
|
30
|
+
|
31
|
+
before { elements.each { |element| RedisModel::Base.connection.sadd(object.key_label, element) } }
|
32
|
+
|
33
|
+
it { expect(object.count).to eq(elements.count) }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#<<' do
|
38
|
+
it { expect { object << 1 }.to change { object.count }.by(1) }
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#remove' do
|
42
|
+
let(:elements) { ['testelement1', 'testelement2'] }
|
43
|
+
|
44
|
+
before { elements.each { |element| RedisModel::Base.connection.sadd(object.key_label, element) } }
|
45
|
+
|
46
|
+
context 'when removing existing element' do
|
47
|
+
it { expect { object.remove(elements.first) }.to change { object.count }.by(-1) }
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'when removing non-existent element' do
|
51
|
+
it { expect { object.remove('nonexistent') }.not_to change { object.count } }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '#pick' do
|
56
|
+
let(:elements) { ['testelement1', 'testelement2'] }
|
57
|
+
|
58
|
+
before { elements.each { |element| RedisModel::Base.connection.sadd(object.key_label, element) } }
|
59
|
+
|
60
|
+
it { expect(object.pick(5).all? { |e| elements.include?(e) }).to be_true }
|
61
|
+
end
|
62
|
+
end
|