riak-shim 0.0.9 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +3 -1
- data/README.md +13 -9
- data/lib/riak-shim/persistable.rb +3 -2
- data/lib/riak-shim/store.rb +6 -1
- data/lib/riak-shim/version.rb +1 -1
- data/riak-shim.gemspec +1 -1
- data/spec/persistable_spec.rb +93 -13
- data/spec/spec_helper.rb +1 -0
- data/spec/store_spec.rb +30 -0
- data/spec/support/camelcase.rb +21 -0
- metadata +6 -4
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -35,10 +35,10 @@ Create a config/database.yml containing the details of your Riak setup like so:
|
|
35
35
|
<<: *default
|
36
36
|
bucket_prefix: myapp_test_
|
37
37
|
|
38
|
-
`bucket_prefix will be prefixed to each bucket name, allowing you to point
|
39
|
-
|
40
|
-
|
41
|
-
|
38
|
+
`bucket_prefix` will be prefixed to each bucket name, allowing you to point
|
39
|
+
multiple applications (or multiple copies of the same application) at a
|
40
|
+
single Riak install. During development, this prevents you from stepping on
|
41
|
+
your own toes.
|
42
42
|
|
43
43
|
## Converting a model to use Riak
|
44
44
|
|
@@ -52,22 +52,25 @@ Then, write a #to_hash method which returns a hash representing your object
|
|
52
52
|
|
53
53
|
def to_hash
|
54
54
|
# Return hashified version of your class
|
55
|
+
{ 'foo' => self.foo, 'bar' => self.bar }
|
55
56
|
end
|
56
57
|
|
57
58
|
You'll use Class#from_hash to create an instance from the hash which was
|
58
59
|
pulled from Riak:
|
59
60
|
|
60
61
|
def self.from_hash(data)
|
62
|
+
# Return a fresh instance of your class populated by the hash provided
|
61
63
|
your_obj = new
|
62
64
|
your_obj.foo = data['foo']
|
63
|
-
|
65
|
+
your_obj.bar = data['bar']
|
64
66
|
return your_obj
|
65
67
|
end
|
66
68
|
|
67
|
-
You can now save instances of your class by calling
|
68
|
-
them from Riak by calling
|
69
|
+
You can now save instances of your class by calling `#save` and later retrieve
|
70
|
+
them from Riak by calling `.for_key`:
|
69
71
|
|
70
|
-
|
72
|
+
an_instance.save
|
73
|
+
retrieved_copy = YourClass.for_key(key)
|
71
74
|
|
72
75
|
### Secondary indexes
|
73
76
|
|
@@ -79,6 +82,7 @@ riak-shim will populate a secondary index for that field.
|
|
79
82
|
|
80
83
|
def fields_to_index
|
81
84
|
# Return an Array of hash keys you would like placed into a secondary index.
|
85
|
+
[foo]
|
82
86
|
end
|
83
87
|
|
84
88
|
The `for_index` method retrieves all records whose value for the given index
|
@@ -105,6 +109,6 @@ Return value is an Array of instances of your class matching the query.
|
|
105
109
|
## TODOS
|
106
110
|
|
107
111
|
- Examples directory
|
108
|
-
-
|
112
|
+
- Keep expanding tests
|
109
113
|
- find less horrible way to deal with index names
|
110
114
|
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module Riak
|
2
2
|
module Shim
|
3
3
|
module Persistable
|
4
|
-
attr_writer :store
|
5
4
|
attr_writer :key
|
6
5
|
|
7
6
|
def key
|
@@ -75,7 +74,9 @@ module Riak
|
|
75
74
|
begin
|
76
75
|
raw = bucket.get(key)
|
77
76
|
data = raw.data
|
78
|
-
from_hash(data)
|
77
|
+
result = from_hash(data)
|
78
|
+
result.key = key
|
79
|
+
result
|
79
80
|
rescue Riak::HTTPFailedRequest
|
80
81
|
return nil
|
81
82
|
end
|
data/lib/riak-shim/store.rb
CHANGED
@@ -7,9 +7,14 @@ module Riak
|
|
7
7
|
attr_writer :config_location
|
8
8
|
attr_writer :riak
|
9
9
|
|
10
|
+
class NoSettingsForCurrentEnvError < StandardError; end
|
11
|
+
class RackEnvNotSetError < StandardError; end
|
12
|
+
|
10
13
|
def config
|
11
|
-
env = ENV['RACK_ENV']
|
14
|
+
env = ENV['RACK_ENV'] or raise RackEnvNotSetError.new
|
12
15
|
@config ||= read_config[env]
|
16
|
+
@config or raise NoSettingsForCurrentEnvError.new(
|
17
|
+
"RACK_ENV #{ENV['RACK_ENV']} not specified in #{config_location}.")
|
13
18
|
end
|
14
19
|
|
15
20
|
def read_config
|
data/lib/riak-shim/version.rb
CHANGED
data/riak-shim.gemspec
CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |gem|
|
|
17
17
|
|
18
18
|
gem.add_dependency 'riak-client', '~>1.0.4'
|
19
19
|
gem.add_dependency 'excon'
|
20
|
-
gem.add_dependency 'uuidtools', '~>2.1.
|
20
|
+
gem.add_dependency 'uuidtools', '~>2.1.3'
|
21
21
|
|
22
22
|
gem.add_development_dependency "rake"
|
23
23
|
gem.add_development_dependency "rspec"
|
data/spec/persistable_spec.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'riak-shim/persistable'
|
3
|
+
require 'support/camelcase'
|
3
4
|
|
4
5
|
class PersistableExample
|
5
6
|
include Riak::Shim::Persistable
|
@@ -16,12 +17,27 @@ class PersistableExample
|
|
16
17
|
result.baz = data['baz']
|
17
18
|
result
|
18
19
|
end
|
20
|
+
|
21
|
+
def ==(other)
|
22
|
+
other.instance_of?(self.class) and
|
23
|
+
self.key == other.key and
|
24
|
+
self.foo == other.foo and
|
25
|
+
self.bar == other.bar and
|
26
|
+
self.baz == other.baz
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class PersistableExampleWithIndex < PersistableExample
|
31
|
+
def fields_to_index
|
32
|
+
[:bar, :baz]
|
33
|
+
end
|
19
34
|
end
|
20
35
|
|
21
36
|
describe 'persistable' do
|
22
37
|
let(:persistable) do
|
23
38
|
p = PersistableExample.new ; p.foo = 'boo' ; p.bar = 'who' ; p
|
24
39
|
end
|
40
|
+
let(:bucket) { PersistableExample.bucket }
|
25
41
|
|
26
42
|
before do
|
27
43
|
Riak::Shim::Store.any_instance.stub(:read_config).and_return(DB_CONFIG)
|
@@ -39,7 +55,7 @@ describe 'persistable' do
|
|
39
55
|
|
40
56
|
describe '#bucket' do
|
41
57
|
it 'returns the correct bucket' do
|
42
|
-
|
58
|
+
bucket.name.should == 'test_persistable_example'
|
43
59
|
end
|
44
60
|
end
|
45
61
|
|
@@ -53,13 +69,13 @@ describe 'persistable' do
|
|
53
69
|
it 'increases key count' do
|
54
70
|
expect do
|
55
71
|
persistable.save
|
56
|
-
end.to change{
|
72
|
+
end.to change{ bucket.keys.count }.by(1)
|
57
73
|
end
|
58
74
|
|
59
75
|
it 'can then be retrieved' do
|
60
76
|
persistable.save
|
61
77
|
retrieved = PersistableExample.for_key(persistable.key)
|
62
|
-
retrieved.
|
78
|
+
retrieved.should eq persistable
|
63
79
|
end
|
64
80
|
end
|
65
81
|
|
@@ -70,7 +86,7 @@ describe 'persistable' do
|
|
70
86
|
end
|
71
87
|
|
72
88
|
it 'removes the key' do
|
73
|
-
|
89
|
+
bucket.exists?(persistable.key).should be_false
|
74
90
|
end
|
75
91
|
end
|
76
92
|
|
@@ -92,12 +108,6 @@ describe 'persistable' do
|
|
92
108
|
end
|
93
109
|
|
94
110
|
context 'with a model which needs indexes' do
|
95
|
-
class PersistableExampleWithIndex < PersistableExample
|
96
|
-
def fields_to_index
|
97
|
-
[:bar, :baz]
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
111
|
let(:indexable) { PersistableExampleWithIndex.new }
|
102
112
|
before do
|
103
113
|
indexable.foo = 1
|
@@ -113,21 +123,91 @@ describe 'persistable' do
|
|
113
123
|
end
|
114
124
|
|
115
125
|
describe '#delete_all' do
|
126
|
+
before do
|
127
|
+
10.times do |i|
|
128
|
+
p = PersistableExample.new
|
129
|
+
p.foo, p.bar, p.baz = i, i, i
|
130
|
+
p.save
|
131
|
+
end
|
132
|
+
@keys = bucket.keys
|
133
|
+
PersistableExample.delete_all
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'has no instances in the DB' do
|
137
|
+
@keys.map { |k| bucket.exists?(k).should be_false }
|
138
|
+
end
|
116
139
|
end
|
117
140
|
|
118
141
|
describe '#de_camel' do
|
142
|
+
it 'handles a bacic camel-case name' do
|
143
|
+
DeCamel.each do |camelcase, lowered|
|
144
|
+
PersistableExample.de_camel(camelcase).should eq(lowered)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'handles runs of capitals appropriately' do
|
149
|
+
DeCamelCapsRuns.each do |camelcase, lowered|
|
150
|
+
PersistableExample.de_camel(camelcase).should eq(lowered)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'turns module separators into slashes' do
|
155
|
+
DeCamelWithModule.each do |camelcase, lowered|
|
156
|
+
PersistableExample.de_camel(camelcase).should eq(lowered)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'does not produce collisions' do
|
161
|
+
PersistableExample.de_camel('RiakShim').should_not
|
162
|
+
eq PersistableExample.de_camel('Riak::Shim')
|
163
|
+
end
|
119
164
|
end
|
120
165
|
|
121
166
|
describe '#for_key' do
|
122
|
-
it 'fetches items for keys which exist'
|
123
|
-
|
167
|
+
it 'fetches items for keys which exist' do
|
168
|
+
persistable.save
|
169
|
+
PersistableExample.for_key(persistable.key).should eq persistable
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'returns null when the key does not exist' do
|
173
|
+
PersistableExample.for_key('no such key').should be_nil
|
174
|
+
end
|
124
175
|
end
|
125
176
|
|
126
177
|
describe '#for_index' do
|
178
|
+
before do
|
179
|
+
@indexed = []
|
180
|
+
3.times do |i|
|
181
|
+
indexable = PersistableExampleWithIndex.new
|
182
|
+
indexable.foo = i
|
183
|
+
indexable.bar = 'wombat'
|
184
|
+
indexable.save
|
185
|
+
@indexed << indexable
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
after do
|
190
|
+
PersistableExampleWithIndex.delete_all
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'returns all items which match indexed value' do
|
194
|
+
PersistableExampleWithIndex.for_index('bar_bin', 'wombat').should =~ @indexed
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'returns an empty list when no matches are found' do
|
198
|
+
PersistableExampleWithIndex.for_index('bar_bin', 'chew').should be_empty
|
199
|
+
end
|
127
200
|
end
|
128
201
|
|
129
202
|
describe '#gen_key' do
|
130
|
-
|
203
|
+
before do
|
204
|
+
@keys = []
|
205
|
+
20.times { @keys << PersistableExample.gen_key }
|
206
|
+
end
|
207
|
+
|
208
|
+
it 'produces no duplicates when called a bunch of times' do
|
209
|
+
@keys.uniq!.should be_nil
|
210
|
+
end
|
131
211
|
end
|
132
212
|
end
|
133
213
|
|
data/spec/spec_helper.rb
CHANGED
@@ -2,6 +2,7 @@ $: << './lib'
|
|
2
2
|
require 'riak-shim'
|
3
3
|
require 'pry'
|
4
4
|
|
5
|
+
ENV['RACK_ENV'] = 'test' unless ENV['RACK_ENV']
|
5
6
|
DB_CONFIG = { 'development' => { 'bucket_prefix' => 'dev_', 'host' => "localhost", 'http_port' => 8098},
|
6
7
|
'test' => {'bucket_prefix' => 'test_', 'host' => "localhost", 'http_port' => 8098 }}
|
7
8
|
|
data/spec/store_spec.rb
CHANGED
@@ -25,6 +25,36 @@ describe Riak::Shim::Store do
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
+
describe 'error handling' do
|
29
|
+
before do
|
30
|
+
@stashed_rack_env = ENV['RACK_ENV']
|
31
|
+
end
|
32
|
+
|
33
|
+
after do
|
34
|
+
ENV['RACK_ENV'] = @stashed_rack_env
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'with current RACK_ENV not explicitly configured in database.yml' do
|
38
|
+
before do
|
39
|
+
ENV['RACK_ENV'] = 'production'
|
40
|
+
end
|
41
|
+
|
42
|
+
it "raises an error" do
|
43
|
+
expect { store.config }.to raise_error(Riak::Shim::Store::NoSettingsForCurrentEnvError)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'with no RACK_ENV set' do
|
48
|
+
before do
|
49
|
+
ENV['RACK_ENV'] = nil
|
50
|
+
end
|
51
|
+
|
52
|
+
it "raises an error" do
|
53
|
+
expect { store.config }.to raise_error(Riak::Shim::Store::RackEnvNotSetError)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
28
58
|
describe '#config' do
|
29
59
|
context 'with RACK_ENV=test' do
|
30
60
|
before do
|
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
DeCamel = {
|
3
|
+
"Cheezburger" => "cheezburger",
|
4
|
+
"SpecialGuest" => "special_guest",
|
5
|
+
"Area51Controller" => "area51_controller"
|
6
|
+
}
|
7
|
+
|
8
|
+
DeCamelCapsRuns = {
|
9
|
+
"LOLCat" => "lol_cat",
|
10
|
+
"LOLCatBukkit" => "lol_cat_bukkit",
|
11
|
+
"MayberryRFD" => "mayberry_rfd",
|
12
|
+
"CNN" => "cnn",
|
13
|
+
}
|
14
|
+
|
15
|
+
DeCamelWithModule = {
|
16
|
+
"Riak::Shim" => "riak__shim",
|
17
|
+
"Taco::Bell::Dog" => "taco__bell__dog",
|
18
|
+
"PizzaHut::PersonalPanPizza" => "pizza_hut__personal_pan_pizza",
|
19
|
+
}
|
20
|
+
|
21
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: riak-shim
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.10
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-07
|
12
|
+
date: 2012-08-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: riak-client
|
@@ -50,7 +50,7 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - ~>
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: 2.1.
|
53
|
+
version: 2.1.3
|
54
54
|
type: :runtime
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -58,7 +58,7 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 2.1.
|
61
|
+
version: 2.1.3
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
63
|
name: rake
|
64
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -193,6 +193,7 @@ files:
|
|
193
193
|
- spec/persistable_spec.rb
|
194
194
|
- spec/spec_helper.rb
|
195
195
|
- spec/store_spec.rb
|
196
|
+
- spec/support/camelcase.rb
|
196
197
|
- spec/support/database.yml
|
197
198
|
homepage: https://github.com/mkb/riak-shim
|
198
199
|
licenses: []
|
@@ -223,4 +224,5 @@ test_files:
|
|
223
224
|
- spec/persistable_spec.rb
|
224
225
|
- spec/spec_helper.rb
|
225
226
|
- spec/store_spec.rb
|
227
|
+
- spec/support/camelcase.rb
|
226
228
|
- spec/support/database.yml
|