pod4 0.8.0 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.hgtags +1 -0
- data/.ruby-version +1 -1
- data/Gemfile +5 -5
- data/lib/pod4/errors.rb +5 -0
- data/lib/pod4/nebulous_interface.rb +10 -11
- data/lib/pod4/pg_interface.rb +2 -2
- data/lib/pod4/tds_interface.rb +4 -2
- data/lib/pod4/typecasting.rb +1 -1
- data/lib/pod4/version.rb +1 -1
- data/pod4.gemspec +1 -21
- data/spec/common/basic_model_spec.rb +37 -45
- data/spec/common/model_plus_typecasting_spec.rb +16 -16
- data/spec/common/model_spec.rb +96 -103
- data/spec/common/nebulous_interface_spec.rb +78 -74
- data/spec/common/sequel_interface_pg_spec.rb +23 -19
- data/spec/common/sql_helper_spec.rb +24 -14
- data/spec/jruby/sequel_interface_jdbc_ms_spec.rb +24 -17
- data/spec/jruby/sequel_interface_jdbc_pg_spec.rb +30 -4
- data/spec/mri/pg_interface_spec.rb +50 -41
- data/spec/mri/sequel_interface_spec.rb +48 -53
- data/spec/mri/tds_interface_spec.rb +51 -42
- data/tags +186 -47
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5f29b0bd813bbf2094177505acbaea2c3f53fdaa
|
4
|
+
data.tar.gz: 869b71281afe127ed15230298bfad61e070e77d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b33eaf931088d4d31ad52d560d8a45b969eb402a3c9baf4d22ec8c8bed017cca67de1ee001c23c6625200ee8f6d0c86107ada232e027c4134a69c9c7e73527c7
|
7
|
+
data.tar.gz: dc7a67002ffcd2c3f7911d18e5bbb131c36c41c630ed7ee2c91c6d461d98caafaa2a500877914eec66d90475201a9420b44952ba355265c4990c5db42888b2e1
|
data/.hgtags
CHANGED
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.3.
|
1
|
+
2.3.2
|
data/Gemfile
CHANGED
@@ -6,15 +6,15 @@ gemspec
|
|
6
6
|
group :development, :test do
|
7
7
|
|
8
8
|
# for bundler, management, etc etc
|
9
|
-
gem "bundler", "~> 1.
|
10
|
-
gem "rake", "~>
|
11
|
-
gem "rspec", "~> 3.
|
9
|
+
gem "bundler", "~> 1.13"
|
10
|
+
gem "rake", "~> 12.0"
|
11
|
+
gem "rspec", "~> 3.5"
|
12
12
|
gem 'pry'
|
13
13
|
gem "pry-doc"
|
14
14
|
|
15
15
|
# For testing
|
16
|
-
gem "sequel", "~> 4.
|
17
|
-
gem "nebulous_stomp", "~>
|
16
|
+
gem "sequel", "~> 4.41"
|
17
|
+
gem "nebulous_stomp", "~> 3"
|
18
18
|
|
19
19
|
platforms :ruby do
|
20
20
|
gem "sqlite3", "~> 1.3"
|
data/lib/pod4/errors.rb
CHANGED
@@ -57,7 +57,7 @@ module Pod4
|
|
57
57
|
|
58
58
|
attr_reader :id_fld
|
59
59
|
|
60
|
-
# The
|
60
|
+
# The NebulousStomp Message object holding the response from the last message sent, or, nil.
|
61
61
|
attr_reader :response
|
62
62
|
|
63
63
|
# The status of the response from the last message:
|
@@ -153,10 +153,10 @@ module Pod4
|
|
153
153
|
##
|
154
154
|
# In normal operation, takes no parameters.
|
155
155
|
#
|
156
|
-
# For testing purposes you may pass
|
157
|
-
#
|
158
|
-
#
|
159
|
-
# called instead of creating a
|
156
|
+
# For testing purposes you may pass something here. Whatever it is you pass, it must respond to
|
157
|
+
# a `send` method, take the same parameters as NebulousStomp::Request.new (that is, a target
|
158
|
+
# and a message) and return something that behaves like a NebulousStomp::Request. This method
|
159
|
+
# will be called instead of creating a NebulousStomp::Request directly.
|
160
160
|
#
|
161
161
|
def initialize(requestObj=nil)
|
162
162
|
@request_object = requestObj # might as well be a reference
|
@@ -184,9 +184,7 @@ module Pod4
|
|
184
184
|
end
|
185
185
|
|
186
186
|
send_message( verb_for(:list), sel )
|
187
|
-
|
188
|
-
@response.body_to_h # should be an array irrespective of the method name
|
189
|
-
.map{|e| Octothorpe.new(e) }
|
187
|
+
@response.body.is_a?(Array) ? @response.body.map{|e| Octothorpe.new e} : []
|
190
188
|
|
191
189
|
rescue => e
|
192
190
|
handle_error(e)
|
@@ -219,7 +217,7 @@ module Pod4
|
|
219
217
|
|
220
218
|
send_message( verb_for(:read), param_string(:read, nil, id) )
|
221
219
|
|
222
|
-
Octothorpe.new( @response.
|
220
|
+
Octothorpe.new( @response.body.is_a?(Hash) ? @response.body : {} )
|
223
221
|
end
|
224
222
|
|
225
223
|
|
@@ -365,11 +363,12 @@ module Pod4
|
|
365
363
|
# returns the response to the request.
|
366
364
|
#
|
367
365
|
def send_message_helper(verb, paramStr, with_cache)
|
366
|
+
message = NebulousStomp::Message.new(verb: verb, params: paramStr)
|
368
367
|
request =
|
369
368
|
if @request_object
|
370
|
-
@request_object.send(
|
369
|
+
@request_object.send(self.class.target, message)
|
371
370
|
else
|
372
|
-
NebulousStomp::
|
371
|
+
NebulousStomp::Request.new(self.class.target, message)
|
373
372
|
end
|
374
373
|
|
375
374
|
if @clear_cache
|
data/lib/pod4/pg_interface.rb
CHANGED
@@ -139,9 +139,9 @@ module Pod4
|
|
139
139
|
|
140
140
|
rescue => e
|
141
141
|
# Select has already wrapped the error in a Pod4Error, but in this case we want to catch
|
142
|
-
# something
|
142
|
+
# something. Ruby 2.0 doesn't define Exception.cause, but in that case, we do on Pod4Error.
|
143
143
|
raise CantContinue, "That doesn't look like an ID" \
|
144
|
-
if e.cause.class == PG::InvalidTextRepresentation
|
144
|
+
if e.respond_to?(:cause) && e.cause.class == PG::InvalidTextRepresentation
|
145
145
|
|
146
146
|
handle_error(e)
|
147
147
|
end
|
data/lib/pod4/tds_interface.rb
CHANGED
@@ -171,9 +171,11 @@ module Pod4
|
|
171
171
|
|
172
172
|
rescue => e
|
173
173
|
# select already wrapped any error in a Pod4::DatabaseError, but in this case we want to try
|
174
|
-
# to catch something.
|
174
|
+
# to catch something. Ruby 2.0 doesn't define Exception.cause, but if it doesn't, we do in
|
175
|
+
# Pod4Error, so. (Side note: TinyTds' error class structure is a bit poor...)
|
175
176
|
raise CantContinue, "Problem reading record. Is '#{id}' really an ID?" \
|
176
|
-
if e.cause
|
177
|
+
if e.respond_to?(:cause) \
|
178
|
+
&& e.cause.class == TinyTds::Error \
|
177
179
|
&& e.cause.message =~ /conversion failed/i
|
178
180
|
|
179
181
|
|
data/lib/pod4/typecasting.rb
CHANGED
data/lib/pod4/version.rb
CHANGED
data/pod4.gemspec
CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.authors = ["Andy Jones"]
|
9
9
|
spec.email = ["andy.jones@twosticksconsulting.co.uk"]
|
10
10
|
spec.summary = %q|Totally not an ORM|
|
11
|
-
spec.description =
|
11
|
+
spec.description = <<-DESC.gsub(/^\s+/, "")
|
12
12
|
Provides a simple, common framework to talk to a bunch of data sources,
|
13
13
|
using model classes which consist of a bare minimum of DSL plus vanilla Ruby
|
14
14
|
inheritance.
|
@@ -27,24 +27,4 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.add_runtime_dependency "devnull", '~>0.1'
|
28
28
|
spec.add_runtime_dependency "octothorpe", '~>0.3'
|
29
29
|
|
30
|
-
=begin
|
31
|
-
# for bundler, management, etc etc
|
32
|
-
spec.add_development_dependency "bundler", "~> 1.11"
|
33
|
-
spec.add_development_dependency "rake", "~> 10.5"
|
34
|
-
spec.add_development_dependency "rspec", "~> 3.4"
|
35
|
-
spec.add_development_dependency "rdoc"
|
36
|
-
|
37
|
-
# For testing
|
38
|
-
spec.add_development_dependency "sequel", "~> 4.35"
|
39
|
-
spec.add_development_dependency "sqlite3", "~> 1.3"
|
40
|
-
spec.add_development_dependency "tiny_tds", "~> 0"
|
41
|
-
spec.add_development_dependency "pg", "~> 0"
|
42
|
-
spec.add_development_dependency "nebulous_stomp" , "~> 2"
|
43
|
-
|
44
|
-
# Development tools
|
45
|
-
spec.add_development_dependency "pry"
|
46
|
-
spec.add_development_dependency "pry-doc"
|
47
|
-
spec.add_development_dependency "ripper-tags"
|
48
|
-
=end
|
49
|
-
|
50
30
|
end
|
@@ -4,45 +4,37 @@ require 'pod4/basic_model'
|
|
4
4
|
require 'pod4/null_interface'
|
5
5
|
|
6
6
|
|
7
|
-
|
8
|
-
# We define a model class to test, since in normal operation we would never use
|
9
|
-
# Model directly, and since it needs an inner Interface.
|
10
|
-
#
|
11
|
-
# We can't use a mock for the interface -- class definitions fall outside the
|
12
|
-
# RSpec DSL as far as I can tell, so I can neither create a mock here or inject
|
13
|
-
# it. Which means we can't mock the interface in the rest of the test either;
|
14
|
-
# any mock we created would not get called.
|
15
|
-
#
|
16
|
-
# But: we want to test that Model calls Interface correctly.
|
17
|
-
#
|
18
|
-
# We do have what appears to be a perfectly sane way of testing. We can define
|
19
|
-
# an inner class based on the genuinely existing, non-mock NullInterface class;
|
20
|
-
# and then define expectations on it. When we do this, Rspec fails to pass the
|
21
|
-
# call on to the object, unless we specifically say `.and_call_original`
|
22
|
-
# instead of `.and_return`.
|
23
|
-
#
|
24
|
-
# This is actually quite nice, but more than a little confusing when you see it
|
25
|
-
# for the first time. Its use isn't spelled out in the RSpec docs AFAICS.
|
26
|
-
#
|
27
|
-
class WeirdModel < Pod4::BasicModel
|
28
|
-
set_interface NullInterface.new(:id, :name, :price, :groups, [])
|
29
|
-
|
30
|
-
def fake_an_alert(*args)
|
31
|
-
add_alert(*args) #protected method
|
32
|
-
end
|
33
|
-
|
34
|
-
def reset_alerts; @alerts = []; end
|
35
|
-
end
|
7
|
+
describe 'WeirdModel' do
|
36
8
|
|
9
|
+
##
|
10
|
+
# We define a model class to test, since in normal operation we would never use Model directly,
|
11
|
+
# and since it needs an inner Interface.
|
12
|
+
#
|
13
|
+
# We define an inner class based on the genuinely existing, non-mock NullInterface class; and
|
14
|
+
# then define expectations on it. When we do this, Rspec fails to pass the call on to the object,
|
15
|
+
# unless we specifically say `.and_call_original` instead of `.and_return`.
|
16
|
+
#
|
17
|
+
# This is actually quite nice, but more than a little confusing when you see it for the first
|
18
|
+
# time. Its use isn't spelled out in the RSpec docs AFAICS.
|
19
|
+
#
|
20
|
+
let(:weird_model_class) do
|
21
|
+
Class.new Pod4::BasicModel do
|
22
|
+
set_interface NullInterface.new(:id, :name, :price, :groups, [])
|
23
|
+
|
24
|
+
def fake_an_alert(*args)
|
25
|
+
add_alert(*args) #protected method
|
26
|
+
end
|
37
27
|
|
28
|
+
def reset_alerts; @alerts = []; end
|
29
|
+
end
|
30
|
+
end
|
38
31
|
|
39
|
-
|
40
|
-
let(:model) { WeirdModel.new(20) }
|
32
|
+
let(:model) { weird_model_class.new(20) }
|
41
33
|
|
42
34
|
|
43
35
|
describe 'Model.set_interface' do
|
44
36
|
it 'requires an Interface object' do
|
45
|
-
expect(
|
37
|
+
expect( weird_model_class ).to respond_to(:set_interface).with(1).argument
|
46
38
|
end
|
47
39
|
|
48
40
|
# it 'sets interface' - covered by the interface test
|
@@ -52,8 +44,8 @@ describe 'WeirdModel' do
|
|
52
44
|
|
53
45
|
describe 'Model.interface' do
|
54
46
|
it 'is the interface object' do
|
55
|
-
expect(
|
56
|
-
expect(
|
47
|
+
expect( weird_model_class.interface ).to be_a_kind_of NullInterface
|
48
|
+
expect( weird_model_class.interface.id_fld ).to eq :id
|
57
49
|
end
|
58
50
|
end
|
59
51
|
##
|
@@ -62,25 +54,25 @@ describe 'WeirdModel' do
|
|
62
54
|
describe '#new' do
|
63
55
|
|
64
56
|
it 'takes an optional ID' do
|
65
|
-
expect{
|
66
|
-
expect{
|
57
|
+
expect{ weird_model_class.new }.not_to raise_exception
|
58
|
+
expect{ weird_model_class.new(1) }.not_to raise_exception
|
67
59
|
end
|
68
60
|
|
69
61
|
it 'sets the ID attribute' do
|
70
|
-
expect(
|
62
|
+
expect( weird_model_class.new(23).model_id ).to eq 23
|
71
63
|
end
|
72
64
|
|
73
65
|
it 'sets the status to empty' do
|
74
|
-
expect(
|
66
|
+
expect( weird_model_class.new.model_status ).to eq :empty
|
75
67
|
end
|
76
68
|
|
77
69
|
it 'initializes the alerts attribute' do
|
78
|
-
expect(
|
70
|
+
expect( weird_model_class.new.alerts ).to eq([])
|
79
71
|
end
|
80
72
|
|
81
73
|
it 'doesn''t freak out if the ID is not an integer' do
|
82
|
-
expect{
|
83
|
-
expect(
|
74
|
+
expect{ weird_model_class.new("france") }.not_to raise_exception
|
75
|
+
expect( weird_model_class.new("france").model_id ).to eq "france"
|
84
76
|
end
|
85
77
|
|
86
78
|
end
|
@@ -89,8 +81,8 @@ describe 'WeirdModel' do
|
|
89
81
|
|
90
82
|
describe '#interface' do
|
91
83
|
it 'returns the interface set in the class definition, again' do
|
92
|
-
expect(
|
93
|
-
expect(
|
84
|
+
expect( weird_model_class.new.interface ).to be_a_kind_of NullInterface
|
85
|
+
expect( weird_model_class.new.interface.id_fld ).to eq :id
|
94
86
|
end
|
95
87
|
end
|
96
88
|
##
|
@@ -98,7 +90,7 @@ describe 'WeirdModel' do
|
|
98
90
|
|
99
91
|
describe '#alerts' do
|
100
92
|
it 'returns the list of alerts against the model' do
|
101
|
-
cm =
|
93
|
+
cm = weird_model_class.new
|
102
94
|
cm.fake_an_alert(:warning, :foo, 'one')
|
103
95
|
cm.fake_an_alert(:error, :bar, 'two')
|
104
96
|
|
@@ -195,7 +187,7 @@ describe 'WeirdModel' do
|
|
195
187
|
describe '#raise_exceptions' do
|
196
188
|
|
197
189
|
it 'is also known as .or_die' do
|
198
|
-
cm =
|
190
|
+
cm = weird_model_class.new
|
199
191
|
expect( cm.method(:raise_exceptions) ).to eq( cm.method(:or_die) )
|
200
192
|
end
|
201
193
|
|
@@ -5,17 +5,17 @@ require 'pod4/typecasting'
|
|
5
5
|
require 'pod4/null_interface'
|
6
6
|
|
7
7
|
|
8
|
-
class ProductModel < Pod4::Model
|
9
|
-
include Pod4::TypeCasting
|
10
|
-
force_encoding Encoding::ISO_8859_1 # I assume we are running as UTF8 here
|
11
|
-
attr_columns :id, :code, :product, :price
|
12
|
-
set_interface NullInterface.new(:id, :code, :product, :price, [])
|
13
|
-
end
|
14
|
-
|
15
|
-
|
16
|
-
|
17
8
|
describe 'ProductModel' do
|
18
9
|
|
10
|
+
let(:product_model_class) do
|
11
|
+
Class.new Pod4::Model do
|
12
|
+
include Pod4::TypeCasting
|
13
|
+
force_encoding Encoding::ISO_8859_1 # I assume we are running as UTF8 here
|
14
|
+
attr_columns :id, :code, :product, :price
|
15
|
+
set_interface NullInterface.new(:id, :code, :product, :price, [])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
19
|
let(:records) do
|
20
20
|
[ {id: 10, code: 'aa1', product: 'beans', price: 1.23},
|
21
21
|
{id: 20, code: 'bb1', product: 'pears', price: 2.34},
|
@@ -23,10 +23,10 @@ describe 'ProductModel' do
|
|
23
23
|
{id: 40, code: 'cc2', product: 'matches', price: 4.56} ]
|
24
24
|
end
|
25
25
|
|
26
|
-
let(:model) {
|
26
|
+
let(:model) { product_model_class.new(20) }
|
27
27
|
|
28
28
|
let(:model2) do
|
29
|
-
m =
|
29
|
+
m = product_model_class.new(30)
|
30
30
|
|
31
31
|
allow( m.interface ).to receive(:read).
|
32
32
|
and_return( Octothorpe.new(records[2]) )
|
@@ -43,20 +43,20 @@ describe 'ProductModel' do
|
|
43
43
|
describe 'Model.force_encoding' do
|
44
44
|
|
45
45
|
it 'requires an encoding' do
|
46
|
-
expect(
|
46
|
+
expect( product_model_class ).to respond_to(:force_encoding).with(1).argument
|
47
47
|
|
48
|
-
expect{
|
48
|
+
expect{ product_model_class.force_encoding('foo') }.to raise_exception Pod4Error
|
49
49
|
|
50
50
|
# Cheating here: this has to be the same as above or other tests will
|
51
51
|
# fail...
|
52
|
-
expect{
|
52
|
+
expect{ product_model_class.force_encoding(Encoding::ISO_8859_1) }.
|
53
53
|
not_to raise_exception
|
54
54
|
|
55
55
|
end
|
56
56
|
|
57
57
|
it 'sets the encoding to be returned by Model.encoding' do
|
58
|
-
expect{
|
59
|
-
expect(
|
58
|
+
expect{ product_model_class.encoding }.not_to raise_exception
|
59
|
+
expect( product_model_class.encoding ).to eq(Encoding::ISO_8859_1)
|
60
60
|
end
|
61
61
|
|
62
62
|
end
|