adapter 0.5.2 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/.travis.yml +8 -0
- data/Changelog.md +7 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +39 -0
- data/Guardfile +16 -0
- data/LICENSE +1 -1
- data/README.md +69 -0
- data/Rakefile +2 -3
- data/adapter.gemspec +15 -0
- data/examples/memory.rb +24 -0
- data/examples/overriding_serialization.rb +41 -0
- data/lib/adapter.rb +9 -5
- data/lib/adapter/asserts.rb +1 -1
- data/lib/adapter/defaults.rb +10 -10
- data/lib/adapter/exceptions.rb +1 -1
- data/lib/adapter/memory.rb +2 -2
- data/lib/adapter/spec/an_adapter.rb +157 -74
- data/lib/adapter/version.rb +2 -2
- data/spec/adapter/defaults_spec.rb +13 -20
- data/spec/adapter/memory_spec.rb +3 -2
- data/spec/adapter_spec.rb +16 -6
- data/spec/helper.rb +2 -16
- data/spec/spec.opts +1 -1
- data/spec/support/module_helpers.rb +1 -1
- metadata +45 -49
- data/README.rdoc +0 -55
- data/lib/adapter/spec/json_adapter.rb +0 -10
- data/lib/adapter/spec/marshal_adapter.rb +0 -10
- data/lib/adapter/spec/types.rb +0 -5
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Changelog.md
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
* 0.5.2 => 0.6.0
|
2
|
+
|
3
|
+
* Now aimed at key/value where value is Hash of attributes instead of just any random value, such as String, Array, etc.
|
4
|
+
* `#key_for` now defaults to whatever was passed in, rather than Marshaling anything that was not a String or a Symbol.
|
5
|
+
* `#encode` and `#decode` now default to whatever was passed in, instead of marshaling.
|
6
|
+
* `#delete` no longer returns value. Raise error if delete fails. If you need value, do a read before delete.
|
7
|
+
* Added `#read_multiple`. This can be overridden per adapter to make it more efficient based on the data store. Defaults to multiple single reads.
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
adapter (0.6.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.1.3)
|
10
|
+
ffi (1.0.11)
|
11
|
+
guard (1.0.0)
|
12
|
+
ffi (>= 0.5.0)
|
13
|
+
thor (~> 0.14.6)
|
14
|
+
guard-bundler (0.1.3)
|
15
|
+
bundler (>= 1.0.0)
|
16
|
+
guard (>= 0.2.2)
|
17
|
+
guard-rspec (0.6.0)
|
18
|
+
guard (>= 0.10.0)
|
19
|
+
rake (0.9.2)
|
20
|
+
rspec (2.5.0)
|
21
|
+
rspec-core (~> 2.5.0)
|
22
|
+
rspec-expectations (~> 2.5.0)
|
23
|
+
rspec-mocks (~> 2.5.0)
|
24
|
+
rspec-core (2.5.1)
|
25
|
+
rspec-expectations (2.5.0)
|
26
|
+
diff-lcs (~> 1.1.2)
|
27
|
+
rspec-mocks (2.5.0)
|
28
|
+
thor (0.14.6)
|
29
|
+
|
30
|
+
PLATFORMS
|
31
|
+
ruby
|
32
|
+
|
33
|
+
DEPENDENCIES
|
34
|
+
adapter!
|
35
|
+
guard
|
36
|
+
guard-bundler
|
37
|
+
guard-rspec
|
38
|
+
rake
|
39
|
+
rspec
|
data/Guardfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
rspec_options = {
|
2
|
+
:all_after_pass => false,
|
3
|
+
:all_on_start => false,
|
4
|
+
}
|
5
|
+
|
6
|
+
guard 'rspec', rspec_options do
|
7
|
+
watch(%r{^spec/.+_spec\.rb$})
|
8
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
9
|
+
watch('spec/helper.rb') { "spec" }
|
10
|
+
watch(%r{lib/adapter/spec/(.+)\.rb}) { "spec" }
|
11
|
+
end
|
12
|
+
|
13
|
+
guard 'bundler' do
|
14
|
+
watch('Gemfile')
|
15
|
+
watch(/^.+\.gemspec/)
|
16
|
+
end
|
data/LICENSE
CHANGED
@@ -6,4 +6,4 @@ Redistribution and use in source and binary forms, with or without modification,
|
|
6
6
|
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
7
7
|
* Neither the name of Zynga Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
8
8
|
|
9
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
9
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# Adapter
|
2
|
+
|
3
|
+
A simple interface to anything.
|
4
|
+
|
5
|
+
## Defining an Adapter
|
6
|
+
|
7
|
+
An adapter requires 4 methods to work: read, write, delete and clear.
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
Adapter.define(:memory) do
|
11
|
+
def read(key)
|
12
|
+
decode(client[key_for(key)])
|
13
|
+
end
|
14
|
+
|
15
|
+
def write(key, value)
|
16
|
+
client[key_for(key)] = encode(value)
|
17
|
+
end
|
18
|
+
|
19
|
+
def delete(key)
|
20
|
+
client.delete(key_for(key))
|
21
|
+
end
|
22
|
+
|
23
|
+
def clear
|
24
|
+
client.clear
|
25
|
+
end
|
26
|
+
end
|
27
|
+
```
|
28
|
+
|
29
|
+
Note: in order for things to be most flexible, always wrap key with key_for(key) which will ensure that pretty much anything can be a key. Also, by default encode and decode are included and they Marshal.dump and Marshal.load. Feel free to override these if you prefer JSON serialization or something else.
|
30
|
+
|
31
|
+
Once you have defined an adapter, you can get a class of that adapter like this:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
Adapter[:memory]
|
35
|
+
```
|
36
|
+
|
37
|
+
This returns a dynamic class with your adapting methods included and an initialize method that takes a client. This means you can get an instance of the adapter by using new and passing the client (in this instance a boring hash):
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
adapter = Adapter[:memory].new({}) # sets {} to client
|
41
|
+
adapter.write('foo', 'bar')
|
42
|
+
adapter.read('foo') # 'bar'
|
43
|
+
adapter.delete('foo')
|
44
|
+
adapter.fetch('foo', 'bar') # returns bar and sets foo to bar
|
45
|
+
```
|
46
|
+
|
47
|
+
`get` and `[]` are aliased to read. `set` and `[]=` are aliased to write.
|
48
|
+
|
49
|
+
Note: You can also optionally provide a lock method. [Read More](https://github.com/jnunemaker/adapter/wiki/Locking)
|
50
|
+
|
51
|
+
## Adapter Power User Guides
|
52
|
+
|
53
|
+
* [Wiki Home](https://github.com/jnunemaker/adapter/wiki)
|
54
|
+
* [Creating an Adapter](https://github.com/jnunemaker/adapter/wiki/Creating-an-Adapter)
|
55
|
+
* [Overriding an Adapter](https://github.com/jnunemaker/adapter/wiki/Overriding-an-Adapter)
|
56
|
+
* [Allowing for Options](https://github.com/jnunemaker/adapter/wiki/Allowing-for-Options)
|
57
|
+
* [Adapter defaults](https://github.com/jnunemaker/adapter/wiki/Adapter-defaults)
|
58
|
+
|
59
|
+
## Mailing List
|
60
|
+
|
61
|
+
https://groups.google.com/forum/#!forum/toystoreadapter
|
62
|
+
|
63
|
+
## Note on Patches/Pull Requests
|
64
|
+
|
65
|
+
* Fork the project.
|
66
|
+
* Make your feature addition or bug fix in a topic branch.
|
67
|
+
* Add tests for it. This is important so we don't break it in a future version unintentionally.
|
68
|
+
* Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine, but bump version in a commit by itself so we can ignore when we pull)
|
69
|
+
* Send a pull request.
|
data/Rakefile
CHANGED
data/adapter.gemspec
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require File.expand_path('../lib/adapter/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'adapter'
|
6
|
+
s.homepage = 'http://github.com/jnunemaker/adapter'
|
7
|
+
s.summary = 'A simple interface to anything'
|
8
|
+
s.require_paths = ["lib"]
|
9
|
+
s.authors = ['John Nunemaker', 'Geoffrey Dagley', 'Brandon Keepers']
|
10
|
+
s.email = ['nunemaker@gmail.com', 'gdagley@gmail.com', 'brandon@opensoul.org']
|
11
|
+
s.version = Adapter::VERSION
|
12
|
+
s.platform = Gem::Platform::RUBY
|
13
|
+
s.files = `git ls-files`.split($/)
|
14
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
15
|
+
end
|
data/examples/memory.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
root_path = Pathname(__FILE__).dirname.join('..').expand_path
|
5
|
+
lib_path = root_path.join('lib')
|
6
|
+
$:.unshift(lib_path)
|
7
|
+
|
8
|
+
require 'adapter/memory'
|
9
|
+
|
10
|
+
adapter = Adapter[:memory].new({})
|
11
|
+
adapter.clear
|
12
|
+
|
13
|
+
adapter.write('foo', 'bar')
|
14
|
+
puts 'Should be bar: ' + adapter.read('foo').inspect
|
15
|
+
|
16
|
+
adapter.delete('foo')
|
17
|
+
puts 'Should be nil: ' + adapter.read('foo').inspect
|
18
|
+
|
19
|
+
adapter.write('foo', 'bar')
|
20
|
+
adapter.clear
|
21
|
+
puts 'Should be nil: ' + adapter.read('foo').inspect
|
22
|
+
|
23
|
+
puts 'Should be bar: ' + adapter.fetch('foo', 'bar').inspect
|
24
|
+
puts 'Should be bar: ' + adapter.read('foo').inspect
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_support'
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
root_path = Pathname(__FILE__).dirname.join('..').expand_path
|
6
|
+
lib_path = root_path.join('lib')
|
7
|
+
$:.unshift(lib_path)
|
8
|
+
|
9
|
+
require 'adapter/memory'
|
10
|
+
|
11
|
+
# Adapter.define also takes any combination of module and block.
|
12
|
+
#
|
13
|
+
# If module present, it is included. If block present, it is turned
|
14
|
+
# into a module and included. This means that including a module and
|
15
|
+
# a block allows overriding the module by defining methods in the block.
|
16
|
+
#
|
17
|
+
# In our case below, we simply override the memory adapter to create
|
18
|
+
# a new adapter that encodes/decodes using JSON instead of the default
|
19
|
+
# Marshal.load/dump. Also, important to note that this does not affect
|
20
|
+
# the memory adapter which still uses Marshal.
|
21
|
+
Adapter.define(:memory_json, Adapter::Memory) do
|
22
|
+
def encode(value)
|
23
|
+
ActiveSupport::JSON.encode(value)
|
24
|
+
end
|
25
|
+
|
26
|
+
def decode(value)
|
27
|
+
ActiveSupport::JSON.decode(value)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
adapter = Adapter[:memory_json].new({})
|
32
|
+
adapter.clear
|
33
|
+
|
34
|
+
adapter.write('foo', 'bar' => 'baz')
|
35
|
+
# Encoded in adapter as json instead of being marshal'd
|
36
|
+
puts adapter.client['foo'].inspect # "{\"bar\":\"baz\"}"
|
37
|
+
|
38
|
+
|
39
|
+
adapter.client['foo'] = ActiveSupport::JSON.encode('chunky' => 'bacon')
|
40
|
+
# Decoded from adapter using json instead of being un-marshal'd
|
41
|
+
puts adapter.read('foo').inspect # {"chunky"=>"bacon"}
|
data/lib/adapter.rb
CHANGED
@@ -6,6 +6,7 @@ module Adapter
|
|
6
6
|
extend Asserts
|
7
7
|
include Defaults
|
8
8
|
|
9
|
+
# Stores the definitions for each adapter by name
|
9
10
|
def self.definitions
|
10
11
|
@definitions ||= {}
|
11
12
|
end
|
@@ -20,6 +21,7 @@ module Adapter
|
|
20
21
|
definitions[name.to_sym] = definition_module
|
21
22
|
end
|
22
23
|
|
24
|
+
# Memoizes adapter instances based on their definitions
|
23
25
|
def self.adapters
|
24
26
|
@adapters ||= {}
|
25
27
|
end
|
@@ -41,11 +43,13 @@ module Adapter
|
|
41
43
|
|
42
44
|
include Adapter.definitions[name.to_sym]
|
43
45
|
|
44
|
-
|
45
|
-
|
46
|
+
alias_method :get, :read
|
47
|
+
alias_method :set, :write
|
46
48
|
|
47
|
-
|
48
|
-
|
49
|
+
alias_method :[], :read
|
50
|
+
alias_method :[]=, :write
|
51
|
+
|
52
|
+
alias_method :get_multiple, :read_multiple
|
49
53
|
|
50
54
|
def eql?(other)
|
51
55
|
self.class.eql?(other.class) && client == other.client
|
@@ -55,4 +59,4 @@ module Adapter
|
|
55
59
|
class_eval "def name; :#{name} end"
|
56
60
|
end
|
57
61
|
end
|
58
|
-
end
|
62
|
+
end
|
data/lib/adapter/asserts.rb
CHANGED
data/lib/adapter/defaults.rb
CHANGED
@@ -7,26 +7,26 @@ module Adapter
|
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
|
+
def read_multiple(*keys)
|
11
|
+
result = {}
|
12
|
+
keys.each { |key| result[key_for(key)] = read(key) }
|
13
|
+
result
|
14
|
+
end
|
15
|
+
|
10
16
|
def key?(key)
|
11
17
|
!read(key).nil?
|
12
18
|
end
|
13
19
|
|
14
20
|
def key_for(key)
|
15
|
-
|
16
|
-
key
|
17
|
-
elsif key.is_a?(Symbol)
|
18
|
-
key.to_s
|
19
|
-
else
|
20
|
-
Marshal.dump(key)
|
21
|
-
end
|
21
|
+
key
|
22
22
|
end
|
23
23
|
|
24
24
|
def encode(value)
|
25
|
-
|
25
|
+
value
|
26
26
|
end
|
27
27
|
|
28
28
|
def decode(value)
|
29
|
-
value
|
29
|
+
value
|
30
30
|
end
|
31
31
|
end
|
32
|
-
end
|
32
|
+
end
|
data/lib/adapter/exceptions.rb
CHANGED
data/lib/adapter/memory.rb
CHANGED
@@ -11,7 +11,7 @@ module Adapter
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def delete(key)
|
14
|
-
|
14
|
+
decode(client.delete(key_for(key)))
|
15
15
|
end
|
16
16
|
|
17
17
|
def clear
|
@@ -20,4 +20,4 @@ module Adapter
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
Adapter.define(:memory, Adapter::Memory)
|
23
|
+
Adapter.define(:memory, Adapter::Memory)
|
@@ -3,118 +3,201 @@ shared_examples_for "an adapter" do
|
|
3
3
|
adapter.client.should == client
|
4
4
|
end
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
let(:key) { 'key' }
|
7
|
+
let(:key2) { 'key2' }
|
8
|
+
|
9
|
+
let(:attributes) {
|
10
|
+
{
|
11
|
+
:one => 'one',
|
12
|
+
:three => 'three',
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
16
|
+
let(:attributes2) {
|
17
|
+
{
|
18
|
+
:two => 'two',
|
19
|
+
:four => 'four',
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
describe "#read" do
|
24
|
+
it "returns nil if key not available" do
|
25
|
+
adapter.read(key).should be_nil
|
9
26
|
end
|
10
27
|
|
11
|
-
it "
|
12
|
-
adapter
|
13
|
-
adapter
|
28
|
+
it "returns value if key available" do
|
29
|
+
adapter.write(key, attributes)
|
30
|
+
adapter.read(key).should eq(attributes)
|
14
31
|
end
|
32
|
+
end
|
15
33
|
|
16
|
-
|
17
|
-
|
18
|
-
adapter
|
19
|
-
adapter[key].should_not be_equal(value)
|
34
|
+
describe "#get" do
|
35
|
+
it "returns nil if key not available" do
|
36
|
+
adapter.get(key).should be_nil
|
20
37
|
end
|
21
38
|
|
22
|
-
it "
|
23
|
-
|
24
|
-
adapter
|
25
|
-
adapter[key].should_not be_equal(:foo => :bar)
|
39
|
+
it "returns value if key available" do
|
40
|
+
adapter.write(key, attributes)
|
41
|
+
adapter.get(key).should eq(attributes)
|
26
42
|
end
|
43
|
+
end
|
27
44
|
|
28
|
-
|
29
|
-
|
45
|
+
describe "#[]" do
|
46
|
+
it "returns nil if key not available" do
|
47
|
+
adapter[key].should be_nil
|
30
48
|
end
|
31
49
|
|
32
|
-
it "returns
|
33
|
-
adapter
|
34
|
-
adapter
|
50
|
+
it "returns value if key available" do
|
51
|
+
adapter.write(key, attributes)
|
52
|
+
adapter[key].should eq(attributes)
|
35
53
|
end
|
54
|
+
end
|
36
55
|
|
37
|
-
|
38
|
-
|
39
|
-
adapter.
|
40
|
-
adapter.
|
56
|
+
describe "#read_multiple" do
|
57
|
+
before do
|
58
|
+
adapter.write(key, attributes)
|
59
|
+
adapter.write(key2, attributes2)
|
41
60
|
end
|
42
61
|
|
43
|
-
it "returns
|
44
|
-
adapter.
|
62
|
+
it "returns Hash of keys and values" do
|
63
|
+
adapter.read_multiple(key, key2).should eq({
|
64
|
+
key => attributes,
|
65
|
+
key2 => attributes2,
|
66
|
+
})
|
45
67
|
end
|
46
68
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
69
|
+
context "with mix of keys that are and are not available" do
|
70
|
+
it "returns Hash of keys and values where unavailable keys are nil" do
|
71
|
+
adapter.read_multiple(key, key2, 'foo', 'bar').should eq({
|
72
|
+
key => attributes,
|
73
|
+
key2 => attributes2,
|
74
|
+
'foo' => nil,
|
75
|
+
'bar' => nil,
|
76
|
+
})
|
77
|
+
end
|
53
78
|
end
|
79
|
+
end
|
54
80
|
|
55
|
-
|
56
|
-
|
81
|
+
describe "#get_multiple" do
|
82
|
+
before do
|
83
|
+
adapter.write(key, attributes)
|
84
|
+
adapter.write(key2, attributes2)
|
57
85
|
end
|
58
86
|
|
59
|
-
it "
|
60
|
-
adapter.
|
87
|
+
it "returns Hash of keys and values" do
|
88
|
+
adapter.get_multiple(key, key2).should eq({
|
89
|
+
key => attributes,
|
90
|
+
key2 => attributes2,
|
91
|
+
})
|
61
92
|
end
|
62
93
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
94
|
+
context "with mix of keys that are and are not available" do
|
95
|
+
it "returns Hash of keys and values where unavailable keys are nil" do
|
96
|
+
adapter.get_multiple(key, key2, 'foo', 'bar').should eq({
|
97
|
+
key => attributes,
|
98
|
+
key2 => attributes2,
|
99
|
+
'foo' => nil,
|
100
|
+
'bar' => nil,
|
101
|
+
})
|
102
|
+
end
|
68
103
|
end
|
104
|
+
end
|
69
105
|
|
70
|
-
|
71
|
-
|
72
|
-
adapter.
|
106
|
+
describe "#key?" do
|
107
|
+
it "returns true if key available" do
|
108
|
+
adapter.write(key, attributes)
|
109
|
+
adapter.key?(key).should be_true
|
73
110
|
end
|
74
111
|
|
75
|
-
it "
|
76
|
-
adapter.
|
77
|
-
adapter[key].should == "value"
|
112
|
+
it "returns false if key not available" do
|
113
|
+
adapter.key?(key).should be_false
|
78
114
|
end
|
79
115
|
end
|
80
116
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
117
|
+
describe "#fetch" do
|
118
|
+
context "with key not stored" do
|
119
|
+
context "with default value" do
|
120
|
+
it "returns default value" do
|
121
|
+
adapter.fetch(key, {}).should eq({})
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context "with default block" do
|
126
|
+
it "returns value of yielded block" do
|
127
|
+
adapter.fetch(key) { |k| {} }.should eq({})
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
86
131
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
132
|
+
context "with key that is stored" do
|
133
|
+
context "with default value" do
|
134
|
+
it "returns key value instead of default" do
|
135
|
+
adapter.write(key, attributes2)
|
136
|
+
adapter.fetch(key, attributes).should eq(attributes2)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context "with default block" do
|
141
|
+
it "does not run the block" do
|
142
|
+
adapter.write(key, attributes)
|
143
|
+
unaltered = 'unaltered'
|
144
|
+
adapter.fetch(key) { unaltered = 'altered' }
|
145
|
+
unaltered.should eq('unaltered')
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
91
149
|
end
|
92
150
|
|
93
|
-
|
94
|
-
|
95
|
-
adapter
|
96
|
-
|
151
|
+
describe "#write" do
|
152
|
+
it "sets key to value" do
|
153
|
+
adapter.write(key, attributes)
|
154
|
+
adapter.read(key).should eq(attributes)
|
155
|
+
end
|
97
156
|
end
|
98
157
|
|
99
|
-
|
100
|
-
|
101
|
-
adapter.
|
102
|
-
|
158
|
+
describe "#set" do
|
159
|
+
it "sets key to value" do
|
160
|
+
adapter.set(key, attributes)
|
161
|
+
adapter.read(key).should eq(attributes)
|
162
|
+
end
|
103
163
|
end
|
104
164
|
|
105
|
-
|
106
|
-
|
107
|
-
adapter
|
108
|
-
|
165
|
+
describe "#[]=" do
|
166
|
+
it "sets key to value" do
|
167
|
+
adapter[key] = attributes
|
168
|
+
adapter.read(key).should eq(attributes)
|
169
|
+
end
|
109
170
|
end
|
110
171
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
172
|
+
describe "#delete" do
|
173
|
+
context "when key available" do
|
174
|
+
before do
|
175
|
+
adapter.write(key, attributes)
|
176
|
+
adapter.delete(key)
|
177
|
+
end
|
178
|
+
|
179
|
+
it "removes key" do
|
180
|
+
adapter.key?(key).should be_false
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
context "when key not available" do
|
185
|
+
it "does not complain" do
|
186
|
+
adapter.delete(key)
|
187
|
+
end
|
188
|
+
end
|
115
189
|
end
|
116
190
|
|
117
|
-
|
118
|
-
|
191
|
+
describe "#clear" do
|
192
|
+
before do
|
193
|
+
adapter[key] = attributes
|
194
|
+
adapter[key2] = attributes2
|
195
|
+
adapter.clear
|
196
|
+
end
|
197
|
+
|
198
|
+
it "removes all stored keys" do
|
199
|
+
adapter.key?(key).should be_false
|
200
|
+
adapter.key?(key2).should be_false
|
201
|
+
end
|
119
202
|
end
|
120
|
-
end
|
203
|
+
end
|
data/lib/adapter/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
module Adapter
|
2
|
-
VERSION = '0.
|
3
|
-
end
|
2
|
+
VERSION = '0.6.0'
|
3
|
+
end
|
@@ -8,33 +8,26 @@ describe Adapter::Defaults do
|
|
8
8
|
end
|
9
9
|
|
10
10
|
describe "#key_for" do
|
11
|
-
it "returns
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
it "returns string for symbol" do
|
16
|
-
mod.key_for(:foo).should == 'foo'
|
17
|
-
end
|
18
|
-
|
19
|
-
it "marshals anything not a string or symbol" do
|
20
|
-
mod.key_for({'testing' => 'this'}).should == %Q(\004\b{\006\"\ftesting\"\tthis)
|
11
|
+
it "returns whatever is passed to it" do
|
12
|
+
[nil, 'foo', :foo, {:foo => 'bar'}].each do |key|
|
13
|
+
mod.key_for(key).should be(key)
|
14
|
+
end
|
21
15
|
end
|
22
16
|
end
|
23
17
|
|
24
18
|
describe "#encode" do
|
25
|
-
it "
|
26
|
-
|
27
|
-
|
19
|
+
it "returns whatever is passed to it" do
|
20
|
+
[nil, 'foo', :foo, {:foo => 'bar'}].each do |value|
|
21
|
+
mod.encode(value).should be(value)
|
22
|
+
end
|
28
23
|
end
|
29
24
|
end
|
30
25
|
|
31
26
|
describe "#decode" do
|
32
|
-
it "returns
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
it "returns marshal load if not nil" do
|
37
|
-
mod.decode(%Q(\004\b{\006\"\ftesting\"\tthis)).should == {'testing' => 'this'}
|
27
|
+
it "returns whatever is passed to it" do
|
28
|
+
[nil, 'foo', :foo, {:foo => 'bar'}].each do |value|
|
29
|
+
mod.decode(value).should be(value)
|
30
|
+
end
|
38
31
|
end
|
39
32
|
end
|
40
|
-
end
|
33
|
+
end
|
data/spec/adapter/memory_spec.rb
CHANGED
@@ -3,6 +3,7 @@ require 'adapter/memory'
|
|
3
3
|
|
4
4
|
describe "Memory adapter" do
|
5
5
|
before do
|
6
|
+
Adapter.define(:memory, Adapter::Memory)
|
6
7
|
@client = {}
|
7
8
|
@adapter = Adapter[:memory].new(@client)
|
8
9
|
@adapter.clear
|
@@ -11,5 +12,5 @@ describe "Memory adapter" do
|
|
11
12
|
let(:adapter) { @adapter }
|
12
13
|
let(:client) { @client }
|
13
14
|
|
14
|
-
it_should_behave_like '
|
15
|
-
end
|
15
|
+
it_should_behave_like 'an adapter'
|
16
|
+
end
|
data/spec/adapter_spec.rb
CHANGED
@@ -1,6 +1,16 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
describe Adapter do
|
4
|
+
before do
|
5
|
+
Adapter.definitions.clear
|
6
|
+
Adapter.adapters.clear
|
7
|
+
end
|
8
|
+
|
9
|
+
after do
|
10
|
+
Adapter.definitions.clear
|
11
|
+
Adapter.adapters.clear
|
12
|
+
end
|
13
|
+
|
4
14
|
describe ".definitions" do
|
5
15
|
it "defaults to empty hash" do
|
6
16
|
Adapter.instance_variable_set("@definitions", nil)
|
@@ -104,11 +114,11 @@ describe Adapter do
|
|
104
114
|
before do
|
105
115
|
Adapter.define(:memory_json, valid_module) do
|
106
116
|
def encode(value)
|
107
|
-
|
117
|
+
'encoded'
|
108
118
|
end
|
109
119
|
|
110
120
|
def decode(value)
|
111
|
-
|
121
|
+
'decoded'
|
112
122
|
end
|
113
123
|
end
|
114
124
|
end
|
@@ -117,13 +127,13 @@ describe Adapter do
|
|
117
127
|
it "encodes correctly" do
|
118
128
|
hash = {'foo' => 'bar'}
|
119
129
|
adapter.write('foo', hash)
|
120
|
-
adapter.client['foo'].should ==
|
130
|
+
adapter.client['foo'].should == 'encoded'
|
121
131
|
end
|
122
132
|
|
123
133
|
it "decodes correctly" do
|
124
134
|
hash = {'foo' => 'bar'}
|
125
|
-
adapter.client['foo'] =
|
126
|
-
adapter.read('foo').should ==
|
135
|
+
adapter.client['foo'] = hash
|
136
|
+
adapter.read('foo').should == 'decoded'
|
127
137
|
end
|
128
138
|
end
|
129
139
|
|
@@ -308,4 +318,4 @@ describe Adapter do
|
|
308
318
|
end
|
309
319
|
end
|
310
320
|
end
|
311
|
-
end
|
321
|
+
end
|
data/spec/helper.rb
CHANGED
@@ -1,27 +1,13 @@
|
|
1
1
|
$:.unshift(File.expand_path('../../lib', __FILE__))
|
2
2
|
|
3
|
+
require 'pathname'
|
3
4
|
require 'rubygems'
|
4
5
|
require 'bundler'
|
5
6
|
|
6
|
-
Bundler.require(:default, :development)
|
7
|
-
|
8
|
-
require 'pathname'
|
9
|
-
require 'logger'
|
10
|
-
|
11
|
-
root_path = Pathname(__FILE__).dirname.join('..').expand_path
|
12
|
-
lib_path = root_path.join('lib')
|
13
|
-
log_path = root_path.join('log')
|
14
|
-
log_path.mkpath
|
15
|
-
|
16
7
|
require 'adapter/spec/an_adapter'
|
17
|
-
require 'adapter/spec/marshal_adapter'
|
18
|
-
require 'adapter/spec/json_adapter'
|
19
|
-
require 'adapter/spec/types'
|
20
|
-
|
21
8
|
require 'support/module_helpers'
|
22
9
|
|
23
|
-
|
24
|
-
LogBuddy.init(:logger => logger)
|
10
|
+
Bundler.require(:default, :test)
|
25
11
|
|
26
12
|
Rspec.configure do |c|
|
27
13
|
c.include(ModuleHelpers)
|
data/spec/spec.opts
CHANGED
metadata
CHANGED
@@ -1,90 +1,86 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: adapter
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 5
|
9
|
-
- 2
|
10
|
-
version: 0.5.2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.6.0
|
5
|
+
prerelease:
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- John Nunemaker
|
14
9
|
- Geoffrey Dagley
|
15
10
|
- Brandon Keepers
|
16
11
|
autorequire:
|
17
12
|
bindir: bin
|
18
13
|
cert_chain: []
|
19
|
-
|
20
|
-
date: 2011-01-26 00:00:00 -05:00
|
21
|
-
default_executable:
|
14
|
+
date: 2012-11-07 00:00:00.000000000 Z
|
22
15
|
dependencies: []
|
23
|
-
|
24
16
|
description:
|
25
|
-
email:
|
17
|
+
email:
|
26
18
|
- nunemaker@gmail.com
|
27
19
|
- gdagley@gmail.com
|
28
20
|
- brandon@opensoul.org
|
29
21
|
executables: []
|
30
|
-
|
31
22
|
extensions: []
|
32
|
-
|
33
23
|
extra_rdoc_files: []
|
34
|
-
|
35
|
-
|
24
|
+
files:
|
25
|
+
- .gitignore
|
26
|
+
- .travis.yml
|
27
|
+
- Changelog.md
|
28
|
+
- Gemfile
|
29
|
+
- Gemfile.lock
|
30
|
+
- Guardfile
|
31
|
+
- LICENSE
|
32
|
+
- README.md
|
33
|
+
- Rakefile
|
34
|
+
- adapter.gemspec
|
35
|
+
- examples/memory.rb
|
36
|
+
- examples/overriding_serialization.rb
|
37
|
+
- lib/adapter.rb
|
36
38
|
- lib/adapter/asserts.rb
|
37
39
|
- lib/adapter/defaults.rb
|
38
40
|
- lib/adapter/exceptions.rb
|
39
41
|
- lib/adapter/memory.rb
|
40
42
|
- lib/adapter/spec/an_adapter.rb
|
41
|
-
- lib/adapter/spec/json_adapter.rb
|
42
|
-
- lib/adapter/spec/marshal_adapter.rb
|
43
|
-
- lib/adapter/spec/types.rb
|
44
43
|
- lib/adapter/version.rb
|
45
|
-
- lib/adapter.rb
|
46
44
|
- spec/adapter/defaults_spec.rb
|
47
45
|
- spec/adapter/memory_spec.rb
|
48
46
|
- spec/adapter_spec.rb
|
49
47
|
- spec/helper.rb
|
50
48
|
- spec/spec.opts
|
51
49
|
- spec/support/module_helpers.rb
|
52
|
-
|
53
|
-
- Rakefile
|
54
|
-
- README.rdoc
|
55
|
-
has_rdoc: true
|
56
|
-
homepage: http://github.com/newtoy/adapter
|
50
|
+
homepage: http://github.com/jnunemaker/adapter
|
57
51
|
licenses: []
|
58
|
-
|
59
52
|
post_install_message:
|
60
53
|
rdoc_options: []
|
61
|
-
|
62
|
-
require_paths:
|
54
|
+
require_paths:
|
63
55
|
- lib
|
64
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
57
|
none: false
|
66
|
-
requirements:
|
67
|
-
- -
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
|
70
|
-
segments:
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
segments:
|
71
63
|
- 0
|
72
|
-
|
73
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
hash: -254287751766179836
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
66
|
none: false
|
75
|
-
requirements:
|
76
|
-
- -
|
77
|
-
- !ruby/object:Gem::Version
|
78
|
-
|
79
|
-
segments:
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
segments:
|
80
72
|
- 0
|
81
|
-
|
73
|
+
hash: -254287751766179836
|
82
74
|
requirements: []
|
83
|
-
|
84
75
|
rubyforge_project:
|
85
|
-
rubygems_version: 1.
|
76
|
+
rubygems_version: 1.8.23
|
86
77
|
signing_key:
|
87
78
|
specification_version: 3
|
88
79
|
summary: A simple interface to anything
|
89
|
-
test_files:
|
90
|
-
|
80
|
+
test_files:
|
81
|
+
- spec/adapter/defaults_spec.rb
|
82
|
+
- spec/adapter/memory_spec.rb
|
83
|
+
- spec/adapter_spec.rb
|
84
|
+
- spec/helper.rb
|
85
|
+
- spec/spec.opts
|
86
|
+
- spec/support/module_helpers.rb
|
data/README.rdoc
DELETED
@@ -1,55 +0,0 @@
|
|
1
|
-
= Adapter
|
2
|
-
|
3
|
-
A simple interface to anything.
|
4
|
-
|
5
|
-
== Defining an Adapter
|
6
|
-
|
7
|
-
An adapter requires 4 methods to work: read, write, delete and clear.
|
8
|
-
|
9
|
-
Adapter.define(:memory) do
|
10
|
-
def read(key)
|
11
|
-
decode(client[key_for(key)])
|
12
|
-
end
|
13
|
-
|
14
|
-
def write(key, value)
|
15
|
-
client[key_for(key)] = encode(value)
|
16
|
-
end
|
17
|
-
|
18
|
-
def delete(key)
|
19
|
-
client.delete(key_for(key))
|
20
|
-
end
|
21
|
-
|
22
|
-
def clear
|
23
|
-
client.clear
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
Note: in order for things to be most flexible, always wrap key with key_for(key) which will ensure that pretty much anything can be a key. Also, by default encode and decode are included and they Marshal.dump and Marshal.load. Feel free to override these if you prefer JSON serialization or something else.
|
28
|
-
|
29
|
-
Once you have defined an adapter, you can get a class of that adapter like this:
|
30
|
-
|
31
|
-
Adapter[:memory]
|
32
|
-
|
33
|
-
This returns a dynamic class with your adapting methods included and an initialize method that takes a client. This means you can get an instance of the adapter by using new and passing the client (in this instance a boring hash):
|
34
|
-
|
35
|
-
adapter = Adapter[:memory].new({}) # sets {} to client
|
36
|
-
adapter.write('foo', 'bar')
|
37
|
-
adapter.read('foo') # 'bar'
|
38
|
-
adapter.delete('foo')
|
39
|
-
adapter.fetch('foo', 'bar') # returns bar and sets foo to bar
|
40
|
-
|
41
|
-
get and [] are aliased to read. set and []= are aliased to write.
|
42
|
-
|
43
|
-
Note: You can also optionally provide a lock method. See the memcached and redis adapters for more on locking.
|
44
|
-
|
45
|
-
== Extending Adapters
|
46
|
-
|
47
|
-
Adapters can be defined using a block, a module, or a module and a block. This allows very flexibly overriding specific things in an adapter to create a new adapter, without having to redo all of the work. See examples/overriding_serialization.rb for an example of this.
|
48
|
-
|
49
|
-
== Note on Patches/Pull Requests
|
50
|
-
|
51
|
-
* Fork the project.
|
52
|
-
* Make your feature addition or bug fix.
|
53
|
-
* Add tests for it. This is important so we don't break it in a future version unintentionally.
|
54
|
-
* Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine, but bump version in a commit by itself so we can ignore when we pull)
|
55
|
-
* Send us a pull request. Bonus points for topic branches.
|
@@ -1,10 +0,0 @@
|
|
1
|
-
shared_examples_for "a json adapter" do
|
2
|
-
it_should_behave_like 'an adapter'
|
3
|
-
|
4
|
-
Adapter::Spec::Types.each do |type, (key, key2)|
|
5
|
-
it "writes Object values to keys that are #{type}s like a Hash" do
|
6
|
-
adapter[key] = {:foo => :bar}
|
7
|
-
adapter[key].should == {'foo' => 'bar'}
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
@@ -1,10 +0,0 @@
|
|
1
|
-
shared_examples_for "a marshaled adapter" do
|
2
|
-
it_should_behave_like 'an adapter'
|
3
|
-
|
4
|
-
Adapter::Spec::Types.each do |type, (key, key2)|
|
5
|
-
it "writes Object values to keys that are #{type}s like a Hash" do
|
6
|
-
adapter[key] = {:foo => :bar}
|
7
|
-
adapter[key].should == {:foo => :bar}
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|