pod4 0.10.5 → 0.10.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.bugs/bugs +2 -0
- data/.bugs/details/3979ce1679bc4f8c4aef8436e344e10e3773480d.txt +27 -0
- data/.hgtags +1 -0
- data/README.md +11 -29
- data/lib/pod4/encrypting.rb +1 -1
- data/lib/pod4/pg_interface.rb +2 -5
- data/lib/pod4/sequel_interface.rb +3 -6
- data/lib/pod4/tds_interface.rb +1 -1
- data/lib/pod4/typecasting.rb +22 -8
- data/lib/pod4/version.rb +1 -1
- data/spec/common/model_plus_encrypting_spec.rb +3 -3
- data/spec/common/model_plus_typecasting_spec.rb +114 -13
- data/spec/common/sequel_interface_pg_spec.rb +12 -6
- data/spec/common/sql_helper_spec.rb +2 -2
- data/spec/jruby/sequel_interface_jdbc_ms_spec.rb +5 -5
- data/spec/jruby/sequel_interface_jdbc_pg_spec.rb +5 -5
- data/spec/mri/pg_interface_spec.rb +6 -6
- data/spec/mri/sequel_interface_spec.rb +3 -3
- data/spec/mri/tds_interface_spec.rb +8 -8
- metadata +4 -4
- data/spec/mri/pg_interface_spec.rb.orig +0 -611
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d97fb4e3c277219cfee34b8d28bf0464f5ab6424
|
4
|
+
data.tar.gz: a49c67b03b4dab994775eb5774b41cb897a494d4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e567aa380a11cbbe270c89bd69a2b60d2c69583cb8d5dd71208d15e9b9b8511bb766be5a164f6cc57b23ad3e1cd63cb17f80e4e27373356f4b48527df8c79d55
|
7
|
+
data.tar.gz: d62957ca14ceb46dfd33face48e48da8674fe5a82023ff7a259a048b45031be49ef09a114986f37c7b76dc2402c5041d8059e0ef6f0e2947d7621fb66f72902a
|
data/.bugs/bugs
ADDED
@@ -0,0 +1,2 @@
|
|
1
|
+
Fixnum is Deprecated | owner:Andy Jones <andy.jones@jameshall.co.uk>, open:True, id:274eb8828bd4e7d879e4f7a99317c75eb2a2e2b0, time:1533817328.12
|
2
|
+
BigDecimal.new is deprecated | owner:Andy Jones <andy.jones@jameshall.co.uk>, open:True, id:3979ce1679bc4f8c4aef8436e344e10e3773480d, time:1533817342.0
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Lines starting with '#' and sections without content
|
2
|
+
# are not displayed by a call to 'details'
|
3
|
+
#
|
4
|
+
[paths]
|
5
|
+
# Paths related to this bug.
|
6
|
+
# suggested format: REPO_PATH:LINENUMBERS
|
7
|
+
|
8
|
+
|
9
|
+
[details]
|
10
|
+
# Additional details
|
11
|
+
Use BigDecimal("0") instead.
|
12
|
+
|
13
|
+
|
14
|
+
[expected]
|
15
|
+
# The expected result
|
16
|
+
|
17
|
+
|
18
|
+
[actual]
|
19
|
+
# What happened instead
|
20
|
+
|
21
|
+
|
22
|
+
[reproduce]
|
23
|
+
# Reproduction steps
|
24
|
+
|
25
|
+
|
26
|
+
[comments]
|
27
|
+
# Comments and updates - leave your name
|
data/.hgtags
CHANGED
data/README.md
CHANGED
@@ -121,10 +121,10 @@ Simple Model Usage
|
|
121
121
|
x.two = "new value"
|
122
122
|
x.update
|
123
123
|
|
124
|
-
# create a new record from the params hash
|
124
|
+
# create a new record from the params hash
|
125
125
|
y = ExampleModel.new
|
126
126
|
y.set(params)
|
127
|
-
y.create
|
127
|
+
y.create
|
128
128
|
|
129
129
|
A model is a class, each instance of which represents a single record. on that instance you can
|
130
130
|
call the following for basic operation:
|
@@ -141,7 +141,7 @@ call the following for basic operation:
|
|
141
141
|
instance might be represented on the data source as several records, or something else entirely.)
|
142
142
|
|
143
143
|
There is one more operation - `list`. Call this on the model class itself, and it will return an
|
144
|
-
array of model
|
144
|
+
array of model objects that match the criteria you pass. What you can pass to list depends on
|
145
145
|
your model class (of course); by default it also depends on the interface the model uses. But
|
146
146
|
normally it should except a hash, like so:
|
147
147
|
|
@@ -265,8 +265,9 @@ Here's a model with some validation:
|
|
265
265
|
set_interface CustomerInterface.new($pg_conn)
|
266
266
|
attr_columns :cust_code, :name, :group
|
267
267
|
|
268
|
-
def validate
|
268
|
+
def validate(mode)
|
269
269
|
super
|
270
|
+
return if mode == :delete
|
270
271
|
|
271
272
|
add_alert(:error, :name, "Name cannot be empty") \
|
272
273
|
unless @name && @name =~ \^\s*$\
|
@@ -278,13 +279,12 @@ Here's a model with some validation:
|
|
278
279
|
|
279
280
|
end
|
280
281
|
|
281
|
-
(Note: as a general principal, you should always call super when overriding a
|
282
|
-
|
282
|
+
(Note: as a general principal, you should always call super when overriding a method in Pod4 model,
|
283
|
+
unless you have good reason not to.)
|
283
284
|
|
284
|
-
Validation is run on create, read, update and delete. If the model has a status of :error, then
|
285
|
-
|
286
|
-
|
287
|
-
validation passes.
|
285
|
+
Validation is run on create, read, update and delete. If the model has a status of :error, then
|
286
|
+
the validation will fail. (Probably you do not want this on delete; test the parameter passed
|
287
|
+
to validate as in the example above).
|
288
288
|
|
289
289
|
In passing I should note that validation is _not_ run on list: every record that list returns
|
290
290
|
should be complete, but the `model_status` will be :empty because validation has not been run.
|
@@ -295,24 +295,6 @@ possible to set a model to an invalid state and not raise any alerts against it
|
|
295
295
|
commit to the database. If you want to change the state of the model and then validate it before
|
296
296
|
that, you must call `validate` yourself.
|
297
297
|
|
298
|
-
### Conditional Validation for CRUD modes ###
|
299
|
-
|
300
|
-
If you want to write validation that only fires on some of :create, :read, :update or :delete --
|
301
|
-
for example, to stop deletion if a foreign key points to another record that exists -- then you
|
302
|
-
have two options. The recomended way to do this is to add a parameter to your `validate()` method:
|
303
|
-
|
304
|
-
def validate(vmode)
|
305
|
-
super
|
306
|
-
add_alert(:error, "foo") if vmode == :delete && bar
|
307
|
-
end
|
308
|
-
|
309
|
-
There's a little bit of magic here; when you override `validate()` you can choose to give it a
|
310
|
-
parameter or not; either way will work. The value passed to the parameter will either be :create,
|
311
|
-
:read, :update or :delete.
|
312
|
-
|
313
|
-
Your second option is to override the create/read/update/delete method, instead. Just remember to return
|
314
|
-
self, and only call super if you want the operation to go ahead.
|
315
|
-
|
316
298
|
|
317
299
|
Changine How a Model Represents Data
|
318
300
|
------------------------------------
|
@@ -339,7 +321,7 @@ yourself.
|
|
339
321
|
|
340
322
|
def map_to_model(ot)
|
341
323
|
super
|
342
|
-
@cost = Bigdecimal
|
324
|
+
@cost = Bigdecimal(@cost)
|
343
325
|
end
|
344
326
|
|
345
327
|
def map_to_interface
|
data/lib/pod4/encrypting.rb
CHANGED
data/lib/pod4/pg_interface.rb
CHANGED
@@ -299,7 +299,7 @@ module Pod4
|
|
299
299
|
end
|
300
300
|
|
301
301
|
|
302
|
-
|
302
|
+
private
|
303
303
|
|
304
304
|
|
305
305
|
##
|
@@ -402,9 +402,6 @@ module Pod4
|
|
402
402
|
end
|
403
403
|
|
404
404
|
|
405
|
-
private
|
406
|
-
|
407
|
-
|
408
405
|
##
|
409
406
|
# build a hash of column -> oid
|
410
407
|
#
|
@@ -430,7 +427,7 @@ module Pod4
|
|
430
427
|
lInt =->(s) { Integer(s,10) rescue s }
|
431
428
|
lTime =->(s) { Time.parse(s) rescue s }
|
432
429
|
lDate =->(s) { Date.parse(s) rescue s }
|
433
|
-
lBigDec =->(s) { BigDecimal
|
430
|
+
lBigDec =->(s) { BigDecimal(s) rescue s }
|
434
431
|
|
435
432
|
row.each_with_object({}) do |(k,v),h|
|
436
433
|
key = k.to_sym
|
@@ -98,13 +98,13 @@ module Pod4
|
|
98
98
|
# the money type. This workaround actually allows us to return a BigDecimal, so it's better
|
99
99
|
# than using postgres_pr when under jRuby!
|
100
100
|
if @db.uri =~ /jdbc:postgresql/
|
101
|
-
@db.conversion_procs[790] = ->(s){BigDecimal
|
101
|
+
@db.conversion_procs[790] = ->(s){BigDecimal(s[1..-1]) rescue nil}
|
102
102
|
c = Sequel::JDBC::Postgres::Dataset
|
103
103
|
|
104
104
|
if @sequel_version >= 5
|
105
105
|
# In Sequel 5 everything is frozen, so some hacking is required.
|
106
106
|
# See https://github.com/jeremyevans/sequel/issues/1458
|
107
|
-
vals = c::PG_SPECIFIC_TYPES + [Java::JavaSQL::Types::DOUBLE]
|
107
|
+
vals = c::PG_SPECIFIC_TYPES + [Java::JavaSQL::Types::DOUBLE]
|
108
108
|
c.send(:remove_const, :PG_SPECIFIC_TYPES) # We can probably get away with just const_set, but.
|
109
109
|
c.send(:const_set, :PG_SPECIFIC_TYPES, vals.freeze)
|
110
110
|
else
|
@@ -288,7 +288,7 @@ module Pod4
|
|
288
288
|
end
|
289
289
|
|
290
290
|
|
291
|
-
|
291
|
+
private
|
292
292
|
|
293
293
|
|
294
294
|
##
|
@@ -355,9 +355,6 @@ module Pod4
|
|
355
355
|
end
|
356
356
|
|
357
357
|
|
358
|
-
private
|
359
|
-
|
360
|
-
|
361
358
|
def read_or_die(id)
|
362
359
|
raise CantContinue, "'No record found with ID '#{id}'" if read(id).empty?
|
363
360
|
end
|
data/lib/pod4/tds_interface.rb
CHANGED
data/lib/pod4/typecasting.rb
CHANGED
@@ -57,7 +57,9 @@ module Pod4
|
|
57
57
|
# so.
|
58
58
|
#
|
59
59
|
# `map_to_model`: incoming data from the data source is coerced to the given encoding if
|
60
|
-
# `force_encoding` has been used.
|
60
|
+
# `force_encoding` has been used. Typecast attributes are cast as per their settings, or if they
|
61
|
+
# cannot be cast, are left alone. (Unless you have specified strict: true, in which case they are
|
62
|
+
# set to nil.)
|
61
63
|
#
|
62
64
|
# `set()`: typecast attributes are cast as per their settings, or if they cannot be cast, are left
|
63
65
|
# alone. (Unless you have specified `strict: true`, in which case they are set to nil.)
|
@@ -68,6 +70,9 @@ module Pod4
|
|
68
70
|
# `map_to_interface()`: typecast attributes are cast as per their settings, or if they cannot be
|
69
71
|
# cast, are set to nil.
|
70
72
|
#
|
73
|
+
# Note: Typecasting does not prevent you from setting any value you please on a model attibute
|
74
|
+
# @foo by using `model.foo = value`.
|
75
|
+
#
|
71
76
|
# Additional methods
|
72
77
|
# ------------------
|
73
78
|
#
|
@@ -91,13 +96,17 @@ module Pod4
|
|
91
96
|
# where value is the value to be typecast, and options is the hash of options you specified for
|
92
97
|
# that column. Pod4 will set the column to whatever your method returns.
|
93
98
|
#
|
99
|
+
# The options hash will have an additional key :mode in case you need to cast differently in
|
100
|
+
# different circumstances. Mode will be one of :set, :map_to_interface, :map_to_model, or
|
101
|
+
# :typecast? (if you call `typecast?` yourself).
|
102
|
+
#
|
94
103
|
# What you don't get
|
95
104
|
# ------------------
|
96
105
|
#
|
97
106
|
# None of this has any direct effect on validation, although of course we do provide methods such
|
98
107
|
# as `typecast?()` to specifically help you with validation.
|
99
108
|
#
|
100
|
-
# Naming an attribute using `typecast` does not automatically make
|
109
|
+
# Naming an attribute using `typecast` does not automatically make it a Pod4 column; you need to
|
101
110
|
# use `attr_column`, just as in plain Pod4. Furthermore, *only* Pod4 columns can be named in the
|
102
111
|
# typecast command, although you can use the `typecast` instance method, etc., to help you roll
|
103
112
|
# your own typecasting for non-column attributes.
|
@@ -109,6 +118,10 @@ module Pod4
|
|
109
118
|
# regardless of how it is typecast. (On the contrary: by forcing strict columns to nil if they
|
110
119
|
# fail typecasting, we help you validate.)
|
111
120
|
#
|
121
|
+
# It's theoretically possible that you could typecast a column into something that the
|
122
|
+
# interface cannot cast back onto the database. We don't cover you in that case. If it happens,
|
123
|
+
# you will have to deal with it yourself in `map_to_interface`.
|
124
|
+
#
|
112
125
|
module TypeCasting
|
113
126
|
|
114
127
|
TYPES = [ Date, Time, Integer, Float, BigDecimal, :boolean ]
|
@@ -171,17 +184,18 @@ module Pod4
|
|
171
184
|
v.force_encoding(enc) if v.kind_of?(String) && enc
|
172
185
|
end
|
173
186
|
|
174
|
-
|
187
|
+
hash = typecast_ot(ot, mode: :map_to_model)
|
188
|
+
super(ot.merge hash)
|
175
189
|
end
|
176
190
|
|
177
191
|
def set(ot)
|
178
|
-
hash = typecast_ot(ot)
|
192
|
+
hash = typecast_ot(ot, mode: :set)
|
179
193
|
super(ot.merge hash)
|
180
194
|
end
|
181
195
|
|
182
196
|
def map_to_interface
|
183
197
|
ot = super
|
184
|
-
hash = typecast_ot(ot, strict: true)
|
198
|
+
hash = typecast_ot(ot, strict: true, mode: :map_to_interface)
|
185
199
|
ot.merge hash
|
186
200
|
end
|
187
201
|
|
@@ -234,7 +248,7 @@ module Pod4
|
|
234
248
|
unless (tc = self.class.typecasts[attr])
|
235
249
|
|
236
250
|
val = instance_variable_get("@#{attr}".to_sym) if val.nil?
|
237
|
-
!typecast_one(val, tc.merge(strict: true)).nil?
|
251
|
+
!typecast_one(val, tc.merge(strict: true, mode: :typecast?)).nil?
|
238
252
|
end
|
239
253
|
|
240
254
|
##
|
@@ -291,7 +305,7 @@ module Pod4
|
|
291
305
|
#
|
292
306
|
def set_guard(ot, fld, tc)
|
293
307
|
case tc.to_s
|
294
|
-
when "BigDecimal" then ot.guard(fld) { BigDecimal
|
308
|
+
when "BigDecimal" then ot.guard(fld) { BigDecimal("0") }
|
295
309
|
when "Float" then ot.guard(fld) { Float(0) }
|
296
310
|
when "Integer" then ot.guard(fld) { Integer(0) }
|
297
311
|
when "Date" then ot.guard(fld) { Date.new(1900, 1, 1) }
|
@@ -302,7 +316,7 @@ module Pod4
|
|
302
316
|
|
303
317
|
def tc_bigdecimal(thing)
|
304
318
|
Float(thing) # BigDecimal sucks at catching bad decimals
|
305
|
-
BigDecimal
|
319
|
+
BigDecimal(thing.to_s)
|
306
320
|
end
|
307
321
|
|
308
322
|
def tc_float(thing)
|
data/lib/pod4/version.rb
CHANGED
@@ -24,14 +24,14 @@ describe "(Model with Encryption)" do
|
|
24
24
|
Base64.strict_encode64(answer)
|
25
25
|
end
|
26
26
|
|
27
|
-
let(:encryption_key) { "
|
27
|
+
let(:encryption_key) { "dflkasdgklajndgn" }
|
28
28
|
|
29
29
|
let(:medical_model_class) do # model with an IV column
|
30
30
|
Class.new Pod4::Model do
|
31
31
|
include Pod4::Encrypting
|
32
32
|
attr_columns :id, :nhs_no # note, we don't bother to name encrypted columns
|
33
33
|
encrypted_columns :name, :ailment, :prescription
|
34
|
-
set_key "
|
34
|
+
set_key "dflkasdgklajndgn"
|
35
35
|
set_iv_column :nonce
|
36
36
|
set_interface NullInterface.new(:id, :nhs_no, :name, :ailment, :prescription, :nonce, [])
|
37
37
|
end
|
@@ -64,7 +64,7 @@ describe "(Model with Encryption)" do
|
|
64
64
|
include Pod4::Encrypting
|
65
65
|
attr_columns :id, :date, :heading, :text
|
66
66
|
encrypted_columns :heading, :text
|
67
|
-
set_key "
|
67
|
+
set_key "dflkasdgklajndgn"
|
68
68
|
set_interface NullInterface.new(:id, :date, :heading, :text, [])
|
69
69
|
end
|
70
70
|
end
|
@@ -31,7 +31,7 @@ describe "ProductModel" do
|
|
31
31
|
set_interface NullInterface.new( :id, :code, :band, :sales, :created, :yrstart,
|
32
32
|
:flag, :foo, :bar, [] )
|
33
33
|
|
34
|
-
def mycast(value, opts); "blarg" end
|
34
|
+
def mycast(value, opts); "blarg"; end
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
@@ -160,6 +160,99 @@ describe "ProductModel" do
|
|
160
160
|
expect( ot.>>.product.encoding ).to eq Encoding::ISO_8859_1
|
161
161
|
end
|
162
162
|
|
163
|
+
it "typecasts strings to whatever" do
|
164
|
+
c = customer_model_class.new(77)
|
165
|
+
ot = Octothorpe.new( id: 77,
|
166
|
+
code: "seven",
|
167
|
+
band: "7",
|
168
|
+
sales: "12.34",
|
169
|
+
created: "2018-01-01 12:34",
|
170
|
+
yrstart: "2018-01-02",
|
171
|
+
flag: "true",
|
172
|
+
bar: "34.56" )
|
173
|
+
|
174
|
+
expect( c.interface ).to receive(:read).and_return(ot)
|
175
|
+
c.read
|
176
|
+
|
177
|
+
expect( c.id ).to eq 77
|
178
|
+
expect( c.code ).to eq "seven"
|
179
|
+
expect( c.band ).to eq 7
|
180
|
+
expect( c.sales ).to eq 12.34
|
181
|
+
expect( c.created ).to eq Time.parse("2018-01-01 12:34")
|
182
|
+
expect( c.yrstart ).to eq Date.parse("2018-01-02")
|
183
|
+
expect( c.flag ).to eq true
|
184
|
+
expect( c.bar ).to eq 34.56
|
185
|
+
end
|
186
|
+
|
187
|
+
|
188
|
+
it "allows the attribute to be nil" do
|
189
|
+
c = customer_model_class.new(11)
|
190
|
+
ot = Octothorpe.new( id: 11,
|
191
|
+
code: "foo",
|
192
|
+
band: nil,
|
193
|
+
sales: nil,
|
194
|
+
created: nil,
|
195
|
+
yrstart: nil,
|
196
|
+
flag: nil,
|
197
|
+
bar: nil )
|
198
|
+
|
199
|
+
expect( c.interface ).to receive(:read).and_return(ot)
|
200
|
+
c.read
|
201
|
+
|
202
|
+
expect( c.code ).to eq "foo"
|
203
|
+
expect( c.band ).to eq nil
|
204
|
+
expect( c.sales ).to eq nil
|
205
|
+
expect( c.created ).to eq nil
|
206
|
+
expect( c.yrstart ).to eq nil
|
207
|
+
expect( c.flag ).to eq nil
|
208
|
+
expect( c.bar ).to eq nil
|
209
|
+
end
|
210
|
+
|
211
|
+
it "leaves the column alone if it can't typecast (with strict off)" do
|
212
|
+
c = customer_model_class.new(23)
|
213
|
+
ot = Octothorpe.new( id: 23,
|
214
|
+
created: "bloob",
|
215
|
+
yrstart: "flarg",
|
216
|
+
flag: "blobe",
|
217
|
+
bar: "xing" )
|
218
|
+
|
219
|
+
expect( c.interface ).to receive(:read).and_return(ot)
|
220
|
+
c.read
|
221
|
+
|
222
|
+
expect( c.created ).to eq "bloob"
|
223
|
+
expect( c.yrstart ).to eq "flarg"
|
224
|
+
expect( c.flag ).to eq "blobe"
|
225
|
+
expect( c.bar ).to eq "xing"
|
226
|
+
end
|
227
|
+
|
228
|
+
it "sets the column to nil if it can't typecast (with strict on)" do
|
229
|
+
c = customer_model_class.new(23)
|
230
|
+
ot = Octothorpe.new( id: 23,
|
231
|
+
band: "bloob",
|
232
|
+
sales: "flarg" )
|
233
|
+
|
234
|
+
expect( c.interface ).to receive(:read).and_return(ot)
|
235
|
+
c.read
|
236
|
+
|
237
|
+
expect( c.band ).to be_nil
|
238
|
+
expect( c.sales ).to be_nil
|
239
|
+
end
|
240
|
+
|
241
|
+
it "calls the use method to get a typecast when the use option is given" do
|
242
|
+
c = customer_model_class.new(43)
|
243
|
+
ot = Octothorpe.new( id: 43, foo: "12345" )
|
244
|
+
|
245
|
+
expect( c.interface ).to receive(:read).and_return(ot)
|
246
|
+
expect( c ).
|
247
|
+
to receive(:mycast).
|
248
|
+
with("12345", {use: :mycast, bar: 42, mode: :map_to_model} ).
|
249
|
+
and_call_original
|
250
|
+
|
251
|
+
c.read
|
252
|
+
|
253
|
+
expect( c.foo ).to eq "blarg"
|
254
|
+
end
|
255
|
+
|
163
256
|
end
|
164
257
|
|
165
258
|
|
@@ -232,9 +325,14 @@ describe "ProductModel" do
|
|
232
325
|
|
233
326
|
it "calls the use method to get a typecast when the use option is given" do
|
234
327
|
c = customer_model_class.new
|
235
|
-
expect( c ).
|
328
|
+
expect( c ).
|
329
|
+
to receive(:mycast).
|
330
|
+
with("12345", {use: :mycast, bar: 42, mode: :set} ).
|
331
|
+
and_call_original
|
236
332
|
|
237
333
|
c.set( foo: "12345" )
|
334
|
+
|
335
|
+
expect( c.foo ).to eq "blarg"
|
238
336
|
end
|
239
337
|
|
240
338
|
end # of #set
|
@@ -257,7 +355,7 @@ describe "ProductModel" do
|
|
257
355
|
record = customer_model_class.interface.read(11)
|
258
356
|
expect( record.>>.code ).to eq "foo"
|
259
357
|
expect( record.>>.band ).to eq 12
|
260
|
-
expect( record.>>.sales ).to eq BigDecimal
|
358
|
+
expect( record.>>.sales ).to eq BigDecimal("98.76")
|
261
359
|
expect( record.>>.created ).to eq Time.parse("2018-04-04 11:59")
|
262
360
|
expect( record.>>.yrstart ).to eq Date.parse("2018-01-09")
|
263
361
|
expect( record.>>.flag ).to eq true
|
@@ -309,7 +407,10 @@ describe "ProductModel" do
|
|
309
407
|
it "calls the use method to get a typecast when the use option is given" do
|
310
408
|
c = customer_model_class.new
|
311
409
|
# Note that we have gained the strict option automatically since we're in map_to_interface
|
312
|
-
expect( c ).
|
410
|
+
expect( c ).
|
411
|
+
to receive(:mycast).
|
412
|
+
with("12345", {use: :mycast, bar: 42, strict: true, mode: :map_to_interface}).
|
413
|
+
and_call_original
|
313
414
|
|
314
415
|
c.id = 33
|
315
416
|
c.code = "baz"
|
@@ -335,7 +436,7 @@ describe "ProductModel" do
|
|
335
436
|
|
336
437
|
it "casts any columns with the ot_as option as per that option" do
|
337
438
|
c1 = customer_model_class.new
|
338
|
-
c1.sales = BigDecimal
|
439
|
+
c1.sales = BigDecimal("45.67")
|
339
440
|
ot = c1.to_ot
|
340
441
|
expect( ot.>>.sales ).to be_a Float
|
341
442
|
expect( ot.>>.sales ).to eq 45.67
|
@@ -364,7 +465,7 @@ describe "ProductModel" do
|
|
364
465
|
it "typecasts strings to any type" do
|
365
466
|
expect( cmodel.typecast(Integer, "123") ).to eq 123
|
366
467
|
expect( cmodel.typecast(Float, "23.45") ).to eq 23.45
|
367
|
-
expect( cmodel.typecast(BigDecimal, "34.56") ).to eq BigDecimal
|
468
|
+
expect( cmodel.typecast(BigDecimal, "34.56") ).to eq BigDecimal("34.56")
|
368
469
|
expect( cmodel.typecast(Date, "2018-01-01") ).to eq Date.parse("2018-01-01")
|
369
470
|
expect( cmodel.typecast(Time, "2018-02-02 14:56") ).to eq Time.parse("2018-02-02 14:56")
|
370
471
|
expect( cmodel.typecast(:boolean, "true") ).to eq true
|
@@ -375,16 +476,16 @@ describe "ProductModel" do
|
|
375
476
|
expect( cmodel.typecast(Float, 12) ).to be_a Float
|
376
477
|
expect( cmodel.typecast(Float, 12) ).to eq 12.0
|
377
478
|
|
378
|
-
expect( cmodel.typecast(Float, BigDecimal
|
379
|
-
expect( cmodel.typecast(Float, BigDecimal
|
479
|
+
expect( cmodel.typecast(Float, BigDecimal("12.34")) ).to be_a Float
|
480
|
+
expect( cmodel.typecast(Float, BigDecimal("12.34")) ).to eq 12.34
|
380
481
|
end
|
381
482
|
|
382
483
|
it "typecasts Integer and Float to BigDecimal" do
|
383
484
|
expect( cmodel.typecast(BigDecimal, 12) ).to be_a BigDecimal
|
384
|
-
expect( cmodel.typecast(BigDecimal, 12) ).to eq BigDecimal
|
485
|
+
expect( cmodel.typecast(BigDecimal, 12) ).to eq BigDecimal("12.0")
|
385
486
|
|
386
487
|
expect( cmodel.typecast(BigDecimal, 12.34) ).to be_a BigDecimal
|
387
|
-
expect( cmodel.typecast(BigDecimal, 12.34) ).to eq BigDecimal
|
488
|
+
expect( cmodel.typecast(BigDecimal, 12.34) ).to eq BigDecimal("12.34")
|
388
489
|
end
|
389
490
|
|
390
491
|
|
@@ -423,8 +524,8 @@ describe "ProductModel" do
|
|
423
524
|
end
|
424
525
|
|
425
526
|
it "will not cast a float or a BigDecimal to an Integer" do
|
426
|
-
expect( cmodel.typecast(Integer, 12.34,
|
427
|
-
expect( cmodel.typecast(Integer, BigDecimal
|
527
|
+
expect( cmodel.typecast(Integer, 12.34, strict: true) ).to eq nil
|
528
|
+
expect( cmodel.typecast(Integer, BigDecimal("12.34"), strict: true) ).to eq nil
|
428
529
|
end
|
429
530
|
|
430
531
|
it "will not cast a Time to a Date" do
|
@@ -440,7 +541,7 @@ describe "ProductModel" do
|
|
440
541
|
it "returns true if the value can be cast to the type" do
|
441
542
|
expect( cmodel.typecast?(:band, 123) ).to eq true
|
442
543
|
expect( cmodel.typecast?(:bar, 23.45) ).to eq true
|
443
|
-
expect( cmodel.typecast?(:sales, BigDecimal
|
544
|
+
expect( cmodel.typecast?(:sales, BigDecimal("34.56")) ).to eq true
|
444
545
|
expect( cmodel.typecast?(:created, Time.parse("2018-02-02 14:56")) ).to eq true
|
445
546
|
expect( cmodel.typecast?(:yrstart, Date.parse("2018-01-01")) ).to eq true
|
446
547
|
expect( cmodel.typecast?(:flag, true) ).to eq true
|
@@ -41,22 +41,22 @@ describe "SequelInterface (Pg)" do
|
|
41
41
|
level: 1.23,
|
42
42
|
day: Date.parse("2016-01-01"),
|
43
43
|
timestamp: Time.parse('2015-01-01 12:11'),
|
44
|
-
qty: BigDecimal
|
45
|
-
price: BigDecimal
|
44
|
+
qty: BigDecimal("1.24"),
|
45
|
+
price: BigDecimal("1.24") }
|
46
46
|
|
47
47
|
d << { name: 'Fred',
|
48
48
|
level: 2.34,
|
49
49
|
day: Date.parse("2016-02-02"),
|
50
50
|
timestamp: Time.parse('2015-01-02 12:22'),
|
51
|
-
qty: BigDecimal
|
52
|
-
price: BigDecimal
|
51
|
+
qty: BigDecimal("2.35"),
|
52
|
+
price: BigDecimal("2.35") }
|
53
53
|
|
54
54
|
d << { name: 'Betty',
|
55
55
|
level: 3.45,
|
56
56
|
day: Date.parse("2016-03-03"),
|
57
57
|
timestamp: Time.parse('2015-01-03 12:33'),
|
58
|
-
qty: BigDecimal
|
59
|
-
price: BigDecimal
|
58
|
+
qty: BigDecimal("3.46"),
|
59
|
+
price: BigDecimal("3.46") }
|
60
60
|
|
61
61
|
d
|
62
62
|
end
|
@@ -97,6 +97,7 @@ describe "SequelInterface (Pg)" do
|
|
97
97
|
let(:prod_interface) { prod_interface_class.new(db) }
|
98
98
|
|
99
99
|
|
100
|
+
|
100
101
|
before do
|
101
102
|
interface.execute %Q|
|
102
103
|
truncate table customer restart identity;
|
@@ -132,6 +133,7 @@ describe "SequelInterface (Pg)" do
|
|
132
133
|
let(:hash) { {name: 'Bam-Bam', qty: 4.44} }
|
133
134
|
let(:ot) { Octothorpe.new(name: 'Wilma', qty: 5.55) }
|
134
135
|
|
136
|
+
|
135
137
|
it 'raises a Pod4::DatabaseError if anything goes wrong' do
|
136
138
|
expect{ interface.create(one: 'two') }.to raise_exception DatabaseError
|
137
139
|
end
|
@@ -165,6 +167,8 @@ describe "SequelInterface (Pg)" do
|
|
165
167
|
end
|
166
168
|
|
167
169
|
it 'shouldnt have a problem with strings containing special characters' do
|
170
|
+
# Note that in passing we retest that create returns the ID for identity columns
|
171
|
+
|
168
172
|
record = {name: "T'Challa[]", price: nil}
|
169
173
|
expect{ interface.create(record) }.not_to raise_exception
|
170
174
|
id = interface.create(record)
|
@@ -172,6 +176,8 @@ describe "SequelInterface (Pg)" do
|
|
172
176
|
end
|
173
177
|
|
174
178
|
it 'shouldn\'t have a problem with non-integer keys' do
|
179
|
+
# Note that in passing we retest that create returns the ID for non-identity columns
|
180
|
+
|
175
181
|
hash = {code: "foo", name: "bar"}
|
176
182
|
id = prod_interface.create( Octothorpe.new(hash) )
|
177
183
|
|
@@ -103,7 +103,7 @@ describe "SQLHelper" do
|
|
103
103
|
end
|
104
104
|
|
105
105
|
it "returns a BigDecimal as a float" do
|
106
|
-
bd = BigDecimal
|
106
|
+
bd = BigDecimal("14.98")
|
107
107
|
expect( tester1.send :quote, bd ).to eq 14.98
|
108
108
|
end
|
109
109
|
|
@@ -112,7 +112,7 @@ describe "SQLHelper" do
|
|
112
112
|
end
|
113
113
|
|
114
114
|
it "will wrap the value in some other character if you pass that" do
|
115
|
-
bd = BigDecimal
|
115
|
+
bd = BigDecimal("14.98")
|
116
116
|
expect( tester1.send :quote, "thing", nil ).to eq %Q|thing|
|
117
117
|
expect( tester1.send :quote, "thing", "x" ).to eq %Q|xthingx|
|
118
118
|
expect( tester1.send :quote, bd ).to eq 14.98
|
@@ -46,21 +46,21 @@ describe "SequelInterface (JDBC/MSSQL)" do
|
|
46
46
|
level: 1.23,
|
47
47
|
day: Date.parse("2016-01-01"),
|
48
48
|
timestamp: Time.parse('2015-01-01 12:11'),
|
49
|
-
qty: BigDecimal
|
49
|
+
qty: BigDecimal("1.24"),
|
50
50
|
price: nil }
|
51
51
|
|
52
52
|
d << { name: 'Fred',
|
53
53
|
level: 2.34,
|
54
54
|
day: Date.parse("2016-02-02"),
|
55
55
|
timestamp: Time.parse('2015-01-02 12:22'),
|
56
|
-
qty: BigDecimal
|
56
|
+
qty: BigDecimal("2.35"),
|
57
57
|
price: nil }
|
58
58
|
|
59
59
|
d << { name: 'Betty',
|
60
60
|
level: 3.45,
|
61
61
|
day: Date.parse("2016-03-03"),
|
62
62
|
timestamp: Time.parse('2015-01-03 12:33'),
|
63
|
-
qty: BigDecimal
|
63
|
+
qty: BigDecimal("3.46"),
|
64
64
|
price: nil }
|
65
65
|
|
66
66
|
d
|
@@ -244,8 +244,8 @@ describe "SequelInterface (JDBC/MSSQL)" do
|
|
244
244
|
level: 4.56,
|
245
245
|
day: Date.parse("2016-03-03"),
|
246
246
|
timestamp: Time.parse('2015-01-03 12:44'),
|
247
|
-
qty: BigDecimal
|
248
|
-
price: BigDecimal
|
247
|
+
qty: BigDecimal("4.57"),
|
248
|
+
price: BigDecimal("4.58") }
|
249
249
|
|
250
250
|
interface.create(dibble)
|
251
251
|
price = interface.read(4).>>.price
|