sander6-daijobu 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/daijobu.rb CHANGED
@@ -1,12 +1,14 @@
1
1
  $:.unshift(File.dirname(__FILE__))
2
2
  require 'daijobu/errors'
3
3
  require 'daijobu/client'
4
+ require 'daijobu/namespace_proxy'
4
5
  require 'daijobu/scheme_set'
5
6
  require 'daijobu/scheme'
6
- require 'daijobu/schemes/marshal'
7
+ require 'daijobu/schemes/eval'
7
8
  require 'daijobu/schemes/json'
9
+ require 'daijobu/schemes/marshal'
10
+ require 'daijobu/schemes/raw'
8
11
  require 'daijobu/schemes/yaml'
9
- require 'daijobu/schemes/eval'
10
12
  require 'daijobu/adapter'
11
13
  require 'daijobu/adapters/mem_cache'
12
14
  require 'daijobu/adapters/tokyo_cabinet'
@@ -8,12 +8,24 @@ module Daijobu
8
8
  @store = store
9
9
  end
10
10
 
11
- def get(key)
12
- @store.get(key, true)
11
+ def get(*keys)
12
+ if keys.size == 0
13
+ nil
14
+ elsif keys.size == 1
15
+ get_one(keys.first)
16
+ else
17
+ keys.inject({}) { |agg, key| agg.merge(key => get_one(key)) }
18
+ end
13
19
  end
14
20
 
15
21
  def set(key, value)
16
- @store.set(key, value, 0, true)
22
+ @store.add(key, value, 0, true)
23
+ end
24
+
25
+ private
26
+
27
+ def get_one(key)
28
+ @store.get(key, true)
17
29
  end
18
30
 
19
31
  end
@@ -8,8 +8,14 @@ module Daijobu
8
8
  @store = store
9
9
  end
10
10
 
11
- def get(key)
12
- @store[key]
11
+ def get(*keys)
12
+ if keys.size == 0
13
+ nil
14
+ elsif keys.size == 1
15
+ @store[keys.first]
16
+ else
17
+ @store.lget(keys)
18
+ end
13
19
  end
14
20
 
15
21
  def set(key, value)
@@ -8,8 +8,14 @@ module Daijobu
8
8
  @store = store
9
9
  end
10
10
 
11
- def get(key)
12
- @store[key]
11
+ def get(*keys)
12
+ if keys.size == 0
13
+ nil
14
+ elsif keys.size == 1
15
+ @store[keys.first]
16
+ else
17
+ @store.lget(keys)
18
+ end
13
19
  end
14
20
 
15
21
  def set(key, value)
@@ -1,27 +1,32 @@
1
1
  module Daijobu
2
2
  class Client
3
3
 
4
- def initialize(casket, *schemes)
5
- @adapter = Daijobu::Adapter.get(casket)
6
- @schemes = Daijobu::SchemeSet.new(*schemes)
4
+ def initialize(casket, options = {})
5
+ @adapter = Daijobu::Adapter.get(casket)
6
+ @read_schemes = Daijobu::SchemeSet.new(options[:schemes] || options[:read])
7
+ @write_schemes = Daijobu::SchemeSet.new(options[:schemes] || options[:write])
7
8
  end
8
9
 
9
- def [](key)
10
- parse(@adapter.get(key))
10
+ def [](*keys)
11
+ __parse__(@adapter.get(*keys.collect { |key| key.to_s }))
11
12
  end
12
13
 
13
14
  def []=(key, value)
14
- @adapter.set(key, unparse(value))
15
+ @adapter.set(key.to_s, __unparse__(value))
16
+ end
17
+
18
+ def method_missing(name, *args)
19
+ args.empty? ? Daijobu::NamespaceProxy.new(self, name) : Daijobu::NamespaceProxy.new(self, name)[*args]
15
20
  end
16
21
 
17
22
  private
18
23
 
19
- def parse(str)
20
- @schemes.parse(str)
24
+ def __parse__(str)
25
+ @read_schemes.parse(str)
21
26
  end
22
27
 
23
- def unparse(obj)
24
- @schemes.unparse(obj)
28
+ def __unparse__(obj)
29
+ @write_schemes.unparse(obj)
25
30
  end
26
31
 
27
32
  end
@@ -0,0 +1,32 @@
1
+ module Daijobu
2
+ class NamespaceProxy
3
+
4
+ @@default_separator = ':'
5
+ def self.default_separator
6
+ @@default_separator
7
+ end
8
+
9
+ def self.default_separator=(separator)
10
+ @@default_separator = separator
11
+ end
12
+
13
+ def initialize(owner, namespace, separator = @@default_separator)
14
+ @owner = owner
15
+ @namespace = namespace.to_s
16
+ @separator = separator
17
+ end
18
+
19
+ def [](key)
20
+ @owner["#{@namespace}#{@separator}#{key}"]
21
+ end
22
+
23
+ def []=(key, value)
24
+ @owner["#{@namespace}#{@separator}#{key}"] = value
25
+ end
26
+
27
+ def method_missing(namespace, *args)
28
+ separator = args.shift || @@default_separator
29
+ Daijobu::NamespaceProxy.new(@owner, "#{@namespace}#{@separator}#{namespace}", separator)
30
+ end
31
+ end
32
+ end
@@ -5,8 +5,10 @@ module Daijobu
5
5
 
6
6
  attr_reader :current
7
7
 
8
- def initialize(*schemes)
9
- @schemes = (schemes.empty? ? DEFAULT : schemes).collect { |scheme| Daijobu::Scheme.get(scheme) }
8
+ def initialize(schemes = nil)
9
+ schemes = Array(schemes)
10
+ schemes = DEFAULT if schemes.empty?
11
+ @schemes = schemes.collect { |scheme| Daijobu::Scheme.get(scheme) }
10
12
  @current = 0
11
13
  end
12
14
 
@@ -0,0 +1,15 @@
1
+ module Daijobu
2
+ module Scheme
3
+ class Raw
4
+
5
+ def parse(str)
6
+ str
7
+ end
8
+
9
+ def unparse(obj)
10
+ obj
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -6,9 +6,6 @@ describe Daijobu::Adapter do
6
6
 
7
7
  before do
8
8
  Daijobu::Adapter.stubs(:defined?).returns(true)
9
- MemCache = Class.new unless defined?(MemCache)
10
- Rufus::Tokyo::Cabinet = Class.new unless defined?(Rufus::Tokyo::Cabinet)
11
- Rufus::Tokyo::Tyrant = Class.new unless defined?(Rufus::Tokyo::Tyrant)
12
9
  @casket = stub("fake casket")
13
10
  end
14
11
 
@@ -12,11 +12,29 @@ describe Daijobu::Adapter::MemCacheAdapter do
12
12
  @stubby.expects(:get).with('key', true)
13
13
  @adapter.get('key')
14
14
  end
15
+
16
+ describe "with no arguments" do
17
+ it "should return nil" do
18
+ @adapter.get.should be_nil
19
+ end
20
+ end
21
+
22
+ describe "with multiple arguments" do
23
+ it "should call #get for each key" do
24
+ @stubby.expects(:get).times(3)
25
+ @adapter.get('key1', 'key2', 'key3')
26
+ end
27
+
28
+ it "should return a hash" do
29
+ @stubby.stubs(:get)
30
+ @adapter.get('key1', 'key2', 'key3').should be_an_instance_of(Hash)
31
+ end
32
+ end
15
33
  end
16
34
 
17
35
  describe "set" do
18
- it "should call #set on the store and write as raw" do
19
- @stubby.expects(:set).with('key', 'value', 0, true)
36
+ it "should call #add on the store and write as raw" do
37
+ @stubby.expects(:add).with('key', 'value', 0, true)
20
38
  @adapter.set('key', 'value')
21
39
  end
22
40
  end
@@ -12,6 +12,19 @@ describe Daijobu::Adapter::TokyoCabinetAdapter do
12
12
  @stubby.expects(:[]).with('key')
13
13
  @adapter.get('key')
14
14
  end
15
+
16
+ describe "with no arguments" do
17
+ it "should return nil" do
18
+ @adapter.get.should be_nil
19
+ end
20
+ end
21
+
22
+ describe "with multiple arguments" do
23
+ it "should call #lget on all the keys" do
24
+ @stubby.expects(:lget).with(['key1', 'key2', 'key3'])
25
+ @adapter.get('key1', 'key2', 'key3')
26
+ end
27
+ end
15
28
  end
16
29
 
17
30
  describe "set" do
@@ -12,6 +12,19 @@ describe Daijobu::Adapter::TokyoTyrantAdapter do
12
12
  @stubby.expects(:[]).with('key')
13
13
  @adapter.get('key')
14
14
  end
15
+
16
+ describe "with no arguments" do
17
+ it "should return nil" do
18
+ @adapter.get.should be_nil
19
+ end
20
+ end
21
+
22
+ describe "with multiple arguments" do
23
+ it "should call #lget on all the keys" do
24
+ @stubby.expects(:lget).with(['key1', 'key2', 'key3'])
25
+ @adapter.get('key1', 'key2', 'key3')
26
+ end
27
+ end
15
28
  end
16
29
 
17
30
  describe "set" do
@@ -3,7 +3,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
3
3
  describe Daijobu::Client do
4
4
 
5
5
  before do
6
- @casket = Rufus::Tokyo::Cabinet.new('*')
6
+ @casket = Rufus::Tokyo::Cabinet.new # not a real Rufus::Tokyo::Cabinet. See spec_helper.
7
7
  end
8
8
 
9
9
  describe "initialization" do
@@ -13,11 +13,23 @@ describe Daijobu::Client do
13
13
  Daijobu::Client.new(@casket)
14
14
  end
15
15
 
16
- it "should set the schemes based on the scheme list given" do
17
- Daijobu::SchemeSet.expects(:new).with(:json, :yaml)
18
- Daijobu::Client.new(@casket, :json, :yaml)
16
+ it "should set the read and write schemes based on the :schemes scheme list given" do
17
+ Daijobu::SchemeSet.expects(:new).with([:json, :yaml]).twice
18
+ Daijobu::Client.new(@casket, :schemes => [:json, :yaml])
19
19
  end
20
-
20
+
21
+ it "should set the read schemes based on the :read scheme list given" do
22
+ Daijobu::SchemeSet.expects(:new).with([:json, :yaml]).once
23
+ Daijobu::SchemeSet.expects(:new).with(nil).once
24
+ Daijobu::Client.new(@casket, :read => [:json, :yaml])
25
+ end
26
+
27
+ it "should set the write schemes based on the :write scheme list given" do
28
+ Daijobu::SchemeSet.expects(:new).with(nil).once
29
+ Daijobu::SchemeSet.expects(:new).with([:json, :yaml]).once
30
+ Daijobu::Client.new(@casket, :write => [:json, :yaml])
31
+ end
32
+
21
33
  end
22
34
 
23
35
  describe "methods" do
@@ -31,43 +43,84 @@ describe Daijobu::Client do
31
43
  @stringy = "woohoo!"
32
44
  end
33
45
 
34
- describe "#[]" do
46
+ describe " #[]" do
35
47
  it "should call #get on the adapter" do
36
48
  @adapter.expects(:get).with('key')
37
49
  @daijobu['key']
38
50
  end
51
+
52
+ it "should be indifferent to strings and symbols" do
53
+ @adapter.expects(:get).with('key')
54
+ @daijobu[:key]
55
+ end
56
+
57
+ it "should be indifferent to integers or strings" do
58
+ @adapter.expects(:get).with('123')
59
+ @daijobu[123]
60
+ end
61
+
62
+ it "should allow you to get multiple keys at once" do
63
+ @adapter.expects(:get).with('key1', 'key2', 'key3')
64
+ @daijobu['key1', 'key2', 'key3']
65
+ end
39
66
  end
40
67
 
41
- describe "#[]=" do
68
+ describe " #[]=" do
42
69
  before do
43
- @daijobu.stubs(:unparse).returns(@stringy)
70
+ @daijobu.stubs(:__unparse__).returns(@stringy)
44
71
  end
45
72
 
46
73
  it "should call set on the adapter" do
47
74
  @adapter.expects(:set).with('key', @stringy)
48
75
  @daijobu['key'] = @stringy
49
76
  end
77
+
78
+ it "should be indifferent to strings and symbols" do
79
+ @adapter.expects(:set).with('key', @stringy)
80
+ @daijobu[:key] = @stringy
81
+ end
50
82
  end
51
83
  end
52
84
 
53
85
 
54
86
  describe "for parsing and unparsing" do
55
87
  before do
56
- @schemes = @daijobu.instance_variable_get(:@schemes)
57
- @stringy = "woohoo!"
88
+ @read_schemes = @daijobu.instance_variable_get(:@read_schemes)
89
+ @write_schemes = @daijobu.instance_variable_get(:@write_schemes)
90
+ @stringy = "woohoo!"
58
91
  end
59
92
 
60
- describe "#parse" do
61
- it "should call parse on the schemes" do
62
- @schemes.expects(:parse).with(@stringy)
63
- @daijobu.__send__(:parse, @stringy)
93
+ describe " #__parse__" do
94
+ it "should call parse on the read schemes" do
95
+ @read_schemes.expects(:parse).with(@stringy)
96
+ @daijobu.__send__(:__parse__, @stringy)
97
+ end
98
+ end
99
+
100
+ describe " #__unparse__" do
101
+ it "should call unparse on the write schemes" do
102
+ @write_schemes.expects(:unparse).with(@stringy)
103
+ @daijobu.__send__(:__unparse__, @stringy)
64
104
  end
65
105
  end
106
+ end
66
107
 
67
- describe "#unparse" do
68
- it "should call unparse on the schemes" do
69
- @schemes.expects(:unparse).with(@stringy)
70
- @daijobu.__send__(:unparse, @stringy)
108
+ describe "method_missing" do
109
+
110
+ describe "with no arguments" do
111
+ it "should return a namespace proxy with namespace as the missing method" do
112
+ proxy = @daijobu.prefix
113
+ proxy.should be_an_instance_of(Daijobu::NamespaceProxy)
114
+ proxy.instance_variable_get(:@namespace).should == 'prefix'
115
+ end
116
+ end
117
+
118
+ describe "with arguments" do
119
+ it "should call #[] on the proxy with the arguments" do
120
+ proxy = stub('fake-daijobu-proxy!')
121
+ Daijobu::NamespaceProxy.expects(:new).with(@daijobu, :prefix).returns(proxy)
122
+ proxy.expects(:[]).with('key')
123
+ @daijobu.prefix('key')
71
124
  end
72
125
  end
73
126
  end
@@ -0,0 +1,60 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Daijobu::NamespaceProxy do
4
+
5
+ before do
6
+ @daijobu = stub('fake-daijobu-client!')
7
+ end
8
+
9
+ describe "initialization" do
10
+
11
+ it "should set the owner as the given owner" do
12
+ Daijobu::NamespaceProxy.new(@daijobu, 'prefix').instance_variable_get(:@owner).should == @daijobu
13
+ end
14
+
15
+ it "should set the namespace as the given namespace" do
16
+ Daijobu::NamespaceProxy.new(@daijobu, 'prefix').instance_variable_get(:@namespace).should == 'prefix'
17
+ end
18
+
19
+ it "should be indifferent to strings or symbols as the namespace" do
20
+ Daijobu::NamespaceProxy.new(@daijobu, :prefix).instance_variable_get(:@namespace).should == 'prefix'
21
+ end
22
+
23
+ it "should initialize with the class-level default separator" do
24
+ Daijobu::NamespaceProxy.new(@daijobu, 'prefix').instance_variable_get(:@separator).should == Daijobu::NamespaceProxy.default_separator
25
+ end
26
+
27
+ it "should set the separator as the given separator" do
28
+ Daijobu::NamespaceProxy.new(@daijobu, 'prefix', '/').instance_variable_get(:@separator).should == '/'
29
+ end
30
+
31
+ end
32
+
33
+ describe "methods" do
34
+ before do
35
+ @proxy = Daijobu::NamespaceProxy.new(@daijobu, 'prefix')
36
+ end
37
+
38
+ describe "#[]" do
39
+ it "should send #[] with the namespaced key to the owner" do
40
+ @daijobu.expects(:[]).with('prefix:key')
41
+ @proxy['key']
42
+ end
43
+ end
44
+
45
+ describe "#[]=" do
46
+ it "should send #[]= with the namespaced key to the owner" do
47
+ @daijobu.expects(:[]=).with('prefix:key', 'value')
48
+ @proxy['key'] = 'value'
49
+ end
50
+ end
51
+
52
+ describe "method_missing" do
53
+ it "should return a new proxy with compounded namespace" do
54
+ new_proxy = @proxy.another_prefix
55
+ new_proxy.should be_an_instance_of(Daijobu::NamespaceProxy)
56
+ new_proxy.instance_variable_get(:@namespace).should == 'prefix:another_prefix'
57
+ end
58
+ end
59
+ end
60
+ end
@@ -19,11 +19,18 @@ describe Daijobu::SchemeSet do
19
19
  schemes[3].should be_an_instance_of(Daijobu::Scheme::Eval)
20
20
  end
21
21
 
22
+ it "should accept an array of schemes" do
23
+ lambda { Daijobu::SchemeSet.new([:json, :yaml]) }.should_not raise_error
24
+ end
25
+
26
+ it "should accept a single scheme" do
27
+ lambda { Daijobu::SchemeSet.new(:json) }.should_not raise_error
28
+ end
22
29
  end
23
30
 
24
31
  describe "initialization with a specified scheme pattern" do
25
32
  before do
26
- @scheme_set = Daijobu::SchemeSet.new(:eval, :yaml)
33
+ @scheme_set = Daijobu::SchemeSet.new([:eval, :yaml])
27
34
  end
28
35
 
29
36
  it "should have the proper schemes in the given order" do
@@ -82,7 +89,7 @@ describe Daijobu::SchemeSet do
82
89
 
83
90
  describe "#parse" do
84
91
  before do
85
- @scheme_set = Daijobu::SchemeSet.new(:json)
92
+ @scheme_set = Daijobu::SchemeSet.new([:json])
86
93
  @stringy = '{ "thing" : 10 }'
87
94
  @hashy = { "thing" => 10 }
88
95
  end
@@ -118,7 +125,7 @@ describe Daijobu::SchemeSet do
118
125
  @stringy = '{ "thing" : 10 }'
119
126
  @hashy = { "thing" => 10 }
120
127
 
121
- @scheme_set = Daijobu::SchemeSet.new(:marshal, :yaml, :json)
128
+ @scheme_set = Daijobu::SchemeSet.new([:marshal, :yaml, :json])
122
129
  @schemes = @scheme_set.instance_variable_get(:@schemes)
123
130
  @marshal_scheme = @schemes[0]
124
131
  @yaml_scheme = @schemes[1]
@@ -136,7 +143,7 @@ describe Daijobu::SchemeSet do
136
143
 
137
144
  describe "#unparse" do
138
145
  before do
139
- @scheme_set = Daijobu::SchemeSet.new(:json)
146
+ @scheme_set = Daijobu::SchemeSet.new([:json])
140
147
  @stringy = '{ "thing" : 10 }'
141
148
  @hashy = { "thing" => 10 }
142
149
  end
@@ -172,7 +179,7 @@ describe Daijobu::SchemeSet do
172
179
  @stringy = '{ "thing" : 10 }'
173
180
  @hashy = { "thing" => 10 }
174
181
 
175
- @scheme_set = Daijobu::SchemeSet.new(:marshal, :yaml, :json)
182
+ @scheme_set = Daijobu::SchemeSet.new([:marshal, :yaml, :json])
176
183
  @schemes = @scheme_set.instance_variable_get(:@schemes)
177
184
  @marshal_scheme = @schemes[0]
178
185
  @yaml_scheme = @schemes[1]
@@ -0,0 +1,35 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe Daijobu::Scheme::Raw do
4
+
5
+ before do
6
+ @scheme = Daijobu::Scheme::Raw.new
7
+ end
8
+
9
+ describe "#parse" do
10
+ before do
11
+ @stringy = '{ "thing" => 10 }'
12
+ end
13
+
14
+ it "should do nothing to the given string" do
15
+ @scheme.parse(@stringy).should == @stringy
16
+ end
17
+
18
+ describe "when the input string is nil" do
19
+ it "should return nil" do
20
+ @scheme.parse(nil).should be_nil
21
+ end
22
+ end
23
+ end
24
+
25
+ describe "#unparse" do
26
+ before do
27
+ @hashy = { "thing" => 10 }
28
+ end
29
+
30
+ it "should do nothing to the given object" do
31
+ @scheme.unparse(@hashy).should == @hashy
32
+ end
33
+ end
34
+
35
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,12 +1,18 @@
1
1
  require 'rubygems'
2
2
  require 'spec'
3
3
  require 'mocha'
4
- require 'rufus/tokyo'
5
4
 
6
5
  $LOAD_PATH.unshift(File.dirname(__FILE__))
7
6
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
8
7
  require 'daijobu'
9
8
 
9
+ # Some fake contants for the classes and stuff referred to.
10
+ MemCache = Class.new unless defined?(MemCache)
11
+ Rufus = Module.new unless defined?(Rufus)
12
+ Rufus::Tokyo = Module.new unless defined?(Rufus::Tokyo)
13
+ Rufus::Tokyo::Cabinet = Class.new unless defined?(Rufus::Tokyo::Cabinet)
14
+ Rufus::Tokyo::Tyrant = Class.new unless defined?(Rufus::Tokyo::Tyrant)
15
+
10
16
  Spec::Runner.configure do |config|
11
17
  config.mock_with :mocha
12
18
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sander6-daijobu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sander Hartlage
@@ -30,6 +30,7 @@ files:
30
30
  - lib/daijobu/adapter.rb
31
31
  - lib/daijobu/client.rb
32
32
  - lib/daijobu/errors.rb
33
+ - lib/daijobu/namespace_proxy.rb
33
34
  - lib/daijobu/scheme.rb
34
35
  - lib/daijobu/scheme_set.rb
35
36
  - lib/daijobu/adapters/mem_cache.rb
@@ -38,6 +39,7 @@ files:
38
39
  - lib/daijobu/schemes/eval.rb
39
40
  - lib/daijobu/schemes/json.rb
40
41
  - lib/daijobu/schemes/marshal.rb
42
+ - lib/daijobu/schemes/raw.rb
41
43
  - lib/daijobu/schemes/yaml.rb
42
44
  has_rdoc: false
43
45
  homepage: http://github.com/sander6/daijobu
@@ -72,10 +74,12 @@ test_files:
72
74
  - spec/daijobu/adapters/tokyo_tyrant_spec.rb
73
75
  - spec/daijobu/client_spec.rb
74
76
  - spec/daijobu/errors_spec.rb
77
+ - spec/daijobu/namespace_proxy_spec.rb
75
78
  - spec/daijobu/scheme_set_spec.rb
76
79
  - spec/daijobu/scheme_spec.rb
77
80
  - spec/daijobu/schemes/eval_spec.rb
78
81
  - spec/daijobu/schemes/json_spec.rb
79
82
  - spec/daijobu/schemes/marshal_spec.rb
83
+ - spec/daijobu/schemes/raw_spec.rb
80
84
  - spec/daijobu/schemes/yaml_spec.rb
81
85
  - spec/spec_helper.rb