mongo-lock 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +51 -0
- data/LICENSE +22 -0
- data/README.md +291 -0
- data/Rakefile +8 -0
- data/lib/mongo-lock.rb +296 -0
- data/lib/mongo-lock/configuration.rb +72 -0
- data/lib/mongo-lock/version.rb +5 -0
- data/mongo-lock.gemspec +30 -0
- data/mongoid.yml +6 -0
- data/spec/acquire_spec.rb +184 -0
- data/spec/acquired_spec.rb +52 -0
- data/spec/available_spec.rb +68 -0
- data/spec/clear_expired_spec.rb +20 -0
- data/spec/configuration_spec.rb +238 -0
- data/spec/configure_spec.rb +87 -0
- data/spec/ensure_indexes_spec.rb +25 -0
- data/spec/expired_spec.rb +40 -0
- data/spec/extend_by_spec.rb +133 -0
- data/spec/initialise_spec.rb +36 -0
- data/spec/release_all_spec.rb +78 -0
- data/spec/release_spec.rb +164 -0
- data/spec/spec_helper.rb +36 -0
- data/spec/support/mongo_helper.rb +19 -0
- metadata +141 -0
@@ -0,0 +1,72 @@
|
|
1
|
+
module Mongo
|
2
|
+
class Lock
|
3
|
+
class Configuration
|
4
|
+
|
5
|
+
attr_accessor :connections
|
6
|
+
attr_accessor :limit
|
7
|
+
attr_accessor :timeout_in
|
8
|
+
attr_accessor :frequency
|
9
|
+
attr_accessor :expires_after
|
10
|
+
attr_accessor :owner
|
11
|
+
attr_accessor :raise
|
12
|
+
|
13
|
+
def initialize defaults, options, &block
|
14
|
+
options = defaults.merge(options)
|
15
|
+
options[:collections] ||= {}
|
16
|
+
if options[:collection]
|
17
|
+
options[:collections][:default] = options[:collection]
|
18
|
+
end
|
19
|
+
options.each_pair do |key,value|
|
20
|
+
self.send(:"#{key}=",value)
|
21
|
+
end
|
22
|
+
yield self if block_given?
|
23
|
+
end
|
24
|
+
|
25
|
+
def collection= collection
|
26
|
+
collections[:default] = collection
|
27
|
+
end
|
28
|
+
|
29
|
+
def collection collection = :default
|
30
|
+
collection = collection.to_sym if collection.is_a? String
|
31
|
+
if collection.is_a? Symbol
|
32
|
+
collections[collection]
|
33
|
+
else
|
34
|
+
collection
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def collections= collections
|
39
|
+
@collections = collections
|
40
|
+
end
|
41
|
+
|
42
|
+
def set_collections_keep_default collections
|
43
|
+
collections[:default] = @collections[:default]
|
44
|
+
@collections = collections
|
45
|
+
end
|
46
|
+
|
47
|
+
def collections
|
48
|
+
@collections ||= {}
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_hash
|
52
|
+
{
|
53
|
+
timeout_in: timeout_in,
|
54
|
+
limit: limit,
|
55
|
+
frequency: frequency,
|
56
|
+
expires_after: expires_after,
|
57
|
+
owner: owner,
|
58
|
+
raise: raise
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
def owner
|
63
|
+
if @owner.is_a? Proc
|
64
|
+
@owner.call.to_s
|
65
|
+
else
|
66
|
+
@owner.to_s
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/mongo-lock.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'mongo-lock/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "mongo-lock"
|
8
|
+
spec.version = Mongo::Lock::VERSION
|
9
|
+
spec.authors = ["Matthew Spence"]
|
10
|
+
spec.email = "msaspence@gmail.com"
|
11
|
+
spec.homepage = "https://github.com/trakio/mongo-lock"
|
12
|
+
spec.summary = "Pessimistic locking for Ruby and MongoDB"
|
13
|
+
spec.description = "Key based pessimistic locking for Ruby and MongoDB. Is this key avaliable? Yes - Lock it for me for a sec will you. No - OK I'll just wait here until its ready."
|
14
|
+
spec.required_rubygems_version = ">= 1.3.6"
|
15
|
+
spec.license = 'MIT'
|
16
|
+
|
17
|
+
spec.files = `git ls-files`.split($/)
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
# s.add_dependency 'some-gem'
|
23
|
+
spec.extra_rdoc_files = ['README.md', 'LICENSE']
|
24
|
+
|
25
|
+
spec.add_development_dependency 'rspec'
|
26
|
+
spec.add_development_dependency 'fuubar'
|
27
|
+
spec.add_development_dependency 'pry'
|
28
|
+
spec.add_development_dependency 'activesupport'
|
29
|
+
|
30
|
+
end
|
data/mongoid.yml
ADDED
@@ -0,0 +1,184 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mongo::Lock do
|
4
|
+
|
5
|
+
describe '.acquire' do
|
6
|
+
|
7
|
+
it "creates and returns a new Mongo::Lock instance" do
|
8
|
+
expect(Mongo::Lock.acquire 'my_lock').to be_a Mongo::Lock
|
9
|
+
end
|
10
|
+
|
11
|
+
it "calls #acquire to acquire the lock" do
|
12
|
+
expect_any_instance_of(Mongo::Lock).to receive(:acquire)
|
13
|
+
Mongo::Lock.acquire 'my_lock'
|
14
|
+
end
|
15
|
+
|
16
|
+
context "when options are provided" do
|
17
|
+
|
18
|
+
it "passes them to the new lock" do
|
19
|
+
lock = Mongo::Lock.acquire('my_lock', { limit: 3 })
|
20
|
+
expect(lock.configuration.limit).to be 3
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#acquire' do
|
28
|
+
|
29
|
+
let(:lock) { Mongo::Lock.new 'my_lock', owner: 'spence' }
|
30
|
+
|
31
|
+
context "when lock is available" do
|
32
|
+
|
33
|
+
it "acquires the lock" do
|
34
|
+
lock.acquire
|
35
|
+
expect(collection.find(key: 'my_lock').count).to be 1
|
36
|
+
end
|
37
|
+
|
38
|
+
it "sets the lock to expire" do
|
39
|
+
lock.acquire
|
40
|
+
expect(collection.find(key: 'my_lock').first['expires_at']).to be_within(1.second).of(10.seconds.from_now)
|
41
|
+
expect(collection.find(key: 'my_lock').first['ttl']).to be_within(1.second).of(10.seconds.from_now)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "returns true" do
|
45
|
+
expect(lock.acquire).to be_true
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
context "when the frequency option is a Proc" do
|
51
|
+
|
52
|
+
let(:lock) { Mongo::Lock.new 'my_lock' }
|
53
|
+
|
54
|
+
it "should call the Proc with the attempt number" do
|
55
|
+
collection.insert key: 'my_lock', owner: 'tobie', expires_at: 0.04.seconds.from_now
|
56
|
+
proc = Proc.new{ |x| x }
|
57
|
+
expect(proc).to receive(:call).with(1).and_return(0.01)
|
58
|
+
expect(proc).to receive(:call).with(2).and_return(0.01)
|
59
|
+
expect(proc).to receive(:call).with(3).and_return(0.01)
|
60
|
+
lock.acquire limit: 3, frequency: proc
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
context "when the lock is unavailable" do
|
66
|
+
|
67
|
+
it "retries until it can acquire it" do
|
68
|
+
collection.insert key: 'my_lock', owner: 'tobie', expires_at: 0.1.seconds.from_now
|
69
|
+
lock.acquire frequency: 0.01, timeout_in: 0.2, limit: 20
|
70
|
+
expect(collection.find(key: 'my_lock', owner: 'spence').count).to be 1
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
context "when the lock is already acquired but by the same owner" do
|
76
|
+
|
77
|
+
before :each do
|
78
|
+
collection.insert key: 'my_lock', owner: 'spence', expires_at: 10.minutes.from_now
|
79
|
+
end
|
80
|
+
|
81
|
+
it "doesn't create a new lock" do
|
82
|
+
lock.acquire
|
83
|
+
expect(collection.find(key: 'my_lock').count).to be 1
|
84
|
+
end
|
85
|
+
|
86
|
+
it "returns true" do
|
87
|
+
expect(lock.acquire).to be_true
|
88
|
+
end
|
89
|
+
|
90
|
+
it "sets this instance as acquired" do
|
91
|
+
lock.acquire
|
92
|
+
expect(lock.instance_variable_get('@acquired')).to be_true
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
context "when the lock cannot be acquired" do
|
98
|
+
|
99
|
+
context "and acquisition timeout_in occurs" do
|
100
|
+
|
101
|
+
let(:lock) { Mongo::Lock.new 'my_lock', owner: 'spence', timeout_in: 0.03, frequency: 0.01 }
|
102
|
+
|
103
|
+
it "should return false" do
|
104
|
+
collection.insert key: 'my_lock', owner: 'tobie', expires_at: 0.2.seconds.from_now
|
105
|
+
expect(lock.acquire).to be_false
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
context "and acquisition limit is exceeded" do
|
111
|
+
|
112
|
+
let(:lock) { Mongo::Lock.new 'my_lock', owner: 'spence', timeout_in: 0.4, limit: 3, frequency: 0.01 }
|
113
|
+
|
114
|
+
it "should return false" do
|
115
|
+
collection.insert key: 'my_lock', owner: 'tobie', expires_at: 0.2.seconds.from_now
|
116
|
+
expect(lock.acquire).to be_false
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
context "when the lock cannot be acquired and raise option is set to true" do
|
124
|
+
|
125
|
+
context "and acquisition timeout_in occurs" do
|
126
|
+
|
127
|
+
let(:lock) { Mongo::Lock.new 'my_lock', owner: 'tobie', timeout_in: 0.4, frequency: 0.01, raise: true }
|
128
|
+
|
129
|
+
it "should raise Mongo::Lock::NotAcquiredError" do
|
130
|
+
collection.insert key: 'my_lock', owner: 'spence', expires_at: 0.2.seconds.from_now
|
131
|
+
expect{lock.acquire}.to raise_error Mongo::Lock::NotAcquiredError
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
context "and acquisition limit is exceeded" do
|
137
|
+
|
138
|
+
let(:lock) { Mongo::Lock.new 'my_lock', owner: 'tobie', timeout_in: 0.3, limit: 3, frequency: 0.01, raise: true }
|
139
|
+
|
140
|
+
it "should raise Mongo::Lock::NotAcquiredError" do
|
141
|
+
collection.insert key: 'my_lock', owner: 'spence', expires_at: 0.2.seconds.from_now
|
142
|
+
expect{lock.acquire}.to raise_error Mongo::Lock::NotAcquiredError
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
context "when options are provided" do
|
150
|
+
|
151
|
+
let(:lock) { Mongo::Lock.new 'my_lock', owner: 'tobie', timeout_in: 0.2, limit: 11, frequency: 0.01, raise: true }
|
152
|
+
|
153
|
+
it "overrides the lock's" do
|
154
|
+
collection.insert key: 'my_lock', owner: 'spence', expires_at: 0.1.seconds.from_now
|
155
|
+
expect(lock.acquire timeout_in: 0.05, limit: 3, frequency: 0.02, raise: false).to be_false
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
|
162
|
+
describe '.acquire!' do
|
163
|
+
|
164
|
+
let(:lock) { Mongo::Lock.new 'my_lock', owner: 'spence' }
|
165
|
+
|
166
|
+
it "calls .acquire with raise errors option set to true" do
|
167
|
+
expect(Mongo::Lock).to receive(:init_and_send).with('my_lock', { limit: 3 }, :acquire!)
|
168
|
+
Mongo::Lock.acquire! 'my_lock', limit: 3
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
describe '#acquire!' do
|
174
|
+
|
175
|
+
let(:lock) { Mongo::Lock.new 'my_lock', owner: 'spence' }
|
176
|
+
|
177
|
+
it "calls #acquire with raise errors option set to true" do
|
178
|
+
expect(lock).to receive(:acquire).with({ limit: 3, raise: true })
|
179
|
+
lock.acquire! limit: 3
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
183
|
+
|
184
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mongo::Lock do
|
4
|
+
|
5
|
+
describe '#acquired?' do
|
6
|
+
|
7
|
+
let(:lock) { Mongo::Lock.new 'my_lock', owner: 'spence', timeout_in: 0.01, frequency: 0.01 }
|
8
|
+
|
9
|
+
context "when the lock has been acquired" do
|
10
|
+
|
11
|
+
it "returns true" do
|
12
|
+
lock.acquire
|
13
|
+
expect(lock.acquired?).to be_true
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
context "when the lock hasn't been acquired" do
|
19
|
+
|
20
|
+
it "returns false" do
|
21
|
+
collection.insert key: 'my_lock', owner: 'tobie', expires_at: 1.minute.from_now
|
22
|
+
lock.acquire
|
23
|
+
expect(lock.acquired?).to be_false
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
context "when the lock was acquired but has since expired" do
|
29
|
+
|
30
|
+
it "returns false" do
|
31
|
+
collection.insert key: 'my_lock', owner: 'spence', expires_at: 0.01.seconds.from_now
|
32
|
+
lock.acquire
|
33
|
+
sleep 0.02
|
34
|
+
expect(lock.acquired?).to be_false
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
context "when the lock was acquired but has since been released" do
|
40
|
+
|
41
|
+
it "returns false" do
|
42
|
+
collection.insert key: 'my_lock', owner: 'tobie', expires_at: 1.minute.ago
|
43
|
+
lock.acquire
|
44
|
+
lock.release
|
45
|
+
expect(lock.acquired?).to be_false
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mongo::Lock do
|
4
|
+
|
5
|
+
describe '.available?' do
|
6
|
+
|
7
|
+
it "creates and returns a new Mongo::Lock instance" do
|
8
|
+
expect(Mongo::Lock.available? 'my_lock').to be_a Mongo::Lock
|
9
|
+
end
|
10
|
+
|
11
|
+
it "calls #available?" do
|
12
|
+
expect_any_instance_of(Mongo::Lock).to receive(:available?)
|
13
|
+
Mongo::Lock.available? 'my_lock'
|
14
|
+
end
|
15
|
+
|
16
|
+
context "when options are provided" do
|
17
|
+
|
18
|
+
it "passes them to the new lock" do
|
19
|
+
lock = Mongo::Lock.available?('my_lock', { owner: 'spence' })
|
20
|
+
expect(lock.configuration.owner).to eql 'spence'
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#available?' do
|
28
|
+
|
29
|
+
let(:lock) { Mongo::Lock.new 'my_lock', owner: 'spence', timeout_in: 0.01, frequency: 0.01 }
|
30
|
+
|
31
|
+
context "when the lock is available" do
|
32
|
+
|
33
|
+
it "returns true" do
|
34
|
+
expect(lock.available?).to be_true
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
context "when the lock is expired" do
|
40
|
+
|
41
|
+
it "returns true" do
|
42
|
+
collection.insert key: 'my_lock', owner: 'tobie', expires_at: 1.minute.ago
|
43
|
+
expect(lock.available?).to be_true
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
context "when the lock is already acquired but by this owner" do
|
49
|
+
|
50
|
+
it "returns true" do
|
51
|
+
collection.insert key: 'my_lock', owner: 'spence', expires_at: 1.minute.from_now
|
52
|
+
expect(lock.available?).to be_true
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
context "when the lock is already acquired" do
|
58
|
+
|
59
|
+
it "returns false" do
|
60
|
+
collection.insert key: 'my_lock', owner: 'tobie', expires_at: 1.minute.from_now
|
61
|
+
expect(lock.available?).to be_false
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mongo::Lock do
|
4
|
+
|
5
|
+
describe '.clear_expired' do
|
6
|
+
|
7
|
+
it "deletes expired locks in all collections" do
|
8
|
+
Mongo::Lock.configure collections: { default: collection, other: other_collection }
|
9
|
+
collection.insert owner: 'owner', key: 'my_lock', expires_at: 1.minute.from_now
|
10
|
+
collection.insert owner: 'owner', key: 'my_lock', expires_at: 1.minute.ago
|
11
|
+
other_collection.insert owner: 'owner', key: 'my_lock', expires_at: 1.minute.from_now
|
12
|
+
other_collection.insert owner: 'owner', key: 'my_lock', expires_at: 1.minute.ago
|
13
|
+
Mongo::Lock.clear_expired
|
14
|
+
expect(collection.find().count).to be 1
|
15
|
+
expect(other_collection.find().count).to be 1
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,238 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mongo::Lock::Configuration do
|
4
|
+
|
5
|
+
subject { Mongo::Lock::Configuration.new({}, {}) }
|
6
|
+
|
7
|
+
let (:collections_with_default) { { a: 'a', b: 'b', default: collection } }
|
8
|
+
let (:collections) { { a: 'a', b: 'b' } }
|
9
|
+
let (:collection) { 'default' }
|
10
|
+
|
11
|
+
describe '#initialize' do
|
12
|
+
|
13
|
+
context "when provided with a hash" do
|
14
|
+
|
15
|
+
it "sets each value" do
|
16
|
+
config = Mongo::Lock::Configuration.new({}, { limit: 3, timeout_in: 4 })
|
17
|
+
expect(config.limit).to be 3
|
18
|
+
expect(config.timeout_in).to be 4
|
19
|
+
end
|
20
|
+
|
21
|
+
context "when provided with a default connection" do
|
22
|
+
|
23
|
+
it "stores it in the connections hash as :default" do
|
24
|
+
config = Mongo::Lock::Configuration.new({}, { collection: collection, collections: collections })
|
25
|
+
expect(config.collections).to eql collections_with_default
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
context "when provided with a default" do
|
33
|
+
|
34
|
+
it "sets each value" do
|
35
|
+
config = Mongo::Lock::Configuration.new({ limit: 3, timeout_in: 4 }, { limit: 5 })
|
36
|
+
expect(config.limit).to be 5
|
37
|
+
expect(config.timeout_in).to be 4
|
38
|
+
end
|
39
|
+
|
40
|
+
context "when provided with a default connection" do
|
41
|
+
|
42
|
+
it "stores it in the connections hash as :default" do
|
43
|
+
config = Mongo::Lock::Configuration.new({ collections: collections }, { collection: collection})
|
44
|
+
expect(config.collections).to eql collections_with_default
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#collections=" do
|
54
|
+
|
55
|
+
it "should set collections hash" do
|
56
|
+
subject.collections = collections
|
57
|
+
expect(subject.instance_variable_get('@collections')).to be collections
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should remove default from collections hash" do
|
61
|
+
subject.instance_variable_set('@collections', collections_with_default)
|
62
|
+
subject.collections = collections
|
63
|
+
expect(subject.instance_variable_get('@collections')).to be collections
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "#set_collections_keep_default" do
|
69
|
+
|
70
|
+
it "should keep default in the collections hash" do
|
71
|
+
subject.instance_variable_set('@collections', collections_with_default)
|
72
|
+
subject.set_collections_keep_default collections
|
73
|
+
expect(subject.instance_variable_get('@collections')).to eql collections_with_default
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "#collections" do
|
79
|
+
|
80
|
+
it "should return the collections hash" do
|
81
|
+
subject.instance_variable_set('@collections', collections)
|
82
|
+
expect(subject.collections).to be collections
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "#collection=" do
|
88
|
+
|
89
|
+
it "should set the default collection" do
|
90
|
+
subject.collection = collection
|
91
|
+
expect(subject.instance_variable_get('@collections')[:default]).to be collection
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "#collection" do
|
97
|
+
|
98
|
+
context "when a symbol is provided" do
|
99
|
+
|
100
|
+
it "should return that collection" do
|
101
|
+
subject.instance_variable_set('@collections', collections)
|
102
|
+
expect(subject.collection :a).to eql 'a'
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
context "when a string is provided" do
|
108
|
+
|
109
|
+
it "should return that collection" do
|
110
|
+
subject.instance_variable_set('@collections', collections)
|
111
|
+
expect(subject.collection 'a').to eql 'a'
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
context "when it's any other object is" do
|
117
|
+
|
118
|
+
it "should return that collection" do
|
119
|
+
my_collection = Object.new
|
120
|
+
subject.instance_variable_set('@collections', collections)
|
121
|
+
expect(subject.collection my_collection).to be my_collection
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
context "when a symbol isn't provided" do
|
127
|
+
|
128
|
+
it "should return the default collection" do
|
129
|
+
subject.instance_variable_set('@collections', collections_with_default)
|
130
|
+
expect(subject.collection).to eql 'default'
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "#timeout_in=" do
|
138
|
+
|
139
|
+
it "should set the timeout_in value" do
|
140
|
+
subject.timeout_in = 123
|
141
|
+
expect(subject.instance_variable_get('@timeout_in')).to be 123
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
describe "#timeout_in" do
|
147
|
+
|
148
|
+
it "should return the timeout_in value" do
|
149
|
+
subject.instance_variable_set('@timeout_in', 456)
|
150
|
+
expect(subject.timeout_in).to be 456
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
describe "#limit=" do
|
156
|
+
|
157
|
+
it "should set the limit value" do
|
158
|
+
subject.limit = 7
|
159
|
+
expect(subject.instance_variable_get('@limit')).to be 7
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
|
164
|
+
describe "#limit" do
|
165
|
+
|
166
|
+
it "should return the limit value" do
|
167
|
+
subject.instance_variable_set('@limit', 8)
|
168
|
+
expect(subject.limit).to be 8
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
describe "#frequency=" do
|
174
|
+
|
175
|
+
it "should set the frequency value" do
|
176
|
+
subject.frequency = 9
|
177
|
+
expect(subject.instance_variable_get('@frequency')).to be 9
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
181
|
+
|
182
|
+
describe "#frequency" do
|
183
|
+
|
184
|
+
it "should return the frequency value" do
|
185
|
+
subject.instance_variable_set('@frequency', 1)
|
186
|
+
expect(subject.frequency).to be 1
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
190
|
+
|
191
|
+
describe "#expires_after=" do
|
192
|
+
|
193
|
+
it "should set the expires_after value" do
|
194
|
+
subject.expires_after = 9
|
195
|
+
expect(subject.instance_variable_get('@expires_after')).to be 9
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
199
|
+
|
200
|
+
describe "#expires_after" do
|
201
|
+
|
202
|
+
it "should return the expires_after value" do
|
203
|
+
subject.instance_variable_set('@expires_after', 1)
|
204
|
+
expect(subject.expires_after).to be 1
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
208
|
+
|
209
|
+
describe "#owner" do
|
210
|
+
|
211
|
+
it "should return the owner value" do
|
212
|
+
subject.instance_variable_set('@owner', 'spence')
|
213
|
+
expect(subject.owner).to eql 'spence'
|
214
|
+
end
|
215
|
+
|
216
|
+
context "when owner is a Proc" do
|
217
|
+
|
218
|
+
it "is called" do
|
219
|
+
proc = Proc.new { }
|
220
|
+
expect(proc).to receive(:call)
|
221
|
+
subject.instance_variable_set('@owner', proc)
|
222
|
+
subject.owner
|
223
|
+
end
|
224
|
+
|
225
|
+
end
|
226
|
+
|
227
|
+
end
|
228
|
+
|
229
|
+
describe "#owner=" do
|
230
|
+
|
231
|
+
it "should set the owner value" do
|
232
|
+
subject.owner = 'spence'
|
233
|
+
expect(subject.instance_variable_get('@owner')).to eql 'spence'
|
234
|
+
end
|
235
|
+
|
236
|
+
end
|
237
|
+
|
238
|
+
end
|