pod4 0.10.5 → 0.10.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|