adapter 0.5.2 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ .bundle
2
+ log
3
+ pkg
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - ree
5
+ - 1.9.3
6
+ notifications:
7
+ email: false
8
+ bundler_args: --without guard
@@ -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
@@ -0,0 +1,14 @@
1
+ source :rubygems
2
+ gemspec
3
+
4
+ gem 'rake'
5
+
6
+ group(:guard) do
7
+ gem 'guard'
8
+ gem 'guard-bundler'
9
+ gem 'guard-rspec'
10
+ end
11
+
12
+ group(:test) do
13
+ gem 'rspec'
14
+ end
@@ -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
@@ -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.
@@ -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
@@ -1,7 +1,6 @@
1
- require 'bundler'
2
- Bundler::GemHelper.install_tasks
1
+ require 'bundler/gem_tasks'
3
2
 
4
3
  require 'rspec/core/rake_task'
5
4
  RSpec::Core::RakeTask.new
6
5
 
7
- task :default => :spec
6
+ task :default => :spec
@@ -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
@@ -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"}
@@ -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
- alias get read
45
- alias set write
46
+ alias_method :get, :read
47
+ alias_method :set, :write
46
48
 
47
- alias [] read
48
- alias []= write
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
@@ -18,4 +18,4 @@ module Adapter
18
18
  raise IncompleteAPI.new(missing_methods) unless missing_methods.empty?
19
19
  end
20
20
  end
21
- end
21
+ end
@@ -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
- if key.is_a?(String)
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
- Marshal.dump(value)
25
+ value
26
26
  end
27
27
 
28
28
  def decode(value)
29
- value && Marshal.load(value)
29
+ value
30
30
  end
31
31
  end
32
- end
32
+ end
@@ -14,4 +14,4 @@ module Adapter
14
14
  super("Timeout on lock #{key} exceeded #{timeout} sec")
15
15
  end
16
16
  end
17
- end
17
+ end
@@ -11,7 +11,7 @@ module Adapter
11
11
  end
12
12
 
13
13
  def delete(key)
14
- read(key).tap { client.delete(key_for(key)) }
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
- Adapter::Spec::Types.each do |type, (key, key2)|
7
- it "reads from keys that are #{type}s like a Hash" do
8
- adapter[key].should == nil
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 "writes String values to keys that are #{type}s like a Hash" do
12
- adapter[key] = "value"
13
- adapter[key].should == "value"
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
- it "guarantees that a different String value is retrieved from the #{type} key" do
17
- value = "value"
18
- adapter[key] = value
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 "guarantees that a different Object value is retrieved from the #{type} key" do
23
- value = {:foo => :bar}
24
- adapter[key] = value
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
- it "returns false from key? if a #{type} key is not available" do
29
- adapter.key?(key).should be_false
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 true from key? if a #{type} key is available" do
33
- adapter[key] = "value"
34
- adapter.key?(key).should be_true
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
- it "removes and return an element with a #{type} key from the backing store via delete if it exists" do
38
- adapter[key] = "value"
39
- adapter.delete(key).should == "value"
40
- adapter.key?(key).should be_false
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 nil from delete if an element for a #{type} key does not exist" do
44
- adapter.delete(key).should be_nil
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
- it "removes all #{type} keys from the store with clear" do
48
- adapter[key] = "value"
49
- adapter[key2] = "value2"
50
- adapter.clear
51
- adapter.key?(key).should_not be_true
52
- adapter.key?(key2).should_not be_true
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
- it "fetches a #{type} key with a default value with fetch, if the key is not available" do
56
- adapter.fetch(key, "value").should == "value"
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 "fetches a #{type} key with a block with fetch, if the key is not available" do
60
- adapter.fetch(key) { |k| "value" }.should == "value"
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
- it "does not run the block if the #{type} key is available" do
64
- adapter[key] = "value"
65
- unaltered = "unaltered"
66
- adapter.fetch(key) { unaltered = "altered" }
67
- unaltered.should == "unaltered"
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
- it "fetches a #{type} key with a default value with fetch, if the key is available" do
71
- adapter[key] = "value2"
72
- adapter.fetch(key, "value").should == "value2"
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 "writes #{key} values with #write" do
76
- adapter.write(key, "value")
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
- it "refuses to #[] from keys that cannot be marshalled" do
82
- lambda do
83
- adapter[Struct.new(:foo).new(:bar)]
84
- end.should raise_error(TypeError)
85
- end
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
- it "refuses to fetch from keys that cannot be marshalled" do
88
- lambda do
89
- adapter.fetch(Struct.new(:foo).new(:bar), true)
90
- end.should raise_error(TypeError)
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
- it "refuses to #[]= to keys that cannot be marshalled" do
94
- lambda do
95
- adapter[Struct.new(:foo).new(:bar)] = "value"
96
- end.should raise_error(TypeError)
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
- it "refuses to store to keys that cannot be marshalled" do
100
- lambda do
101
- adapter.write Struct.new(:foo).new(:bar), "value"
102
- end.should raise_error(TypeError)
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
- it "refuses to check for key? if the key cannot be marshalled" do
106
- lambda do
107
- adapter.key? Struct.new(:foo).new(:bar)
108
- end.should raise_error(TypeError)
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
- it "refuses to delete a key if the key cannot be marshalled" do
112
- lambda do
113
- adapter.delete Struct.new(:foo).new(:bar)
114
- end.should raise_error(TypeError)
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
- it "specifies that it is writable via frozen?" do
118
- adapter.should_not be_frozen
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
@@ -1,3 +1,3 @@
1
1
  module Adapter
2
- VERSION = '0.5.2'
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 value for string" do
12
- mod.key_for('foo').should == 'foo'
13
- end
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 "marshals value" do
26
- mod.encode(nil).should == "\004\b0"
27
- mod.encode({'testing' => 'this'}).should == %Q(\004\b{\006\"\ftesting\"\tthis)
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 nil if nil" do
33
- mod.decode(nil).should be_nil
34
- end
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
@@ -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 'a marshaled adapter'
15
- end
15
+ it_should_behave_like 'an adapter'
16
+ end
@@ -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
- ActiveSupport::JSON.encode(value)
117
+ 'encoded'
108
118
  end
109
119
 
110
120
  def decode(value)
111
- ActiveSupport::JSON.decode(value)
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 == ActiveSupport::JSON.encode(hash)
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'] = ActiveSupport::JSON.encode(hash)
126
- adapter.read('foo').should == hash
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
@@ -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
- logger = Logger.new(log_path.join('test.log'))
24
- LogBuddy.init(:logger => logger)
10
+ Bundler.require(:default, :test)
25
11
 
26
12
  Rspec.configure do |c|
27
13
  c.include(ModuleHelpers)
@@ -1,3 +1,3 @@
1
1
  --colour
2
2
  --timeout
3
- 20
3
+ 20
@@ -18,4 +18,4 @@ module ModuleHelpers
18
18
  end
19
19
  end
20
20
  end
21
- end
21
+ end
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
- hash: 15
5
- prerelease: false
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
- files:
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
- - LICENSE
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
- hash: 3
70
- segments:
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ segments:
71
63
  - 0
72
- version: "0"
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
- hash: 3
79
- segments:
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ segments:
80
72
  - 0
81
- version: "0"
73
+ hash: -254287751766179836
82
74
  requirements: []
83
-
84
75
  rubyforge_project:
85
- rubygems_version: 1.3.7
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
@@ -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
@@ -1,5 +0,0 @@
1
- module Adapter
2
- module Spec
3
- Types = {"String" => ["key", "key2"]}
4
- end
5
- end