cookies_manager 0.1.8 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +5 -1
- data/README.rdoc +2 -0
- data/lib/cookies_manager/base.rb +14 -20
- data/lib/cookies_manager/version.rb +1 -1
- data/spec/cookies_manager/base_spec.rb +52 -9
- metadata +4 -4
data/CHANGELOG.rdoc
CHANGED
data/README.rdoc
CHANGED
@@ -29,7 +29,9 @@ To activate the feature, simply call +load_cookies_manager+ on your controller c
|
|
29
29
|
Next, you can refer the CookiesManager instance by calling the +cookies_manager+ helper method from your controllers and views:
|
30
30
|
|
31
31
|
len_bytes = cookies_manager.write('a_key', ['an', 'array']) # store the array as is in the cache, and as a base-64 string in the cookies
|
32
|
+
|
32
33
|
my_array = cookies_manager.read('a_key') # retrieves the array from the cache (or from the cookies if the cache is not in sync)
|
34
|
+
|
33
35
|
my_deleted_array = cookies_manager.delete('a_key') # removes the array from both the cookies and the cache
|
34
36
|
|
35
37
|
=== Supported options
|
data/lib/cookies_manager/base.rb
CHANGED
@@ -23,19 +23,16 @@ module CookiesManager
|
|
23
23
|
end
|
24
24
|
|
25
25
|
# Reads the data object corresponding to the key.
|
26
|
+
# - Reads from the cache, or from the cookies if the cache is not in sync.
|
27
|
+
# - Cache desynchronization can occur when the cookies hash has been modified directly, in which case the cache is automatically re-synchronized.
|
28
|
+
# - When the data needs to be retrieved from the cookies, it is successively base64-decoded, unzipped, and unmarshalled by default. If you consider your data does not need to be transformed, you can disable this feature by passing the +:skip_unpack+ option.
|
26
29
|
#
|
27
|
-
#
|
28
|
-
# Cache desynchronization can occur when the cookies hash is modified directly.
|
29
|
-
# The cache is automatically re-synchronized if out of sync.
|
30
|
-
#
|
31
|
-
# If option +:unpack+ is set to true, data will be successively base64-decoded, unzipped, and unmarshalled. This option is used only when the data
|
32
|
-
# is retrieved from the cookies hash (i.e. the cache is not in sync with the cookies).
|
33
|
-
#
|
34
|
-
# === Example:
|
30
|
+
# === Examples:
|
35
31
|
# data = cookies_manager.read('my_key') # reads the data associated with the key 'my_key'
|
32
|
+
# raw_data = cookies_manager.read('my_key', :skip_unpack => true) # reads without unpacking
|
36
33
|
#
|
37
34
|
# @param [String or Symbol] key a unique key corresponding to the data to read
|
38
|
-
# @option opts [Boolean] :
|
35
|
+
# @option opts [Boolean] :skip_unpack if true, DO NOT base64-decode, unzip, nor unmarshall the data. Default is false. This option is used only when the cache is out of sync.
|
39
36
|
# @return [Object] the data associated with the key
|
40
37
|
#
|
41
38
|
def read(key, opts = {})
|
@@ -47,10 +44,8 @@ module CookiesManager
|
|
47
44
|
end
|
48
45
|
|
49
46
|
# Writes the data object and associates it with the key.
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
53
|
-
# By default, before being stored in the cookies, data is marshalled, zipped, and base64-encoded. Although this feature is recommended, you can disable it by passing the option +:skip_pack+ if you consider your data can be stored as is in the cookies (ex: US-ASCII string).
|
47
|
+
# - Data is stored in both the cookies and the cache.
|
48
|
+
# - By default, before being stored in the cookies, data is marshalled, zipped, and base64-encoded. Although this feature is recommended, you can disable it by passing the option +:skip_pack+ if you consider your data can be stored as is in the cookies (ex: US-ASCII string).
|
54
49
|
#
|
55
50
|
# === Examples:
|
56
51
|
#
|
@@ -85,14 +80,13 @@ module CookiesManager
|
|
85
80
|
return result[:value].try(:bytesize) || 0
|
86
81
|
end
|
87
82
|
|
88
|
-
# Deletes the data corresponding to the key.
|
89
|
-
#
|
90
|
-
#
|
91
|
-
# The returned value is read from the cache if this is in sync with the cookies. Otherwise, the data is read from the cookies, in which case it is successively
|
92
|
-
# base64-decoded, unzipped, and unmarshalled if option +:unpack+ is set to true.
|
83
|
+
# Deletes the data corresponding to the key, and return it.
|
84
|
+
# - Removes the data from both the cookies and the cache.
|
85
|
+
# - The returned value is read from the cache if this is in sync with the cookies. Otherwise, the data is read from the cookies, in which case it is successively base64-decoded, unzipped, and unmarshalled by default. If you consider your data does not need to be transformed, you can disable this feature by passing the +:skip_unpack+ option.
|
93
86
|
#
|
94
87
|
# === Example:
|
95
|
-
# data = cookies_manager.delete('my_key') # deletes the data associated with the key 'my_key'
|
88
|
+
# data = cookies_manager.delete('my_key') # deletes and returns the data associated with the key 'my_key'
|
89
|
+
# raw_data = cookies_manager.delete('my_key', :skip_unpack => true) # same as above except that the returned data is not unpacked
|
96
90
|
#
|
97
91
|
# @param [String or Symbol] key a unique key corresponding to the data to delete
|
98
92
|
# @option opts (see #read)
|
@@ -132,7 +126,7 @@ module CookiesManager
|
|
132
126
|
if cache[key][:packed_data] == data_from_cookies # checks whether cache is in sync with cookies
|
133
127
|
result = cache[key][:unpacked_data] # reads from cache
|
134
128
|
else # cache not in sync
|
135
|
-
result = opts[:
|
129
|
+
result = opts[:skip_unpack] ? data_from_cookies : unpack(data_from_cookies) # read from cookies
|
136
130
|
# updates the cache
|
137
131
|
cache[key][:packed_data] = data_from_cookies
|
138
132
|
cache[key][:unpacked_data] = result
|
@@ -86,7 +86,7 @@ describe CookiesManager::Base do
|
|
86
86
|
describe "#read some data previously stored directly into the cookies hash" do
|
87
87
|
context "when reading non-nil data" do
|
88
88
|
before { cookies['my_key'] = {:value => @complex_data} }
|
89
|
-
specify { subject.read('my_key').should eql @complex_data }
|
89
|
+
specify { subject.read('my_key', :skip_unpack => true).should eql @complex_data }
|
90
90
|
end
|
91
91
|
context "when reading a nil value" do
|
92
92
|
before { cookies['my_key'] = {:value => nil } }
|
@@ -94,13 +94,13 @@ describe CookiesManager::Base do
|
|
94
94
|
end
|
95
95
|
context "when reading some data stored with a nil key" do
|
96
96
|
before { cookies[nil] = {:value => @complex_data} }
|
97
|
-
specify { subject.read(nil).should eql @complex_data }
|
98
|
-
specify { subject.read('').should eql @complex_data }
|
97
|
+
specify { subject.read(nil, :skip_unpack => true).should eql @complex_data }
|
98
|
+
specify { subject.read('', :skip_unpack => true).should eql @complex_data }
|
99
99
|
end
|
100
100
|
context "when reading some data stored with an empty string key" do
|
101
101
|
before { cookies[''] = {:value => @complex_data} }
|
102
|
-
specify { subject.read(nil).should eql @complex_data }
|
103
|
-
specify { subject.read('').should eql @complex_data }
|
102
|
+
specify { subject.read(nil, :skip_unpack => true).should eql @complex_data }
|
103
|
+
specify { subject.read('', :skip_unpack => true).should eql @complex_data }
|
104
104
|
end
|
105
105
|
end
|
106
106
|
describe "#read some data previously stored through CookiesManager but later modified directly inside the cookies hash" do
|
@@ -109,7 +109,7 @@ describe CookiesManager::Base do
|
|
109
109
|
subject.write('my_key', @simple_data)
|
110
110
|
cookies['my_key'] = {:value => (@new_simple_data = "some new data")}
|
111
111
|
end
|
112
|
-
specify { subject.read('my_key').should eql @new_simple_data }
|
112
|
+
specify { subject.read('my_key', :skip_unpack => true).should eql @new_simple_data }
|
113
113
|
end
|
114
114
|
context "when reading some complex data" do
|
115
115
|
before do
|
@@ -117,8 +117,8 @@ describe CookiesManager::Base do
|
|
117
117
|
@new_complex_data = @complex_data.merge(:some_new_item => 'it modifies the data')
|
118
118
|
cookies['my_key'] = {:value => pack(@new_complex_data)}
|
119
119
|
end
|
120
|
-
specify { subject.read('my_key'
|
121
|
-
specify { unpack(subject.read('my_key')).should eql @new_complex_data } #if :
|
120
|
+
specify { subject.read('my_key').should eql @new_complex_data }
|
121
|
+
specify { unpack(subject.read('my_key', :skip_unpack => true)).should eql @new_complex_data } #if :skip_unpack option is set, we need to unpack the data manually
|
122
122
|
end
|
123
123
|
end
|
124
124
|
describe "read with key symbol/string indifferent access (ex: :foo, 'foo')" do
|
@@ -141,7 +141,7 @@ describe CookiesManager::Base do
|
|
141
141
|
describe "#delete" do
|
142
142
|
describe "#delete existing data" do
|
143
143
|
shared_examples_for "when deleting existing data" do
|
144
|
-
before { @result = subject.delete('my_key') }
|
144
|
+
before { @result = subject.delete('my_key', :skip_unpack => true) }
|
145
145
|
specify { @result.should eql @complex_data }
|
146
146
|
specify { subject.read('my_key').should be_nil }
|
147
147
|
end
|
@@ -205,6 +205,49 @@ describe CookiesManager::Base do
|
|
205
205
|
end
|
206
206
|
end
|
207
207
|
|
208
|
+
describe "#cache management" do
|
209
|
+
shared_examples_for 'when accessing the data' do
|
210
|
+
context 'when reading' do
|
211
|
+
specify { subject.read('my_key').should eql @complex_data }
|
212
|
+
end
|
213
|
+
context 'when deleting' do
|
214
|
+
specify { subject.delete('my_key').should eql @complex_data }
|
215
|
+
end
|
216
|
+
end
|
217
|
+
describe "#cache in sync with the cookies" do
|
218
|
+
describe "#accessing some data that has been read at least once by the CookiesManager" do
|
219
|
+
before do
|
220
|
+
cookies['my_key'] = pack(@complex_data)
|
221
|
+
subject.read('my_key').should eql @complex_data # this should store the data in the cache, thus sparing the need for future unmarshalling
|
222
|
+
dont_allow(Marshal).load # this makes sure unmarshalling is never done (i.e. the cache is used)
|
223
|
+
end
|
224
|
+
it_should_behave_like 'when accessing the data'
|
225
|
+
end
|
226
|
+
describe "#accessing some data that has been written through the CookiesManager" do
|
227
|
+
before do
|
228
|
+
subject.write('my_key', @complex_data) # this should store the data in the cache, thus sparing the need for future unmarshalling
|
229
|
+
dont_allow(Marshal).load # this makes sure unmarshalling is never done (i.e. the cache is used)
|
230
|
+
end
|
231
|
+
it_should_behave_like 'when accessing the data'
|
232
|
+
end
|
233
|
+
end
|
234
|
+
describe "#cache out of sync" do
|
235
|
+
before do
|
236
|
+
subject.write('my_key', @original_data = ['my', 'original', 'array'])
|
237
|
+
cookies['my_key'] = pack(@complex_data) # this causes the cache to be out of sync, thus causing future reads to unmarshall the data from the cookies
|
238
|
+
mock.proxy(Marshal).load.with_any_args # this makes sure unmarshalling is invoked
|
239
|
+
end
|
240
|
+
it_should_behave_like 'when accessing the data'
|
241
|
+
describe "#automatic cache resynchronization on read" do
|
242
|
+
before do
|
243
|
+
subject.read('my_key').should eql @complex_data # this causes unmarshalling, and cache resynchronization
|
244
|
+
dont_allow(Marshal).load # this makes sure we don't unmarshall anymore at this point (i.e. the cache is now in sync and can be used)
|
245
|
+
end
|
246
|
+
specify { subject.read('my_key').should eql @complex_data}
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
208
251
|
describe "#multi-threading", :slow do
|
209
252
|
def print_inside_critical_section(method_name)
|
210
253
|
p "Inside the critical section, when calling cookies#{method_name}, the #{thread_name} thread pauses for #{sleep(2)} seconds, to make the other thread wait at the entrance of the critical section..."
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cookies_manager
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 2
|
9
|
+
- 0
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Christophe Levand
|