pod4 0.10.6 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +5 -5
  2. data/.bugs/bugs +2 -1
  3. data/.bugs/details/b5368c7ef19065fc597b5692314da71772660963.txt +53 -0
  4. data/.hgtags +1 -0
  5. data/Gemfile +5 -5
  6. data/README.md +157 -46
  7. data/lib/pod4/basic_model.rb +9 -22
  8. data/lib/pod4/connection.rb +67 -0
  9. data/lib/pod4/connection_pool.rb +154 -0
  10. data/lib/pod4/errors.rb +20 -0
  11. data/lib/pod4/interface.rb +34 -12
  12. data/lib/pod4/model.rb +32 -27
  13. data/lib/pod4/nebulous_interface.rb +25 -30
  14. data/lib/pod4/null_interface.rb +22 -16
  15. data/lib/pod4/pg_interface.rb +84 -104
  16. data/lib/pod4/sequel_interface.rb +138 -82
  17. data/lib/pod4/tds_interface.rb +83 -70
  18. data/lib/pod4/tweaking.rb +105 -0
  19. data/lib/pod4/version.rb +1 -1
  20. data/md/breaking_changes.md +80 -0
  21. data/spec/common/basic_model_spec.rb +67 -70
  22. data/spec/common/connection_pool_parallelism_spec.rb +154 -0
  23. data/spec/common/connection_pool_spec.rb +246 -0
  24. data/spec/common/connection_spec.rb +129 -0
  25. data/spec/common/model_ai_missing_id_spec.rb +256 -0
  26. data/spec/common/model_plus_encrypting_spec.rb +16 -4
  27. data/spec/common/model_plus_tweaking_spec.rb +128 -0
  28. data/spec/common/model_plus_typecasting_spec.rb +10 -4
  29. data/spec/common/model_spec.rb +283 -363
  30. data/spec/common/nebulous_interface_spec.rb +159 -108
  31. data/spec/common/null_interface_spec.rb +88 -65
  32. data/spec/common/sequel_interface_pg_spec.rb +217 -161
  33. data/spec/common/shared_examples_for_interface.rb +50 -50
  34. data/spec/jruby/sequel_encrypting_jdbc_pg_spec.rb +1 -1
  35. data/spec/jruby/sequel_interface_jdbc_ms_spec.rb +3 -3
  36. data/spec/jruby/sequel_interface_jdbc_pg_spec.rb +3 -23
  37. data/spec/mri/pg_encrypting_spec.rb +1 -1
  38. data/spec/mri/pg_interface_spec.rb +311 -223
  39. data/spec/mri/sequel_encrypting_spec.rb +1 -1
  40. data/spec/mri/sequel_interface_spec.rb +177 -180
  41. data/spec/mri/tds_encrypting_spec.rb +1 -1
  42. data/spec/mri/tds_interface_spec.rb +296 -212
  43. data/tags +340 -174
  44. metadata +19 -11
  45. data/md/fixme.md +0 -3
  46. data/md/roadmap.md +0 -125
  47. data/md/typecasting.md +0 -80
  48. data/spec/common/model_new_validate_spec.rb +0 -204
@@ -1,152 +1,175 @@
1
- require 'pod4/null_interface'
1
+ require "pod4/null_interface"
2
2
 
3
- require_relative 'shared_examples_for_interface'
3
+ require_relative "shared_examples_for_interface"
4
4
 
5
5
 
6
6
  describe NullInterface do
7
7
 
8
+ def list_contains(id)
9
+ interface.list.find {|x| x[interface.id_fld] == id }
10
+ end
11
+
12
+ # An autoincrementing interface
8
13
  let(:data) do
9
- [ {name: 'Barney', price: 1.11},
10
- {name: 'Fred', price: 2.22},
11
- {name: 'Betty', price: 3.33} ]
14
+ [ {id: 1, name: "Barney", price: 1.11},
15
+ {id: 2, name: "Fred", price: 2.22},
16
+ {id: 3, name: "Betty", price: 3.33} ]
12
17
  end
18
+ let (:interface) { NullInterface.new(:id, :name, :price, data) }
13
19
 
14
- let (:interface) { NullInterface.new(:name, :price, data) }
20
+ # A non-autoincrementing interface
21
+ let(:data2) do
22
+ [ {code: "foo", level: 1},
23
+ {code: "bar", level: 2},
24
+ {code: "baz", level: 3} ]
25
+ end
15
26
 
16
- ##
27
+ let (:interface2) do
28
+ i = NullInterface.new(:code, :level, data2)
29
+ i.id_ai = false
30
+ i
31
+ end
17
32
 
18
33
 
19
34
  it_behaves_like "an interface" do
20
- let(:record) { {name: 'barney', price:1.11} }
21
- let(:interface) { NullInterface.new( :name, :price, [record] ) }
35
+ let(:record) { {name: "barney", price:1.11} }
36
+ let(:interface) { NullInterface.new( :id, :name, :price, [record]) }
22
37
  end
23
38
 
24
39
 
25
- describe '#new' do
40
+ describe "#new" do
26
41
 
27
- it 'requires a list of columns and an array of hashes' do
42
+ it "requires a list of columns and an array of hashes" do
28
43
  expect{ NullInterface.new }.to raise_exception ArgumentError
29
44
  expect{ NullInterface.new(nil) }.to raise_exception ArgumentError
30
- expect{ NullInterface.new('foo') }.to raise_exception ArgumentError
45
+ expect{ NullInterface.new("foo") }.to raise_exception ArgumentError
31
46
 
32
47
  expect{ NullInterface.new(:one, [{one:1}]) }.not_to raise_exception
33
48
  end
34
49
 
35
- end
36
- ##
50
+ it "defaults autoincrement to true" do
51
+ expect( interface.id_ai ).to eq true
52
+ end
37
53
 
54
+ it "allows you to set autoincrement to false" do
55
+ ni = NullInterface.new(:one, [{one:1}])
56
+ ni.id_ai = false
57
+ expect( ni.id_ai ).to eq false
58
+ end
38
59
 
39
- describe '#create' do
60
+ end # of #new
40
61
 
41
- let(:hash) { {name: 'Bam-Bam', price: 4.44} }
42
- let(:ot) { Octothorpe.new(name: 'Wilma', price: 5.55) }
43
62
 
44
- it 'creates the record when given a hash' do
63
+ describe "#create" do
64
+
65
+ let(:hash) { {name: "Bam-Bam", price: 4.44} }
66
+ let(:ot) { Octothorpe.new(name: "Wilma", price: 5.55) }
67
+
68
+ it "creates the record when given a hash" do
45
69
  id = interface.create(hash)
46
70
 
47
71
  expect{ interface.read(id) }.not_to raise_exception
48
72
  expect( interface.read(id).to_h ).to include hash
49
73
  end
50
74
 
51
- it 'creates the record when given an Octothorpe' do
75
+ it "creates the record when given an Octothorpe" do
52
76
  id = interface.create(ot)
53
77
 
54
78
  expect{ interface.read(id) }.not_to raise_exception
55
79
  expect( interface.read(id).to_h ).to include ot.to_h
56
80
  end
57
81
 
58
- end
59
- ##
82
+ it "raises an ArgumentError when the key is not AI and the record is missing the key" do
83
+ expect{ interface2.create(level: 55) }.to raise_error ArgumentError
84
+ end
60
85
 
86
+ it "sets the ID field to the correct integer when autoincrement is true" do
87
+ count = interface.list.size
88
+ id = interface.create(ot)
89
+ expect( id ).to eq(count + 1)
90
+ end
91
+
92
+ it "sets the ID field to whatever you set in the record when autoincrement is false" do
93
+ id = interface2.create Octothorpe.new(code: "flong", level: 9)
94
+ expect( id ).to eq "flong"
95
+ end
96
+
97
+ end # of #create
61
98
 
62
- describe '#read' do
63
99
 
64
- it 'returns the record for the id as an Octothorpe' do
65
- expect( interface.read('Barney') ).to be_a_kind_of Octothorpe
66
- expect( interface.read('Fred').to_h ).
67
- to include(name: 'Fred', price: 2.22)
100
+ describe "#read" do
68
101
 
102
+ it "returns the record for the id as an Octothorpe" do
103
+ expect( interface.read(1) ).to be_a_kind_of Octothorpe
104
+ expect( interface.read(2).to_h ).to include(name: "Fred", price: 2.22)
69
105
  end
70
106
 
71
- it 'returns an empty Octothorpe if no record matches the ID' do
107
+ it "returns an empty Octothorpe if no record matches the ID" do
72
108
  expect{ interface.read(:foo) }.not_to raise_exception
73
109
  expect( interface.read(:foo) ).to be_a_kind_of Octothorpe
74
110
  expect( interface.read(:foo) ).to be_empty
75
111
  end
76
112
 
77
- end
78
- ##
113
+ end # of #read
79
114
 
80
115
 
81
- describe '#list' do
116
+ describe "#list" do
82
117
 
83
- it 'has an optional selection parameter, a hash' do
118
+ it "has an optional selection parameter, a hash" do
84
119
  expect{ interface.list }.not_to raise_exception
85
- expect{ interface.list(name: 'Barney') }.not_to raise_exception
120
+ expect{ interface.list(name: "Barney") }.not_to raise_exception
86
121
  end
87
122
 
88
- it 'returns an array of Octothorpes that match the records' do
123
+ it "returns an array of Octothorpes that match the records" do
89
124
  arr = interface.list.map(&:to_h)
90
125
  expect( arr ).to match_array data
91
126
  end
92
127
 
93
- it 'returns a subset of records based on the selection parameter' do
94
- expect( interface.list(name: 'Fred').size ).to eq 1
128
+ it "returns a subset of records based on the selection parameter" do
129
+ expect( interface.list(name: "Fred").size ).to eq 1
95
130
 
96
- expect( interface.list(name: 'Betty').first.to_h ).
97
- to include(name: 'Betty', price: 3.33)
131
+ expect( interface.list(name: "Betty").first.to_h ).
132
+ to include(name: "Betty", price: 3.33)
98
133
 
99
134
  end
100
135
 
101
- it 'returns an empty Array if nothing matches' do
102
- expect( interface.list(name: 'Yogi') ).to eq([])
136
+ it "returns an empty Array if nothing matches" do
137
+ expect( interface.list(name: "Yogi") ).to eq([])
103
138
  end
104
139
 
105
- it 'returns an empty array if there is no data' do
140
+ it "returns an empty array if there is no data" do
106
141
  interface.list.each {|x| interface.delete(x[interface.id_fld]) }
107
142
  expect( interface.list ).to eq([])
108
143
  end
109
144
 
110
- end
111
- ##
145
+ end # of #list
112
146
 
113
147
 
114
- describe '#update' do
115
-
116
- let(:id) { interface.list.first[:name] }
148
+ describe "#update" do
117
149
 
118
- it 'updates the record at ID with record parameter' do
150
+ it "updates the record at ID with record parameter" do
119
151
  record = {price: 99.99}
120
- interface.update(id, record)
152
+ interface.update(1, record)
121
153
 
122
- expect( interface.read(id).to_h ).to include(record)
154
+ expect( interface.read(1).to_h ).to include(record)
123
155
  end
124
156
 
125
- end
126
- ##
127
-
128
-
129
- describe '#delete' do
130
-
131
- def list_contains(id)
132
- interface.list.find {|x| x[interface.id_fld] == id }
133
- end
157
+ end # of #update
134
158
 
135
- let(:id) { interface.list.first[:name] }
136
159
 
137
- it 'raises CantContinue if anything hinky happens with the ID' do
160
+ describe "#delete" do
161
+ it "raises CantContinue if anything hinky happens with the ID" do
138
162
  expect{ interface.delete(:foo) }.to raise_exception CantContinue
139
163
  expect{ interface.delete(99) }.to raise_exception CantContinue
140
164
  end
141
165
 
142
- it 'makes the record at ID go away' do
143
- expect( list_contains(id) ).to be_truthy
144
- interface.delete(id)
145
- expect( list_contains(id) ).to be_falsy
166
+ it "makes the record at ID go away" do
167
+ expect( list_contains(1) ).to be_truthy
168
+ interface.delete(1)
169
+ expect( list_contains(1) ).to be_falsy
146
170
  end
147
171
 
148
- end
149
- ##
172
+ end # of #delete
150
173
 
151
174
 
152
175
  end
@@ -2,16 +2,48 @@
2
2
  # Supplemental test for Sequel -- tests using PG gem in MRI, jeremyevans-postgres-pg under jruby?
3
3
  #
4
4
 
5
- require 'pod4/sequel_interface'
5
+ require "pod4/sequel_interface"
6
6
 
7
- require 'sequel'
8
- require 'date'
9
- require 'time'
10
- require 'bigdecimal'
7
+ require "sequel"
8
+ require "date"
9
+ require "time"
10
+ require "bigdecimal"
11
11
 
12
12
 
13
13
  describe "SequelInterface (Pg)" do
14
14
 
15
+ def fill_data(ifce, data)
16
+ data.each{|r| ifce.create(r) }
17
+ end
18
+
19
+ def fill_product_data(ifce)
20
+ ifce.create( {code: "foo", name: "bar"} )
21
+ end
22
+
23
+ def list_contains(ifce, id)
24
+ ifce.list.find {|x| x[ifce.id_fld] == id }
25
+ end
26
+
27
+ def db_setup(db)
28
+ db.run %Q|
29
+ drop table if exists customer;
30
+ drop table if exists product;
31
+
32
+ create table customer (
33
+ id serial primary key,
34
+ name text,
35
+ level real null,
36
+ day date null,
37
+ timestamp timestamp null,
38
+ price money null,
39
+ qty numeric null );
40
+
41
+ create table product (
42
+ code text,
43
+ name text );|
44
+
45
+ end
46
+
15
47
  let(:sequel_interface_class) do
16
48
  Class.new SequelInterface do
17
49
  set_table :customer
@@ -30,115 +62,139 @@ describe "SequelInterface (Pg)" do
30
62
  let(:prod_interface_class) do
31
63
  Class.new SequelInterface do
32
64
  set_table :product
33
- set_id_fld :code
65
+ set_id_fld :code, autoincrement: false
34
66
  end
35
67
  end
36
68
 
37
-
38
69
  let(:data) do
39
70
  d = []
40
- d << { name: 'Barney',
71
+ d << { name: "Barney",
41
72
  level: 1.23,
42
73
  day: Date.parse("2016-01-01"),
43
- timestamp: Time.parse('2015-01-01 12:11'),
74
+ timestamp: Time.parse("2015-01-01 12:11"),
44
75
  qty: BigDecimal("1.24"),
45
76
  price: BigDecimal("1.24") }
46
77
 
47
- d << { name: 'Fred',
78
+ d << { name: "Fred",
48
79
  level: 2.34,
49
80
  day: Date.parse("2016-02-02"),
50
- timestamp: Time.parse('2015-01-02 12:22'),
81
+ timestamp: Time.parse("2015-01-02 12:22"),
51
82
  qty: BigDecimal("2.35"),
52
83
  price: BigDecimal("2.35") }
53
84
 
54
- d << { name: 'Betty',
85
+ d << { name: "Betty",
55
86
  level: 3.45,
56
87
  day: Date.parse("2016-03-03"),
57
- timestamp: Time.parse('2015-01-03 12:33'),
88
+ timestamp: Time.parse("2015-01-03 12:33"),
58
89
  qty: BigDecimal("3.46"),
59
90
  price: BigDecimal("3.46") }
60
91
 
61
92
  d
62
93
  end
63
94
 
64
- def fill_data(ifce)
65
- data.each{|r| ifce.create(r) }
66
- end
67
-
68
- def fill_product_data(ifce)
69
- ifce.create( {code: "foo", name: "bar"} )
70
- end
71
-
72
-
73
- let (:db) do
74
- db = Sequel.connect('postgres://pod4test:pod4test@centos7andy/pod4_test?search_path=public')
75
-
76
- db.run %Q|
77
- drop table if exists customer;
78
- drop table if exists product;
79
-
80
- create table customer (
81
- id serial primary key,
82
- name text,
83
- level real null,
84
- day date null,
85
- timestamp timestamp null,
86
- price money null,
87
- qty numeric null );
88
-
89
- create table product (
90
- code text,
91
- name text );|
95
+ let(:db_url) { "postgres://pod4test:pod4test@centos7andy/pod4_test?search_path=public" }
92
96
 
97
+ let(:db) do
98
+ db = Sequel.connect(db_url)
99
+ db_setup(db)
93
100
  db
94
101
  end
95
102
 
96
103
  let(:interface) { sequel_interface_class.new(db) }
97
104
  let(:prod_interface) { prod_interface_class.new(db) }
98
105
 
99
-
100
-
101
106
  before do
102
107
  interface.execute %Q|
103
108
  truncate table customer restart identity;
104
109
  truncate table product;|
105
110
 
106
- fill_data(interface)
111
+ fill_data(interface, data)
107
112
  end
108
113
 
109
114
  after do
110
115
  db.disconnect
111
116
  end
112
117
 
113
- ##
114
118
 
119
+ describe "#new" do
120
+
121
+ context "when passed a Sequel DB object" do
122
+ let(:ifce) { sequel_interface_class.new(Sequel.connect db_url) }
123
+
124
+ it "uses it to create a connection" do
125
+ expect( ifce._connection ).to be_a Connection
126
+ expect( ifce._connection.interface_class ).to eq sequel_interface_class
127
+ end
128
+
129
+ it "calls Connection#client on first use" do
130
+ expect( ifce._connection ).to receive(:client).with(ifce).and_call_original
131
+ ifce.list
132
+ end
133
+ end
134
+
135
+ context "when passed a String" do
136
+ let(:ifce) { sequel_interface_class.new(db_url) }
137
+
138
+ it "uses it to create a connection" do
139
+ expect( ifce._connection ).to be_a Connection
140
+ expect( ifce._connection.interface_class ).to eq sequel_interface_class
141
+ end
142
+
143
+ # Normally we'd expect on _every_ use, but Sequel is different
144
+ it "calls Connection#client on first use" do
145
+ expect( ifce._connection ).to receive(:client).with(ifce).and_call_original
146
+ ifce.list
147
+ end
148
+ end
149
+
150
+ context "when passed a Connection object" do
151
+ let(:conn) { Connection.new(interface: sequel_interface_class) }
152
+ let(:ifce) { sequel_interface_class.new(conn) }
153
+
154
+ it "uses that as its connection object" do
155
+ expect( ifce._connection ).to be_a Connection
156
+ expect( ifce._connection ).to eq conn
157
+ expect( ifce._connection.interface_class ).to eq sequel_interface_class
158
+ end
159
+
160
+ # Normally we'd expect on _every_ use, but Sequel is different
161
+ it "calls Connection#client on first use" do
162
+ # When we pass a connection object we are expected to set the data layer option
163
+ conn.data_layer_options = Sequel.connect(db_url)
115
164
 
116
- describe '#quoted_table' do
165
+ expect( ifce._connection ).to receive(:client).with(ifce).and_call_original
117
166
 
118
- it 'returns just the table when the schema is not set' do
167
+ ifce.list
168
+ end
169
+ end
170
+
171
+ end # of #new
172
+
173
+ describe "#quoted_table" do
174
+
175
+ it "returns just the table when the schema is not set" do
119
176
  expect( interface.quoted_table.downcase ).to eq( %Q|"customer"| )
120
177
  end
121
178
 
122
- it 'returns the schema plus table when the schema is set' do
179
+ it "returns the schema plus table when the schema is set" do
123
180
  ifce = schema_interface_class.new(db)
124
181
  expect( ifce.quoted_table.downcase ).to eq( %|"public"."customer"| )
125
182
  end
126
183
 
127
- end
128
- ##
184
+ end # of #quoted_table
129
185
 
130
186
 
131
- describe '#create' do
187
+ describe "#create" do
132
188
 
133
- let(:hash) { {name: 'Bam-Bam', qty: 4.44} }
134
- let(:ot) { Octothorpe.new(name: 'Wilma', qty: 5.55) }
189
+ let(:hash) { {name: "Bam-Bam", qty: 4.44} }
190
+ let(:ot) { Octothorpe.new(name: "Wilma", qty: 5.55) }
135
191
 
136
192
 
137
- it 'raises a Pod4::DatabaseError if anything goes wrong' do
138
- expect{ interface.create(one: 'two') }.to raise_exception DatabaseError
193
+ it "raises a Pod4::DatabaseError if anything goes wrong" do
194
+ expect{ interface.create(one: "two") }.to raise_exception DatabaseError
139
195
  end
140
196
 
141
- it 'creates the record when given a hash' do
197
+ it "creates the record when given a hash" do
142
198
  # kinda impossible to seperate these two tests
143
199
  id = interface.create(hash)
144
200
 
@@ -147,26 +203,26 @@ describe "SequelInterface (Pg)" do
147
203
  expect( interface.read(id).to_h ).to include hash
148
204
  end
149
205
 
150
- it 'creates the record when given an Octothorpe' do
206
+ it "creates the record when given an Octothorpe" do
151
207
  id = interface.create(ot)
152
208
 
153
209
  expect{ interface.read(id) }.not_to raise_exception
154
210
  expect( interface.read(id).to_h ).to include ot.to_h
155
211
  end
156
212
 
157
- it 'does not freak out if the hash has symbol values' do
213
+ it "does not freak out if the hash has symbol values" do
158
214
  # Which, Sequel does
159
215
  expect{ interface.create(name: :Booboo) }.not_to raise_exception
160
216
  end
161
217
 
162
- it 'shouldnt have a problem with record values of nil' do
163
- record = {name: 'Ranger', price: nil}
218
+ it "has no problem with record values of nil" do
219
+ record = {name: "Ranger", price: nil}
164
220
  expect{ interface.create(record) }.not_to raise_exception
165
221
  id = interface.create(record)
166
222
  expect( interface.read(id).to_h ).to include(record)
167
223
  end
168
224
 
169
- it 'shouldnt have a problem with strings containing special characters' do
225
+ it "has no problem with strings containing special characters" do
170
226
  # Note that in passing we retest that create returns the ID for identity columns
171
227
 
172
228
  record = {name: "T'Challa[]", price: nil}
@@ -175,7 +231,7 @@ describe "SequelInterface (Pg)" do
175
231
  expect( interface.read(id).to_h ).to include(record)
176
232
  end
177
233
 
178
- it 'shouldn\'t have a problem with non-integer keys' do
234
+ it "has no problem with non-integer keys" do
179
235
  # Note that in passing we retest that create returns the ID for non-identity columns
180
236
 
181
237
  hash = {code: "foo", name: "bar"}
@@ -186,55 +242,64 @@ describe "SequelInterface (Pg)" do
186
242
  expect( prod_interface.read("foo").to_h ).to include hash
187
243
  end
188
244
 
189
- end
190
- ##
245
+ it "copes with an OT with the ID field in it when the ID field autoincrements" do
246
+ h = {id: nil, name: "Bam-Bam", qty: 4.44}
247
+ expect{ interface.create(h) }.not_to raise_error
191
248
 
249
+ id = interface.create(h)
250
+ expect( id ).not_to be_nil
251
+ expect{ interface.read(id) }.not_to raise_exception
252
+ expect( interface.read(id).to_h ).to include( {name: "Bam-Bam", qty: 4.44} )
253
+ end
192
254
 
193
- describe '#read' do
255
+ end # of #create
194
256
 
195
- it 'returns the record for the id as an Octothorpe' do
196
- expect( interface.read(2).to_h ).to include(name: 'Fred', qty: 2.35)
257
+
258
+ describe "#read" do
259
+
260
+ it "returns the record for the id as an Octothorpe" do
261
+ expect( interface.read(2).to_h ).to include(name: "Fred", qty: 2.35)
197
262
  end
198
263
 
199
- it 'raises a Pod4::CantContinue if the ID is bad' do
264
+ it "raises a Pod4::CantContinue if the ID is bad" do
200
265
  expect{ interface.read(:foo) }.to raise_exception CantContinue
201
266
  end
202
267
 
203
- it 'returns an empty Octothorpe if no record matches the ID' do
268
+ it "returns an empty Octothorpe if no record matches the ID" do
204
269
  expect{ interface.read(99) }.not_to raise_exception
205
270
  expect( interface.read(99) ).to be_a_kind_of Octothorpe
206
271
  expect( interface.read(99) ).to be_empty
207
272
  end
208
273
 
209
- it 'returns real fields as Float' do
274
+ it "returns real fields as Float" do
210
275
  level = interface.read(1).>>.level
211
276
 
212
277
  expect( level ).to be_a_kind_of Float
213
278
  expect( level ).to be_within(0.001).of( data.first[:level] )
214
279
  end
215
280
 
216
- it 'returns date fields as Date' do
281
+ it "returns date fields as Date" do
217
282
  date = interface.read(1).>>.day
218
283
 
219
284
  expect( date ).to be_a_kind_of Date
220
285
  expect( date ).to eq data.first[:day]
221
286
  end
222
287
 
223
- it 'returns datetime fields as Time' do
288
+ it "returns datetime fields as Time" do
224
289
  timestamp = interface.read(1).>>.timestamp
225
290
 
226
291
  expect( timestamp ).to be_a_kind_of Time
227
292
  expect( timestamp ).to eq data.first[:timestamp]
228
293
  end
229
294
 
230
- it 'returns numeric fields as BigDecimal' do
295
+ it "returns numeric fields as BigDecimal" do
231
296
  qty = interface.read(1).>>.qty
232
297
 
233
298
  expect( qty ).to be_a_kind_of BigDecimal
234
299
  expect( qty ).to eq data.first[:qty]
235
300
  end
236
301
 
237
- it 'returns money fields as bigdecimal' do
302
+ it "returns money fields as bigdecimal" do
238
303
  pending "Sequel/PG returns a string for Money type"
239
304
 
240
305
  price = interface.read(1).>>.price
@@ -243,7 +308,7 @@ describe "SequelInterface (Pg)" do
243
308
  expect( price ).to eq data.first[:price]
244
309
  end
245
310
 
246
- it 'shouldn\'t have a problem with non-integer keys' do
311
+ it "has no problem with non-integer keys" do
247
312
  # this is a 100% overlap with the create test above...
248
313
  fill_product_data(prod_interface)
249
314
 
@@ -251,14 +316,12 @@ describe "SequelInterface (Pg)" do
251
316
  expect( prod_interface.read("foo").to_h ).to include(code: "foo", name: "bar")
252
317
  end
253
318
 
254
- end
255
- ##
256
-
257
-
319
+ end # of #read
320
+
258
321
 
259
- describe '#list' do
322
+ describe "#list" do
260
323
 
261
- it 'returns an array of Octothorpes that match the records' do
324
+ it "returns an array of Octothorpes that match the records" do
262
325
  arr = interface.list.map {|ot| x = ot.to_h}
263
326
 
264
327
  expect( arr.size ).to eq(data.size)
@@ -274,43 +337,40 @@ describe "SequelInterface (Pg)" do
274
337
 
275
338
  end
276
339
 
277
- it 'returns a subset of records based on the selection parameter' do
278
- expect( interface.list(name: 'Fred').size ).to eq 1
340
+ it "returns a subset of records based on the selection parameter" do
341
+ expect( interface.list(name: "Fred").size ).to eq 1
279
342
 
280
- expect( interface.list(name: 'Betty').first.to_h ).
281
- to include(name: 'Betty', qty: 3.46)
343
+ expect( interface.list(name: "Betty").first.to_h ).
344
+ to include(name: "Betty", qty: 3.46)
282
345
 
283
346
  end
284
347
 
285
- it 'returns an empty Array if nothing matches' do
286
- expect( interface.list(name: 'Yogi') ).to eq([])
348
+ it "returns an empty Array if nothing matches" do
349
+ expect( interface.list(name: "Yogi") ).to eq([])
287
350
  end
288
351
 
289
- it 'raises DatabaseError if the selection criteria is nonsensical' do
290
- expect{ interface.list('foo') }.to raise_exception Pod4::DatabaseError
352
+ it "raises DatabaseError if the selection criteria is nonsensical" do
353
+ expect{ interface.list("foo") }.to raise_exception Pod4::DatabaseError
291
354
  end
292
355
 
293
- it 'returns an empty array if there is no data' do
356
+ it "returns an empty array if there is no data" do
294
357
  interface.list.each {|x| interface.delete(x[interface.id_fld]) }
295
358
  expect( interface.list ).to eq([])
296
359
  end
297
360
 
298
- it 'does not freak out if the hash has symbol values' do
361
+ it "doesn't freak out if the hash has symbol values" do
299
362
  # Which, Sequel does
300
363
  expect{ interface.list(name: :Barney) }.not_to raise_exception
301
364
  end
302
365
 
303
-
304
- end
305
- ##
366
+ end # of #list
306
367
 
307
368
 
308
- describe '#update' do
309
-
369
+ describe "#update" do
310
370
  let(:id) { interface.list.first[:id] }
311
371
 
312
- it 'updates the record at ID with record parameter' do
313
- record = {name: 'Booboo', qty: 99.99}
372
+ it "updates the record at ID with record parameter" do
373
+ record = {name: "Booboo", qty: 99.99}
314
374
  interface.update(id, record)
315
375
 
316
376
  booboo = interface.read(id)
@@ -318,203 +378,199 @@ describe "SequelInterface (Pg)" do
318
378
  expect( booboo.>>.qty.to_f ).to eq( record[:qty] )
319
379
  end
320
380
 
321
- it 'raises a CantContinue if anything weird happens with the ID' do
322
- expect{ interface.update(99, name: 'Booboo') }.
381
+ it "raises a CantContinue if anything weird happens with the ID" do
382
+ expect{ interface.update(99, name: "Booboo") }.
323
383
  to raise_exception CantContinue
324
384
 
325
385
  end
326
386
 
327
- it 'raises a DatabaseError if anything weird happensi with the record' do
328
- expect{ interface.update(id, smarts: 'more') }.
387
+ it "raises a DatabaseError if anything weird happensi with the record" do
388
+ expect{ interface.update(id, smarts: "more") }.
329
389
  to raise_exception DatabaseError
330
390
 
331
391
  end
332
392
 
333
- it 'does not freak out if the hash has symbol values' do
393
+ it "doesn't freak out if the hash has symbol values" do
334
394
  # Which, Sequel does
335
395
  expect{ interface.update(id, name: :Booboo) }.not_to raise_exception
336
396
  end
337
397
 
338
- it 'shouldn\'t have a problem with record values of nil' do
339
- record = {name: 'Ranger', qty: nil}
398
+ it "has no problem with record values of nil" do
399
+ record = {name: "Ranger", qty: nil}
340
400
  expect{ interface.update(id, record) }.not_to raise_exception
341
401
  expect( interface.read(id).to_h ).to include(record)
342
402
  end
343
403
 
344
- it 'shouldn\'t have a problem with strings containing special characters' do
404
+ it "has no problem with strings containing special characters" do
345
405
  record = {name: "T'Challa[]", qty: nil}
346
406
  expect{ interface.update(id, record) }.not_to raise_exception
347
407
  expect( interface.read(id).to_h ).to include(record)
348
408
  end
349
409
 
350
- it 'shouldn\'t have a problem with non-integer keys' do
410
+ it "has no problem with non-integer keys" do
351
411
  fill_product_data(prod_interface)
352
412
  expect{ prod_interface.update("foo", name: "baz") }.not_to raise_error
353
413
  expect( prod_interface.read("foo").to_h[:name] ).to eq "baz"
354
414
  end
355
415
 
356
- end
357
- ##
358
-
359
-
360
- describe '#delete' do
416
+ end # of #update
361
417
 
362
- def list_contains(ifce, id)
363
- ifce.list.find {|x| x[ifce.id_fld] == id }
364
- end
365
418
 
419
+ describe "#delete" do
366
420
  let(:id) { interface.list.first[:id] }
367
421
 
368
- it 'raises CantContinue if anything hinky happens with the ID' do
422
+ it "raises CantContinue if anything hinky happens with the ID" do
369
423
  expect{ interface.delete(:foo) }.to raise_exception CantContinue
370
424
  expect{ interface.delete(99) }.to raise_exception CantContinue
371
425
  end
372
426
 
373
- it 'makes the record at ID go away' do
427
+ it "makes the record at ID go away" do
374
428
  expect( list_contains(interface, id) ).to be_truthy
375
429
  interface.delete(id)
376
430
  expect( list_contains(interface, id) ).to be_falsy
377
431
  end
378
432
 
379
- it 'shouldn\'t have a problem with non-integer keys' do
433
+ it "has no problem with non-integer keys" do
380
434
  fill_product_data(prod_interface)
381
435
  expect( list_contains(prod_interface, "foo") ).to be_truthy
382
436
  prod_interface.delete("foo")
383
437
  expect( list_contains(prod_interface, "foo") ).to be_falsy
384
438
  end
385
439
 
386
- end
387
- ##
388
-
440
+ end # of #delete
389
441
 
390
- describe '#execute' do
391
442
 
392
- let(:sql) { 'delete from customer where qty < 2.0;' }
443
+ describe "#execute" do
444
+ let(:sql) { "delete from customer where qty < 2.0;" }
393
445
 
394
- it 'requires an SQL string' do
446
+ it "requires an SQL string" do
395
447
  expect{ interface.execute }.to raise_exception ArgumentError
396
448
  expect{ interface.execute(nil) }.to raise_exception ArgumentError
397
449
  expect{ interface.execute(14) }.to raise_exception ArgumentError
398
450
  end
399
451
 
400
- it 'raises some sort of Pod4 error if it runs into problems' do
401
- expect{ interface.execute('delete from not_a_table') }.
452
+ it "raises some sort of Pod4 error if it runs into problems" do
453
+ expect{ interface.execute("delete from not_a_table") }.
402
454
  to raise_exception Pod4Error
403
455
 
404
456
  end
405
457
 
406
- it 'executes the string' do
458
+ it "executes the string" do
407
459
  expect{ interface.execute(sql) }.not_to raise_exception
408
460
  expect( interface.list.size ).to eq(data.size - 1)
409
- expect( interface.list.map{|r| r[:name] } ).not_to include 'Barney'
461
+ expect( interface.list.map{|r| r[:name] } ).not_to include "Barney"
410
462
  end
411
463
 
412
- end
413
- ##
464
+ end # of #execute
414
465
 
415
466
 
416
- describe '#select' do
467
+ describe "#select" do
417
468
 
418
- it 'requires an SQL string' do
469
+ it "requires an SQL string" do
419
470
  expect{ interface.select }.to raise_exception ArgumentError
420
471
  expect{ interface.select(nil) }.to raise_exception ArgumentError
421
472
  expect{ interface.select(14) }.to raise_exception ArgumentError
422
473
  end
423
474
 
424
- it 'raises some sort of Pod4 error if it runs into problems' do
425
- expect{ interface.select('select * from not_a_table') }.
475
+ it "raises some sort of Pod4 error if it runs into problems" do
476
+ expect{ interface.select("select * from not_a_table") }.
426
477
  to raise_exception Pod4Error
427
478
 
428
479
  end
429
480
 
430
- it 'returns the result of the sql' do
431
- sql1 = 'select name from customer where qty < 2.0;'
432
- sql2 = 'select name from customer where qty < 0.0;'
481
+ it "returns the result of the sql" do
482
+ sql1 = "select name from customer where qty < 2.0;"
483
+ sql2 = "select name from customer where qty < 0.0;"
433
484
 
434
485
  expect{ interface.select(sql1) }.not_to raise_exception
435
- expect( interface.select(sql1) ).to eq( [{name: 'Barney'}] )
486
+ expect( interface.select(sql1) ).to eq( [{name: "Barney"}] )
436
487
  expect( interface.select(sql2) ).to eq( [] )
437
488
  end
438
489
 
439
- it 'works if you pass a non-select' do
490
+ it "works if you pass a non-select" do
440
491
  # By which I mean: still executes the SQL; returns []
441
- sql = 'delete from customer where qty < 2.0;'
492
+ sql = "delete from customer where qty < 2.0;"
442
493
  ret = interface.select(sql)
443
494
 
444
495
  expect( interface.list.size ).to eq(data.size - 1)
445
- expect( interface.list.map{|r| r[:name] } ).not_to include 'Barney'
496
+ expect( interface.list.map{|r| r[:name] } ).not_to include "Barney"
446
497
  expect( ret ).to eq( [] )
447
498
  end
448
499
 
449
- end
450
- ##
500
+ end # of #select
451
501
 
452
502
 
453
503
  describe "#executep" do
454
504
  # For the time being lets assume that Sequel does its job and the three modes we are calling
455
505
  # actually work
456
506
 
457
- let(:sql) { 'delete from customer where qty < ?;' }
507
+ let(:sql) { "delete from customer where qty < ?;" }
458
508
 
459
- it 'requires an SQL string and a mode' do
509
+ it "requires an SQL string and a mode" do
460
510
  expect{ interface.executep }.to raise_exception ArgumentError
461
511
  expect{ interface.executep(nil) }.to raise_exception ArgumentError
462
512
  expect{ interface.executep(14, :update) }.to raise_exception ArgumentError
463
513
  expect{ interface.executep(14, :update, 2) }.to raise_exception ArgumentError
464
514
  end
465
515
 
466
- it 'requires the mode to be valid' do
516
+ it "requires the mode to be valid" do
467
517
  expect{ interface.executep(sql, :foo, 2) }.to raise_exception ArgumentError
468
518
  end
469
519
 
470
- it 'raises some sort of Pod4 error if it runs into problems' do
471
- expect{ interface.executep('delete from not_a_table where thingy = ?', :delete, 14) }.
520
+ it "raises some sort of Pod4 error if it runs into problems" do
521
+ expect{ interface.executep("delete from not_a_table where thingy = ?", :delete, 14) }.
472
522
  to raise_exception Pod4Error
473
523
 
474
524
  end
475
525
 
476
- it 'executes the string' do
526
+ it "executes the string" do
477
527
  expect{ interface.executep(sql, :delete, 2.0) }.not_to raise_exception
478
528
  expect( interface.list.size ).to eq(data.size - 1)
479
- expect( interface.list.map{|r| r[:name] } ).not_to include 'Barney'
529
+ expect( interface.list.map{|r| r[:name] } ).not_to include "Barney"
480
530
  end
481
531
 
482
- end
532
+ end # of #executep
483
533
 
484
534
 
485
535
  describe "#selectp" do
486
536
 
487
- it 'requires an SQL string' do
537
+ it "requires an SQL string" do
488
538
  expect{ interface.selectp }.to raise_exception ArgumentError
489
539
  expect{ interface.selectp(nil) }.to raise_exception ArgumentError
490
540
  expect{ interface.selectp(14) }.to raise_exception ArgumentError
491
541
  end
492
542
 
493
- it 'raises some sort of Pod4 error if it runs into problems' do
494
- expect{ interface.selectp('select * from not_a_table where thingy = ?', 14) }.
543
+ it "raises some sort of Pod4 error if it runs into problems" do
544
+ expect{ interface.selectp("select * from not_a_table where thingy = ?", 14) }.
495
545
  to raise_exception Pod4Error
496
546
 
497
547
  end
498
548
 
499
- it 'returns the result of the sql' do
500
- sql = 'select name from customer where qty < ?;'
549
+ it "returns the result of the sql" do
550
+ sql = "select name from customer where qty < ?;"
501
551
 
502
552
  expect{ interface.selectp(sql, 2.0) }.not_to raise_exception
503
- expect( interface.selectp(sql, 2.0) ).to eq( [{name: 'Barney'}] )
553
+ expect( interface.selectp(sql, 2.0) ).to eq( [{name: "Barney"}] )
504
554
  expect( interface.selectp(sql, 0.0) ).to eq( [] )
505
555
  end
506
556
 
507
- it 'works if you pass a non-select' do
557
+ it "works if you pass a non-select" do
508
558
  # By which I mean: still executes the SQL; returns []
509
- sql = 'delete from customer where qty < ?;'
559
+ sql = "delete from customer where qty < ?;"
510
560
  ret = interface.selectp(sql, 2.0)
511
561
 
512
562
  expect( interface.list.size ).to eq(data.size - 1)
513
- expect( interface.list.map{|r| r[:name] } ).not_to include 'Barney'
563
+ expect( interface.list.map{|r| r[:name] } ).not_to include "Barney"
514
564
  expect( ret ).to eq( [] )
515
565
  end
516
566
 
517
- end
567
+ end # #selectp
568
+
569
+
570
+ #
571
+ # We'll not be testing #new_connection or #close_connection since for Sequel, they basically do
572
+ # nothing.
573
+ #
518
574
 
519
575
 
520
576
  end