rrrmatey 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.md +16 -0
- data/README.md +249 -0
- data/RELEASE_NOTES.md +26 -0
- data/Rakefile +39 -0
- data/lib/rrrmatey.rb +8 -0
- data/lib/rrrmatey/crud_controller.rb +97 -0
- data/lib/rrrmatey/discrete_result.rb +31 -0
- data/lib/rrrmatey/errors.rb +11 -0
- data/lib/rrrmatey/retryable.rb +28 -0
- data/lib/rrrmatey/string_model/connection_methods.rb +47 -0
- data/lib/rrrmatey/string_model/consumer_adapter_methods.rb +9 -0
- data/lib/rrrmatey/string_model/delete_methods.rb +12 -0
- data/lib/rrrmatey/string_model/field_definition_methods.rb +101 -0
- data/lib/rrrmatey/string_model/find_methods.rb +85 -0
- data/lib/rrrmatey/string_model/index_methods.rb +90 -0
- data/lib/rrrmatey/string_model/namespaced_key_methods.rb +21 -0
- data/lib/rrrmatey/string_model/string_model.rb +92 -0
- data/lib/rrrmatey/type_coercion.rb +61 -0
- data/lib/rrrmatey/version.rb +3 -0
- data/spec/rrrmatey/crud_controller/crud_controller_spec.rb +258 -0
- data/spec/rrrmatey/crud_controller/model_methods_spec.rb +26 -0
- data/spec/rrrmatey/discrete_result_spec.rb +104 -0
- data/spec/rrrmatey/retryable_spec.rb +95 -0
- data/spec/rrrmatey/string_model/connection_methods_spec.rb +64 -0
- data/spec/rrrmatey/string_model/consumer_adapter_methods_spec.rb +43 -0
- data/spec/rrrmatey/string_model/delete_methods_spec.rb +36 -0
- data/spec/rrrmatey/string_model/field_definition_methods_spec.rb +51 -0
- data/spec/rrrmatey/string_model/find_methods_spec.rb +147 -0
- data/spec/rrrmatey/string_model/index_methods_spec.rb +231 -0
- data/spec/rrrmatey/string_model/namespaced_key_methods_spec.rb +34 -0
- data/spec/rrrmatey/string_model/string_model_spec.rb +208 -0
- data/spec/spec_helper.rb +16 -0
- metadata +148 -0
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Conn
|
4
|
+
def get(id)
|
5
|
+
{ :id => id }
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class ConnPool
|
10
|
+
def initialize(opts = {})
|
11
|
+
@conn = Conn.new()
|
12
|
+
@errors = opts[:errors] || -1
|
13
|
+
end
|
14
|
+
|
15
|
+
def with(&block)
|
16
|
+
if @errors > 0
|
17
|
+
@errors -= 1
|
18
|
+
raise "errors remaining: #{@errors}"
|
19
|
+
else
|
20
|
+
block.call(@conn)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe RRRMatey::Retryable do
|
26
|
+
describe '#initialize' do
|
27
|
+
let(:conn) { Conn.new() }
|
28
|
+
let(:conn_pool) { ConnPool.new() }
|
29
|
+
let(:default) { RRRMatey::Retryable.new(conn) }
|
30
|
+
let(:default_pool) { RRRMatey::Retryable.new(conn_pool) }
|
31
|
+
let(:optioned) { RRRMatey::Retryable.new(conn_pool,
|
32
|
+
:retries => 5,
|
33
|
+
:retry_delay => 0.01) }
|
34
|
+
|
35
|
+
it 'has sane defaults for conn_pool' do
|
36
|
+
expect(default_pool.instance_variable_get(:@retries)).to eq(3)
|
37
|
+
expect(default_pool.instance_variable_get(:@retry_delay)).to eq(0.1)
|
38
|
+
expect(default_pool.instance_variable_get(:@conn)).to eq(conn_pool)
|
39
|
+
expect(default_pool.instance_variable_get(:@conn_respond_to_with)).to be(true)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'has sane defaults for conn' do
|
43
|
+
expect(default.instance_variable_get(:@retries)).to eq(3)
|
44
|
+
expect(default.instance_variable_get(:@retry_delay)).to eq(0.1)
|
45
|
+
expect(default.instance_variable_get(:@conn)).to eq(conn)
|
46
|
+
expect(default.instance_variable_get(:@conn_respond_to_with)).to be(false)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'accepts options' do
|
50
|
+
expect(optioned.instance_variable_get(:@retries)).to eq(5)
|
51
|
+
expect(optioned.instance_variable_get(:@retry_delay)).to eq(0.01)
|
52
|
+
expect(optioned.instance_variable_get(:@conn)).to eq(conn_pool)
|
53
|
+
expect(optioned.instance_variable_get(:@conn_respond_to_with)).to be(true)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '#with' do
|
58
|
+
let(:conn) { Conn.new() }
|
59
|
+
let(:conn_pool) { ConnPool.new() }
|
60
|
+
let(:flappy_conn) { ConnPool.new(:errors => 2) }
|
61
|
+
let(:failing_conn) { ConnPool.new(:errors => 10) }
|
62
|
+
let(:optioned) { RRRMatey::Retryable.new(conn,
|
63
|
+
:retries => 5,
|
64
|
+
:retry_delay => 0.01) }
|
65
|
+
let(:optioned_pool) { RRRMatey::Retryable.new(conn_pool,
|
66
|
+
:retries => 5,
|
67
|
+
:retry_delay => 0.01) }
|
68
|
+
let(:flappy_optioned_pool) { RRRMatey::Retryable.new(flappy_conn,
|
69
|
+
:retries => 5,
|
70
|
+
:retry_delay => 0.01) }
|
71
|
+
let(:failing_optioned_pool) { RRRMatey::Retryable.new(failing_conn,
|
72
|
+
:retries => 5,
|
73
|
+
:retry_delay => 0.01) }
|
74
|
+
|
75
|
+
it 'yields nil if !block.given?' do
|
76
|
+
expect(optioned.with()).to be(nil)
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'yields block response on no error for conn' do
|
80
|
+
expect(optioned.with { |c| c.get(3) }).to eq({:id => 3})
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'yields block response on no error for conn_pool' do
|
84
|
+
expect(optioned_pool.with { |c| c.get(3) }).to eq({:id => 3})
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'yields block response for flappy pool' do
|
88
|
+
expect(flappy_optioned_pool.with { |c| c.get(3) }).to eq({:id => 3})
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'raises for failing pool' do
|
92
|
+
expect{failing_optioned_pool.with { |c| c.get(3) }}.to raise_error(RuntimeError)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class ConnectionModel
|
4
|
+
extend RRRMatey::StringModel::ConnectionMethods
|
5
|
+
|
6
|
+
class ConnPool
|
7
|
+
def initialize(conn)
|
8
|
+
@conn = conn
|
9
|
+
end
|
10
|
+
|
11
|
+
def with(&block)
|
12
|
+
block.call(@conn)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Conn
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe RRRMatey::StringModel::ConnectionMethods do
|
21
|
+
context 'with riak and cache_proxy setup' do
|
22
|
+
let(:conn) { ConnectionModel::ConnPool.new(ConnectionModel::Conn.new()) }
|
23
|
+
let(:model_klass) {
|
24
|
+
m = ConnectionModel
|
25
|
+
m.riak = conn
|
26
|
+
m.cache_proxy = conn
|
27
|
+
m
|
28
|
+
}
|
29
|
+
|
30
|
+
describe '#cache_proxy' do
|
31
|
+
it 'yields values from self' do
|
32
|
+
expect(model_klass.cache_proxy).to eq(conn)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#riak' do
|
37
|
+
it 'yields values from self' do
|
38
|
+
expect(model_klass.riak).to eq(conn)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'with or without riak and cache_proxy setup' do
|
44
|
+
let(:model_klass) {
|
45
|
+
m = ConnectionModel
|
46
|
+
m.riak = nil
|
47
|
+
m.cache_proxy = nil
|
48
|
+
m
|
49
|
+
}
|
50
|
+
let(:string_model_klass) { RRRMatey::StringModel }
|
51
|
+
|
52
|
+
describe '#cache_proxy' do
|
53
|
+
it 'yields values from StringModel' do
|
54
|
+
expect(model_klass.cache_proxy).to eq(string_model_klass.cache_proxy)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe '#riak' do
|
59
|
+
it 'yields values from StringModel' do
|
60
|
+
expect(model_klass.riak).to eq(string_model_klass.riak)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class SomeModel
|
4
|
+
extend RRRMatey::StringModel::ConsumerAdapterMethods
|
5
|
+
|
6
|
+
attr_accessor :id, :name, :content_type
|
7
|
+
|
8
|
+
def self.object_from_hash(h, id, content_type)
|
9
|
+
sm = SomeModel.new()
|
10
|
+
sm.id = id
|
11
|
+
sm.content_type = content_type
|
12
|
+
sm.name = h[:name] || name
|
13
|
+
sm
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe RRRMatey::StringModel::ConsumerAdapterMethods do
|
18
|
+
describe '#from_params' do
|
19
|
+
let(:model_klass) { SomeModel }
|
20
|
+
let(:params) { { :id => 'di', :name => 'eman' } }
|
21
|
+
let(:model_params_id_content_type) { SomeModel.from_params(params, 'dis', :xml) }
|
22
|
+
let(:model_params_id) { SomeModel.from_params(params, 'dis') }
|
23
|
+
let(:model_params) { SomeModel.from_params(params) }
|
24
|
+
|
25
|
+
it 'yields a model from params hash, id, and content-type' do
|
26
|
+
expect(model_params_id_content_type.name).to eq(params[:name])
|
27
|
+
expect(model_params_id_content_type.id).to eq('dis')
|
28
|
+
expect(model_params_id_content_type.content_type).to eq(:xml)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'yields a model from params hash and id' do
|
32
|
+
expect(model_params_id.name).to eq(params[:name])
|
33
|
+
expect(model_params_id.id).to eq('dis')
|
34
|
+
expect(model_params_id.content_type).to eq(:json)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'yields a model from params hash' do
|
38
|
+
expect(model_params.name).to eq(params[:name])
|
39
|
+
expect(model_params.id).to eq(params[:id])
|
40
|
+
expect(model_params.content_type).to eq(:json)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RRRMatey::StringModel::DeleteMethods do
|
4
|
+
context 'with or without cache_proxy setup' do
|
5
|
+
describe '#delete' do
|
6
|
+
let(:model) { StringModelKlass.new() }
|
7
|
+
|
8
|
+
it 'yields 0 if cache_proxy is not setup' do
|
9
|
+
model.id = 'di'
|
10
|
+
expect(model.delete()).to eq(0)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'with cache_proxy setup' do
|
16
|
+
describe '#delete' do
|
17
|
+
let(:model_klass) { StringModelKlass }
|
18
|
+
let(:model) {
|
19
|
+
m = model_klass.new()
|
20
|
+
m.class.cache_proxy = StringModelKlass::ConnPool.new(StringModelKlass::Conn.new)
|
21
|
+
m.class.cache_proxy.with { |c| c.set(model_klass.namespaced_key('di'), 'exists') }
|
22
|
+
m
|
23
|
+
}
|
24
|
+
|
25
|
+
it 'yields 0 if value was not in the store' do
|
26
|
+
model.id = 'dne'
|
27
|
+
expect(model.delete()).to eq(0)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'yields 1 if the value was in the store' do
|
31
|
+
model.id = 'di'
|
32
|
+
expect(model.delete()).to eq(1)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class SomeFieldyModel
|
4
|
+
extend RRRMatey::StringModel::FieldDefinitionMethods
|
5
|
+
|
6
|
+
field :name, :type => :string
|
7
|
+
field :hornery, :type => :boolean
|
8
|
+
field :created, :type => :date
|
9
|
+
field :bounties, :type => :integer
|
10
|
+
field :ales, :type => :long
|
11
|
+
field :chins, :type => :double
|
12
|
+
field :corks, :type => :float
|
13
|
+
end
|
14
|
+
|
15
|
+
describe RRRMatey::StringModel::FieldDefinitionMethods do
|
16
|
+
let(:model_klass) { SomeFieldyModel }
|
17
|
+
let(:model) { SomeFieldyModel.new }
|
18
|
+
|
19
|
+
describe '#fields' do
|
20
|
+
it 'yields fields defined on the model' do
|
21
|
+
expect(model_klass.fields).to eq([:name_s, :hornery_b, :created_ti, :bounties_i, :ales_l, :chins_d, :corks_f])
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'creates accessors for defined fields' do
|
25
|
+
expect(model.respond_to?(:name)).to be(true)
|
26
|
+
expect(model.respond_to?(:name=)).to be(true)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'allows fields to be defined programmatically' do
|
30
|
+
model_klass.fields(:name, :birth)
|
31
|
+
expect(model_klass.fields).to eq([:name, :birth])
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'specializes initialize, mapping all opts set to field set ops' do
|
35
|
+
expect(model_klass.new(:name => 'eman').name).to eq('eman')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#consumer_fields' do
|
40
|
+
it 'yields consumer fields' do
|
41
|
+
model_klass.fields(:name_s, :hornery_b, :created_ti, :bounties_i, :ales_l, :chins_d, :corks_f)
|
42
|
+
expect(model_klass.consumer_fields).to eq([:name, :hornery, :created, :bounties, :ales, :chins, :corks])
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '#append_type' do
|
47
|
+
it 'raises for unsupported type' do
|
48
|
+
expect{model_klass.send(:append_type, :some_field, :some_unknown_type)}.to raise_error(RRRMatey::UnsupportedTypeError)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class FindModel
|
4
|
+
extend RRRMatey::StringModel::FindMethods
|
5
|
+
|
6
|
+
@@cache_proxy = nil
|
7
|
+
|
8
|
+
def self.cache_proxy
|
9
|
+
@@cache_proxy
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.cache_proxy=(v)
|
13
|
+
@@cache_proxy = v
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.item_name()
|
17
|
+
'find_model'
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.namespace
|
21
|
+
'find_models'
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.namespaced_key(id)
|
25
|
+
"#{namespace}:#{id}"
|
26
|
+
end
|
27
|
+
|
28
|
+
attr_accessor :id, :content_type
|
29
|
+
attr_accessor :name
|
30
|
+
attr_accessor :field_dne_d
|
31
|
+
|
32
|
+
def self.fields
|
33
|
+
[ :name_s, :field_dne_d ]
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.consumer_fields
|
37
|
+
[ :name ]
|
38
|
+
end
|
39
|
+
|
40
|
+
class ConnPool
|
41
|
+
def initialize(conn)
|
42
|
+
@conn = conn
|
43
|
+
end
|
44
|
+
|
45
|
+
def with(&block)
|
46
|
+
block.call(@conn)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class Conn
|
51
|
+
attr_accessor :result
|
52
|
+
|
53
|
+
def get(id)
|
54
|
+
@result
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe RRRMatey::StringModel::FindMethods do
|
60
|
+
context 'with or without cache_proxy setup' do
|
61
|
+
let(:model_klass) { FindModel }
|
62
|
+
|
63
|
+
describe '#get' do
|
64
|
+
it 'returns nil if cache_proxy is not set' do
|
65
|
+
expect(model_klass.get('di')).to be(nil)
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'returns nil if id is blank' do
|
69
|
+
expect(model_klass.get(nil)).to be(nil)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'with cache_proxy setup' do
|
75
|
+
let(:cache_proxy) { FindModel::Conn.new() }
|
76
|
+
let(:model_klass) {
|
77
|
+
m = FindModel
|
78
|
+
m.cache_proxy = FindModel::ConnPool.new(cache_proxy)
|
79
|
+
m
|
80
|
+
}
|
81
|
+
|
82
|
+
context 'with no value at key' do
|
83
|
+
let(:model) { model_klass.get('di') }
|
84
|
+
|
85
|
+
describe '#get' do
|
86
|
+
it 'returns object with id and content-type set' do
|
87
|
+
expect(model.id).to eq('di')
|
88
|
+
expect(model.content_type).to eq('application/json')
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'with json value at key' do
|
94
|
+
let(:result) { '{"find_model":{"id":"di","name":"eman","field_dne_d":2.718}}' }
|
95
|
+
let(:model) {
|
96
|
+
m = model_klass
|
97
|
+
cache_proxy.result = result
|
98
|
+
m.get('di')
|
99
|
+
}
|
100
|
+
|
101
|
+
describe '#get' do
|
102
|
+
it 'returns object with fields set' do
|
103
|
+
expect(model.id).to eq('di')
|
104
|
+
expect(model.content_type).to eq('application/json')
|
105
|
+
expect(model.name).to eq('eman')
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'with xml value at key' do
|
111
|
+
let(:result) { '<root><find_model><id>di</id><name>eman</name><field_dne_d>2.718</field_dne_d></find_model></root>' }
|
112
|
+
let(:model) {
|
113
|
+
m = model_klass
|
114
|
+
cache_proxy.result = result
|
115
|
+
m.get('di')
|
116
|
+
}
|
117
|
+
|
118
|
+
describe '#get' do
|
119
|
+
it 'returns object with fields set' do
|
120
|
+
expect(model.id).to eq('di')
|
121
|
+
expect(model.content_type).to eq('application/xml')
|
122
|
+
expect(model.name).to eq('eman')
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context 'with string value at key' do
|
128
|
+
let(:result) { <<EOF
|
129
|
+
id:di
|
130
|
+
name:eman
|
131
|
+
field_dne_d:2.718
|
132
|
+
EOF
|
133
|
+
}
|
134
|
+
let(:model_klass_s) {
|
135
|
+
m = model_klass
|
136
|
+
cache_proxy.result = result
|
137
|
+
m
|
138
|
+
}
|
139
|
+
|
140
|
+
describe '#get' do
|
141
|
+
it 'raises UnparseableContentError' do
|
142
|
+
expect{model_klass_s.get('di')}.to raise_error(RRRMatey::UnparseableContentError)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,231 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class IndexModel
|
4
|
+
extend RRRMatey::StringModel::IndexMethods
|
5
|
+
|
6
|
+
class ConnPool
|
7
|
+
def initialize(conn)
|
8
|
+
@conn = conn
|
9
|
+
end
|
10
|
+
|
11
|
+
def with(&block)
|
12
|
+
block.call(@conn)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Conn
|
17
|
+
@@search_index_name =
|
18
|
+
@@search_index_term =
|
19
|
+
@@search_start =
|
20
|
+
@@search_rows =
|
21
|
+
@@search_sort = nil
|
22
|
+
|
23
|
+
def search_index_name
|
24
|
+
@@search_index_name
|
25
|
+
end
|
26
|
+
|
27
|
+
def search_index_term
|
28
|
+
@@search_index_term
|
29
|
+
end
|
30
|
+
|
31
|
+
def search_start
|
32
|
+
@@search_start
|
33
|
+
end
|
34
|
+
|
35
|
+
def search_rows
|
36
|
+
@@search_rows
|
37
|
+
end
|
38
|
+
|
39
|
+
def search_sort
|
40
|
+
@@search_sort
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.mock_results(limit)
|
44
|
+
item_name_prefix = "#{IndexModel.item_name}."
|
45
|
+
{
|
46
|
+
'num_found' => 3,
|
47
|
+
'docs' => [
|
48
|
+
{
|
49
|
+
'_yz_rk' => 'di1',
|
50
|
+
"#{item_name_prefix}name" => 'eman1'
|
51
|
+
},
|
52
|
+
{
|
53
|
+
'_yz_rk' => 'di2',
|
54
|
+
"#{item_name_prefix}name" => 'eman2'
|
55
|
+
},
|
56
|
+
nil,
|
57
|
+
{
|
58
|
+
'_yz_rk' => 'di3',
|
59
|
+
"#{item_name_prefix}name" => 'eman3'
|
60
|
+
}
|
61
|
+
]
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
def search(index_name, index_term, opts = {})
|
66
|
+
@@search_index_name = index_name
|
67
|
+
@@search_index_term = index_term
|
68
|
+
@@search_start = opts[:start]
|
69
|
+
@@search_rows = opts[:rows]
|
70
|
+
@@search_sort = opts[:sort]
|
71
|
+
|
72
|
+
self.class.mock_results(@@search_rows)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.namespace()
|
77
|
+
'index_models'
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.item_name()
|
81
|
+
'index_model'
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.riak()
|
85
|
+
@riak
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.riak=(v)
|
89
|
+
@riak = v
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.object_from_hash(h, id, content_type)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe RRRMatey::StringModel::IndexMethods do
|
97
|
+
context 'with or without riak setup' do
|
98
|
+
context 'index_name set' do
|
99
|
+
let(:model_klass) {
|
100
|
+
IndexModel.index_name = 'something_else'
|
101
|
+
IndexModel
|
102
|
+
}
|
103
|
+
|
104
|
+
describe '#index_name' do
|
105
|
+
it 'yields values from self' do
|
106
|
+
expect(model_klass.index_name).to eq('something_else')
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'index_name not set' do
|
112
|
+
let(:model_klass) {
|
113
|
+
IndexModel.index_name = nil
|
114
|
+
IndexModel
|
115
|
+
}
|
116
|
+
let(:offset) { 4 }
|
117
|
+
let(:limit) { 20 }
|
118
|
+
let(:empty_discrete_result) {
|
119
|
+
RRRMatey::DiscreteResult.new(:length => 0,
|
120
|
+
:offset => offset,
|
121
|
+
:discrete_length => limit,
|
122
|
+
:results => [])
|
123
|
+
}
|
124
|
+
|
125
|
+
describe '#index_name' do
|
126
|
+
it 'yields values from StringModel' do
|
127
|
+
expect(model_klass.index_name).to eq('index_models')
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe '#list' do
|
132
|
+
let(:list_result) { model_klass.list(offset, limit) }
|
133
|
+
|
134
|
+
it 'yields an empty DiscreteResult' do
|
135
|
+
expect(list_result.length).to eq(empty_discrete_result.length)
|
136
|
+
expect(list_result.offset).to eq(empty_discrete_result.offset)
|
137
|
+
expect(list_result.discrete_length).to eq(empty_discrete_result.discrete_length)
|
138
|
+
expect(list_result.results).to eq(empty_discrete_result.results)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe '#list_by' do
|
143
|
+
let(:list_by_result) { model_klass.list_by(offset, limit, :name => 'ema*') }
|
144
|
+
|
145
|
+
it 'yields an empty DiscreteResult' do
|
146
|
+
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
context 'with riak setup' do
|
153
|
+
let(:riak) { IndexModel::Conn.new() }
|
154
|
+
let(:riak_pool) {
|
155
|
+
IndexModel::ConnPool.new(riak)
|
156
|
+
}
|
157
|
+
let(:model_klass) {
|
158
|
+
IndexModel.index_name = nil
|
159
|
+
IndexModel.riak = riak_pool
|
160
|
+
IndexModel
|
161
|
+
}
|
162
|
+
let(:offset) { 4 }
|
163
|
+
let(:limit) { 20 }
|
164
|
+
let(:results) { IndexModel::Conn.mock_results(limit) }
|
165
|
+
let(:result_docs) { results['docs'].select { |it| !it.nil? } }
|
166
|
+
let(:discrete_result) {
|
167
|
+
RRRMatey::DiscreteResult.new(:length => results.length,
|
168
|
+
:offset => offset,
|
169
|
+
:discrete_length => limit,
|
170
|
+
:results => results)
|
171
|
+
}
|
172
|
+
|
173
|
+
describe '#list' do
|
174
|
+
let(:list_result) { model_klass.list(offset, limit) }
|
175
|
+
|
176
|
+
it 'yields a hydrated DiscreteResult' do
|
177
|
+
expect(list_result.length).to eq(result_docs.length)
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'passes the index_name to riak search' do
|
181
|
+
expect(riak.search_index_name).to eq(model_klass.index_name)
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'passes the open index_term to riak search' do
|
185
|
+
expect(riak.search_index_term).to eq('*:*')
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'passes the offset to riak search' do
|
189
|
+
expect(riak.search_start).to eq(offset)
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'passes the limit to riak search' do
|
193
|
+
expect(riak.search_rows).to eq(limit)
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'passes riak key ascending sort to riak search' do
|
197
|
+
expect(riak.search_sort).to eq('_yz_rk asc')
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
describe '#list_by' do
|
202
|
+
let(:list_result) { model_klass.list_by(offset, limit, :name => 'ema*',
|
203
|
+
:birth => Date.today) }
|
204
|
+
let(:birth_date) { Date.today.to_s }
|
205
|
+
|
206
|
+
it 'yields a hydrated DiscreteResult' do
|
207
|
+
expect(list_result.length).to eq(result_docs.length)
|
208
|
+
end
|
209
|
+
|
210
|
+
it 'passes the index_name to riak search' do
|
211
|
+
expect(riak.search_index_name).to eq(model_klass.index_name)
|
212
|
+
end
|
213
|
+
|
214
|
+
it 'passes the specified index_term to riak search' do
|
215
|
+
expect(riak.search_index_term).to eq("index_model.name:ema* OR index_model.birth:#{birth_date}")
|
216
|
+
end
|
217
|
+
|
218
|
+
it 'passes the offset to riak search' do
|
219
|
+
expect(riak.search_start).to eq(offset)
|
220
|
+
end
|
221
|
+
|
222
|
+
it 'passes the limit to riak search' do
|
223
|
+
expect(riak.search_rows).to eq(limit)
|
224
|
+
end
|
225
|
+
|
226
|
+
it 'passes riak key ascending sort to riak search' do
|
227
|
+
expect(riak.search_sort).to eq('_yz_rk asc')
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|