mongo-lock 1.0.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 +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
|