redis_model 0.1.0.pre3
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 +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
|