pod4 0.10.6 → 1.0.0
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 +5 -5
- data/.bugs/bugs +2 -1
- data/.bugs/details/b5368c7ef19065fc597b5692314da71772660963.txt +53 -0
- data/.hgtags +1 -0
- data/Gemfile +5 -5
- data/README.md +157 -46
- data/lib/pod4/basic_model.rb +9 -22
- data/lib/pod4/connection.rb +67 -0
- data/lib/pod4/connection_pool.rb +154 -0
- data/lib/pod4/errors.rb +20 -0
- data/lib/pod4/interface.rb +34 -12
- data/lib/pod4/model.rb +32 -27
- data/lib/pod4/nebulous_interface.rb +25 -30
- data/lib/pod4/null_interface.rb +22 -16
- data/lib/pod4/pg_interface.rb +84 -104
- data/lib/pod4/sequel_interface.rb +138 -82
- data/lib/pod4/tds_interface.rb +83 -70
- data/lib/pod4/tweaking.rb +105 -0
- data/lib/pod4/version.rb +1 -1
- data/md/breaking_changes.md +80 -0
- data/spec/common/basic_model_spec.rb +67 -70
- data/spec/common/connection_pool_parallelism_spec.rb +154 -0
- data/spec/common/connection_pool_spec.rb +246 -0
- data/spec/common/connection_spec.rb +129 -0
- data/spec/common/model_ai_missing_id_spec.rb +256 -0
- data/spec/common/model_plus_encrypting_spec.rb +16 -4
- data/spec/common/model_plus_tweaking_spec.rb +128 -0
- data/spec/common/model_plus_typecasting_spec.rb +10 -4
- data/spec/common/model_spec.rb +283 -363
- data/spec/common/nebulous_interface_spec.rb +159 -108
- data/spec/common/null_interface_spec.rb +88 -65
- data/spec/common/sequel_interface_pg_spec.rb +217 -161
- data/spec/common/shared_examples_for_interface.rb +50 -50
- data/spec/jruby/sequel_encrypting_jdbc_pg_spec.rb +1 -1
- data/spec/jruby/sequel_interface_jdbc_ms_spec.rb +3 -3
- data/spec/jruby/sequel_interface_jdbc_pg_spec.rb +3 -23
- data/spec/mri/pg_encrypting_spec.rb +1 -1
- data/spec/mri/pg_interface_spec.rb +311 -223
- data/spec/mri/sequel_encrypting_spec.rb +1 -1
- data/spec/mri/sequel_interface_spec.rb +177 -180
- data/spec/mri/tds_encrypting_spec.rb +1 -1
- data/spec/mri/tds_interface_spec.rb +296 -212
- data/tags +340 -174
- metadata +19 -11
- data/md/fixme.md +0 -3
- data/md/roadmap.md +0 -125
- data/md/typecasting.md +0 -80
- data/spec/common/model_new_validate_spec.rb +0 -204
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1e0f3ba3e1a6e876874296334e8df4a789c6757403a6f72697e7f2a5506ac05f
|
4
|
+
data.tar.gz: db35eb4f442ebe83b30de9ce394354143586142144af531171f35afffa8e504c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4d033f6947e0e2fcf421f764746f647c68e1158b65568a215c57db2508773aecc700815bc4ad318bb844f5252e89c64fe16eca6a1b20c60fb15730835d411b90
|
7
|
+
data.tar.gz: 68908e5107c5f1160b42b4948514554c57e53dcc337e413fd5b6282e6edc22ecf4dd51680a4a11f59103c6fb2ee1f8cb1d138f01b0f9007c5be41f4e2b984b1f
|
data/.bugs/bugs
CHANGED
@@ -1,2 +1,3 @@
|
|
1
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:
|
2
|
+
BigDecimal.new is deprecated | owner:Andy Jones <andy.jones@jameshall.co.uk>, open:False, id:3979ce1679bc4f8c4aef8436e344e10e3773480d, time:1533817342.0
|
3
|
+
Connection Pool Parallelism tests crash rspec when run as part of the suite | owner:Andy Jones <andy.jones@jameshall.co.uk>, open:False, id:b5368c7ef19065fc597b5692314da71772660963, time:1554280671.5
|
@@ -0,0 +1,53 @@
|
|
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
|
+
You can duplicate this by running the following tests in this order, in Jruby:
|
12
|
+
|
13
|
+
* common/connection_pool_parallelism_spec
|
14
|
+
* common/nebulous_interface_spec
|
15
|
+
* common/sequel_pg_interface_spec
|
16
|
+
|
17
|
+
Here's the error:
|
18
|
+
|
19
|
+
```
|
20
|
+
Stomp::Error::ReceiveTimeout: Stomp::Error::ReceiveTimeout
|
21
|
+
block in _receive at /home/jonea/.rbenv/versions/jruby-9.1.17.0/lib/ruby/gems/shared/gems/stomp-1.4.4/lib/connec
|
22
|
+
tion/netio.rb:66
|
23
|
+
synchronize at org/jruby/ext/thread/Mutex.java:158
|
24
|
+
_receive at /home/jonea/.rbenv/versions/jruby-9.1.17.0/lib/ruby/gems/shared/gems/stomp-1.4.4/lib/connec
|
25
|
+
tion/netio.rb:31
|
26
|
+
__old_receive at /home/jonea/.rbenv/versions/jruby-9.1.17.0/lib/ruby/gems/shared/gems/stomp-1.4.4/lib/connec
|
27
|
+
tion/utils.rb:250
|
28
|
+
receive at /home/jonea/.rbenv/versions/jruby-9.1.17.0/lib/ruby/gems/shared/gems/stomp-1.4.4/lib/stomp/
|
29
|
+
connection.rb:481
|
30
|
+
block in start_listeners at /home/jonea/.rbenv/versions/jruby-9.1.17.0/lib/ruby/gems/shared/gems/stomp-1.4.4/lib/client
|
31
|
+
/utils.rb:194
|
32
|
+
loop at org/jruby/RubyKernel.java:1316
|
33
|
+
block in start_listeners at /home/jonea/.rbenv/versions/jruby-9.1.17.0/lib/ruby/gems/shared/gems/stomp-1.4.4/lib/client
|
34
|
+
/utils.rb:193
|
35
|
+
r
|
36
|
+
```
|
37
|
+
|
38
|
+
This might be related to this jRuby bug: https://github.com/jruby/jruby/issues/5476.
|
39
|
+
|
40
|
+
[expected]
|
41
|
+
# The expected result
|
42
|
+
|
43
|
+
|
44
|
+
[actual]
|
45
|
+
# What happened instead
|
46
|
+
|
47
|
+
|
48
|
+
[reproduce]
|
49
|
+
# Reproduction steps
|
50
|
+
|
51
|
+
|
52
|
+
[comments]
|
53
|
+
# Comments and updates - leave your name
|
data/.hgtags
CHANGED
data/Gemfile
CHANGED
@@ -6,19 +6,19 @@ gemspec
|
|
6
6
|
group :development, :test do
|
7
7
|
|
8
8
|
# for bundler, management, etc etc
|
9
|
-
gem "bundler", "~>
|
9
|
+
gem "bundler", "~> 2"
|
10
10
|
gem "rake", "~> 12"
|
11
|
-
gem "rspec", "~> 3.
|
11
|
+
gem "rspec", "~> 3.8"
|
12
12
|
gem 'pry'
|
13
13
|
gem "pry-doc"
|
14
14
|
|
15
15
|
# For testing
|
16
|
-
gem "sequel", "~> 5.
|
16
|
+
gem "sequel", "~> 5.20"
|
17
17
|
gem "nebulous_stomp", "~> 3"
|
18
18
|
|
19
19
|
platforms :ruby do
|
20
|
-
gem "sqlite3", "~> 1.
|
21
|
-
gem "tiny_tds", "~> 1
|
20
|
+
gem "sqlite3", "~> 1.4"
|
21
|
+
gem "tiny_tds", "~> 2.1"
|
22
22
|
gem "pg"
|
23
23
|
end
|
24
24
|
|
data/README.md
CHANGED
@@ -49,7 +49,8 @@ I don't want the people who maintain my code to have to know the differences bet
|
|
49
49
|
or so methods you need to worry about, and six of those are pretty much self-explanatory. Or, you
|
50
50
|
can inherit from Pod4::BasicModel instead, and do without even that.
|
51
51
|
|
52
|
-
I honestly don't think of it as an Object Relational Manager. I think of it as a Way To Have Nice
|
52
|
+
I honestly don't think of it as an Object Relational Manager. I think of it as a Way To Have Nice
|
53
|
+
Models.
|
53
54
|
|
54
55
|
If you are looking for something with all the features of, say, ActiveRecord, then this isn't for
|
55
56
|
you. I provide basic access to and maintenance of records, with validation. For anything more, you
|
@@ -168,7 +169,7 @@ Here is the model and interface definition that goes with the above example:
|
|
168
169
|
|
169
170
|
class ExampleInterface < Pod4::PgInterface
|
170
171
|
set_table :example
|
171
|
-
set_id_fld :id
|
172
|
+
set_id_fld :id, autoincrement: true
|
172
173
|
end
|
173
174
|
|
174
175
|
set_interface ExampleInterface.new($pg_conn)
|
@@ -199,11 +200,12 @@ the data. What they are depends on the interface, but the ones for PgInterface a
|
|
199
200
|
|
200
201
|
Actually, _every_ interface defines `set_id_fld`. Instances of a model _must_ be represented by a
|
201
202
|
single ID field that provides a unique identifier. Pod4 does not care what it's called or what data
|
202
|
-
type it is -- if you say that's what makes it unique, that's good enough.
|
203
|
+
type it is -- if you say that's what makes it unique, that's good enough. Additionally you can
|
204
|
+
specify whether your key autoincrements or not. If you don't say, we assume that it does.
|
203
205
|
|
204
206
|
Internally, Interfaces talk the same basic language of list / create / read / update / delete that
|
205
|
-
models do.
|
206
|
-
for your Interface definition.
|
207
|
+
models do. Sometimes you might want to add a special interface method for a specific database
|
208
|
+
operation, but otherwise that's probably going to be it for your Interface definition.
|
207
209
|
|
208
210
|
### Model ###
|
209
211
|
|
@@ -214,14 +216,16 @@ Models have two of their own DSLish methods:
|
|
214
216
|
|
215
217
|
You can see that interfaces are instantiated when the model is required. Exactly what you need to
|
216
218
|
pass to the interface to instantiate it depends on the interface. SequelInterface wants the Sequel
|
217
|
-
DB object
|
218
|
-
|
219
|
+
DB object; the other interfaces only want connection hashes.
|
220
|
+
|
221
|
+
(If you are finding it annoying to have to, for example, figure out your database connection hash
|
222
|
+
or get a Sequel DB object _before_ requiring your models, then see "Connections", below.)
|
219
223
|
|
220
224
|
Any attributes you define using `attr_columns` are treated specially by Pod4::Model. You get all
|
221
225
|
the effect of the standard Ruby `attr_accessor` call, but in addition, the attribute will be passed
|
222
226
|
to and from the interface, and to and from your external code, by the standard model methods.
|
223
227
|
|
224
|
-
In addition to the
|
228
|
+
In addition to the methods above, we have:
|
225
229
|
|
226
230
|
* `validate` -- override this to provide validation
|
227
231
|
* `map_to_model` -- controls how the interface sets attributes on the model
|
@@ -231,7 +235,7 @@ In addition to the ones above, we have:
|
|
231
235
|
A model also has some built-in attributes of its own:
|
232
236
|
|
233
237
|
* `model_id` -- this is the value of the ID column you set in the interface.
|
234
|
-
* `model_status` -- one of :error :warning :okay :deleted :
|
238
|
+
* `model_status` -- one of :error :warning :okay :deleted :unknown
|
235
239
|
|
236
240
|
We'll deal with all these below.
|
237
241
|
|
@@ -240,11 +244,12 @@ Adding Validation
|
|
240
244
|
-----------------
|
241
245
|
|
242
246
|
Built into the model is an array of alerts (Pod4::Alert) which are messages that have been raised
|
243
|
-
against the instance of the model class. Each alert can have a
|
244
|
-
:success. If any alert has a
|
245
|
-
|
247
|
+
against the instance of the model class. Each alert can have a type of :error, :warning, :info or
|
248
|
+
:success. If any alert has a type of :error or :warning, then that is reflected in the model's
|
249
|
+
`model_status` attribute. A model that has passed validation with no :error or :warning alerts is
|
250
|
+
status :okay.
|
246
251
|
|
247
|
-
(
|
252
|
+
(There are two other possible statuses -- models are :unknown when validation has yet to be run,
|
248
253
|
and :deleted after a call to delete.)
|
249
254
|
|
250
255
|
You can raise alerts yourself, and you normally do so by overriding `validate`. This method is
|
@@ -259,7 +264,7 @@ Here's a model with some validation:
|
|
259
264
|
class CustomerInterface < Pod4::PgInterface
|
260
265
|
set_schema :pod4example
|
261
266
|
set_table :customer
|
262
|
-
set_id_fld :id
|
267
|
+
set_id_fld :id, autoincrement: true
|
263
268
|
end
|
264
269
|
|
265
270
|
set_interface CustomerInterface.new($pg_conn)
|
@@ -287,7 +292,7 @@ the validation will fail. (Probably you do not want this on delete; test the pa
|
|
287
292
|
to validate as in the example above).
|
288
293
|
|
289
294
|
In passing I should note that validation is _not_ run on list: every record that list returns
|
290
|
-
should be complete, but the `model_status` will be :
|
295
|
+
should be complete, but the `model_status` will be :unknown because validation has not been run.
|
291
296
|
(This is partly for the sake of speed.)
|
292
297
|
|
293
298
|
You should be aware that validation is not called on `set`, either. Because of that, it's entirely
|
@@ -304,16 +309,16 @@ datatimes should all end up as the right type in the model. (It depends on the
|
|
304
309
|
going to get tired of me saying that, aren't you?) But maybe you want more than that.
|
305
310
|
|
306
311
|
Let's imagine you have a database table in PostreSQL with a column called cost that uses the money
|
307
|
-
type. And you want it to be a `BigDecimal` in the model.
|
308
|
-
all I know someone might have a problem with my requiring
|
309
|
-
yourself.
|
312
|
+
type. (This is a terrible idea, by the way.) And you want it to be a `BigDecimal` in the model.
|
313
|
+
Well, Pod4 won't do that for you -- for all I know someone might have a problem with my requiring
|
314
|
+
BigDecimal -- but it's not hard to do yourself.
|
310
315
|
|
311
316
|
class Product < Pod4::Model
|
312
317
|
|
313
318
|
class ProductInterface < Pod4::PgInterface
|
314
319
|
set_schema :pod4example
|
315
320
|
set_table :product
|
316
|
-
set_id_fld :product_id
|
321
|
+
set_id_fld :product_id, autoincrement: true
|
317
322
|
end
|
318
323
|
|
319
324
|
set_interface ProductInterface.new($pg_conn)
|
@@ -340,7 +345,8 @@ interface from the model. It _returns_ an Octothorpe to the interface. By defaul
|
|
340
345
|
You might also want to ensure that your data types are honoured when your application updates a
|
341
346
|
model object; in which case you will need to override `set` as well.
|
342
347
|
|
343
|
-
|
348
|
+
If this seems like a lot of work, take a look at the Pod4::TypeCasting mixin. it will handle it for
|
349
|
+
you.
|
344
350
|
|
345
351
|
|
346
352
|
Relations
|
@@ -352,7 +358,7 @@ Pod4 does not provide relations. But, I'm not sure that it needs to. Look:
|
|
352
358
|
|
353
359
|
class BlogPostInterface < Pod4::PgInterface
|
354
360
|
set_table :blogpost
|
355
|
-
set_id_fld :id
|
361
|
+
set_id_fld :id, autoincrement: true
|
356
362
|
end
|
357
363
|
|
358
364
|
set_interface BlogPostInterface.new($conn)
|
@@ -396,7 +402,7 @@ If your interface is connected to a SQL database, it should provide two more met
|
|
396
402
|
|
397
403
|
class BlogPostInterface < Pod4::PgInterface
|
398
404
|
set_table :blogpost
|
399
|
-
set_id_fld :id
|
405
|
+
set_id_fld :id, autoincrement: true
|
400
406
|
end
|
401
407
|
|
402
408
|
set_interface BlogPostInterface.new($conn)
|
@@ -434,12 +440,110 @@ certainly need revisiting if you change database. But how often does that happen
|
|
434
440
|
it ever does, you are likely to need to revisit the effected models anyway...
|
435
441
|
|
436
442
|
|
443
|
+
Connections
|
444
|
+
-----------
|
445
|
+
|
446
|
+
### A Couple Of Wrinkles ###
|
447
|
+
|
448
|
+
There are a couple of weird wrinkles in all this which you may or may not have missed. Wrinkle
|
449
|
+
one:
|
450
|
+
|
451
|
+
class MyModel < Pod4::Model
|
452
|
+
|
453
|
+
class Interface < Pod4::PgInterface
|
454
|
+
set_id_fld :id, autoincrement: true
|
455
|
+
set_table :my_table
|
456
|
+
end
|
457
|
+
|
458
|
+
set_interface Interface.new($pgconn) # <- wrinkle
|
459
|
+
attr_columns :one, two, three
|
460
|
+
end
|
461
|
+
|
462
|
+
You _instantiate_ the interface at the point where you _define_ the model. I admit this is a
|
463
|
+
little odd. It wasn't a specific design decision on my part; rather it was the cleanest way to get
|
464
|
+
where I was going.
|
465
|
+
|
466
|
+
In practice this means you need to get your DB connection details from somewhere, maybe create your
|
467
|
+
Sequel DB object; and only then can you require your models.
|
468
|
+
|
469
|
+
Leading on from this, wrinkle two: except when using Sequel (which behaves differently) each
|
470
|
+
interface has its own connection to the database. This means that your application has (simplifying
|
471
|
+
a bit here) one database connection for each model class. So if you have a Customer model and a
|
472
|
+
Orders model, your application will hold two connections to the database. All customer enquiries
|
473
|
+
share a single connection, and all order enquiries share a single connection.
|
474
|
+
|
475
|
+
I'm finding that, generally, this scales about right. But if you have a lot of different models and a
|
476
|
+
database that runs out of connections easily, it might be problematic.
|
477
|
+
|
478
|
+
### The Connection Object ###
|
479
|
+
|
480
|
+
The solution to both of these wrinkles, if you need one, is to use a Pod4::Connection object:
|
481
|
+
|
482
|
+
#
|
483
|
+
# init.rb -- bootup for my project
|
484
|
+
#
|
485
|
+
|
486
|
+
# Require libraries
|
487
|
+
require "sequel"
|
488
|
+
require "pod4"
|
489
|
+
require "pod4/sequel_interface"
|
490
|
+
require "pod4/connection"
|
491
|
+
|
492
|
+
# require models
|
493
|
+
$conn = Pod4::Connection.new(interface: Pod4::SequelInterface)
|
494
|
+
require_relative "models/customer"
|
495
|
+
|
496
|
+
# set up database connection
|
497
|
+
hash = get_sequel_params
|
498
|
+
$conn.data_layer_options = Sequel.connect(hash)
|
499
|
+
|
500
|
+
#############
|
501
|
+
|
502
|
+
#
|
503
|
+
# models/customer.rb ( only a part shown)
|
504
|
+
#
|
505
|
+
|
506
|
+
class Foo < Pod4::Model
|
507
|
+
class Interface < Pod4::SequelInterface
|
508
|
+
set_table :foo
|
509
|
+
set_id_field :id, autoincrement: true
|
510
|
+
end
|
511
|
+
|
512
|
+
set_interface Interface.new($conn)
|
513
|
+
|
514
|
+
TL;DR: the only code that needs to go in the middle of your requires is the line defining a
|
515
|
+
Connection object; you pass that to the interface instead. You can set up the parameters
|
516
|
+
the interface needs and pass them to the connection object afterwards.
|
517
|
+
|
518
|
+
With TdsInterface and PgInterface you can pass the same connection to multiple models and they will
|
519
|
+
share it. These interfaces take a Pod4::ConnectionPool instead, but otherwise the code looks
|
520
|
+
exactly the same as the above example.
|
521
|
+
|
522
|
+
(Technical note: the ConnectionPool object will actually provide multiple connections, one per
|
523
|
+
thread that uses it. This satisfies the requirement of the underlying libraries that connections
|
524
|
+
are not shared between threads, and therefore ensures that Pod4 is more or less thread safe. You
|
525
|
+
get this functionality automatically -- if you don't define a ConnectionPool, then the interface
|
526
|
+
will create one internally. Sequel uses its own thread pool, of course, and we only use the one
|
527
|
+
Sequel DB object for the whole of Pod4, so it doesn't need any of that. That's why it uses
|
528
|
+
Pod4::Connection, instead.)
|
529
|
+
|
530
|
+
|
437
531
|
BasicModel
|
438
532
|
----------
|
439
533
|
|
440
534
|
Sometimes your model needs to represent data in a way which is so radically different from the data
|
441
535
|
source that the whole list, create, read, update, delete thing that Pod4::Model gives you is no
|
442
|
-
use.
|
536
|
+
use.
|
537
|
+
|
538
|
+
Pod4::BasicModel gives you:
|
539
|
+
|
540
|
+
* `set_interface`
|
541
|
+
* the `model_id`, `model_status` and `alerts` attributes
|
542
|
+
* `add_alert`
|
543
|
+
|
544
|
+
...and nothing else. But that's enough to make a model, your way, using the methods on the
|
545
|
+
interface. These are the same CRUDL methods that Pod4::Model provides -- except that on the
|
546
|
+
interface, the CRUD methods take a record id as a key.
|
443
547
|
|
444
548
|
A real world example: at James Hall my intranet system has a User model, where each attribute is a
|
445
549
|
parameter that controls how the system behaves for that user -- email address, security settings,
|
@@ -450,16 +554,6 @@ add a user parameter. The logical place to change the parameter is in the User m
|
|
450
554
|
database, and certainly not both. So on the database, I have a settings table where the key runs:
|
451
555
|
userid, setting name.
|
452
556
|
|
453
|
-
Pod4::BasicModel gives you:
|
454
|
-
|
455
|
-
* `set_interface`
|
456
|
-
* the `model_id`, `model_status` and `alerts` attributes
|
457
|
-
* `add_alert`
|
458
|
-
|
459
|
-
...and nothing else. But that's enough to make a model, your way, using the methods on the
|
460
|
-
interface. These are the same CRUDL methods that Pod4::Model provides -- except that the CRUD
|
461
|
-
methods take a record id as a key.
|
462
|
-
|
463
557
|
Here's a simplified version of my User model. This one is read only, but it's hopefully enough to
|
464
558
|
get the idea:
|
465
559
|
|
@@ -467,10 +561,9 @@ get the idea:
|
|
467
561
|
|
468
562
|
class UserInterface < ::Pod4::SequelInterface
|
469
563
|
set_table :settings
|
470
|
-
set_id_fld :id
|
564
|
+
set_id_fld :id, autoincrement: false
|
471
565
|
end
|
472
566
|
|
473
|
-
|
474
567
|
# Here we set what settings always exist for a user
|
475
568
|
Setting = Struct.new(:setName, :default)
|
476
569
|
|
@@ -485,19 +578,14 @@ get the idea:
|
|
485
578
|
set_interface UserInterface.new($db)
|
486
579
|
attr_reader :userid, :depot, :store, :menu, :roles, :name, :nick, :mail
|
487
580
|
|
488
|
-
|
489
581
|
class << self
|
490
|
-
|
491
582
|
def keys; DefaultSettings.map{|x| x.setName }; end
|
492
583
|
|
493
584
|
def list
|
494
585
|
array = interface.select(%Q|select distinct userid from settings;|)
|
495
586
|
array.map {|r| self.new( r[:userid] ).read }
|
496
587
|
end
|
497
|
-
|
498
|
-
end
|
499
|
-
##
|
500
|
-
|
588
|
+
end # of class << self
|
501
589
|
|
502
590
|
def initialize(userid=nil)
|
503
591
|
super(userid)
|
@@ -507,7 +595,6 @@ get the idea:
|
|
507
595
|
end
|
508
596
|
end
|
509
597
|
|
510
|
-
|
511
598
|
def read
|
512
599
|
lst = interface.list(userid: @model_id)
|
513
600
|
|
@@ -517,12 +604,11 @@ get the idea:
|
|
517
604
|
|
518
605
|
@userid = @model_id
|
519
606
|
set_merge( Octothorpe.new(data) )
|
520
|
-
validate; @model_status = :okay unless @model_status != :
|
607
|
+
validate; @model_status = :okay unless @model_status != :unknown
|
521
608
|
|
522
609
|
self
|
523
610
|
end
|
524
611
|
|
525
|
-
|
526
612
|
def to_ot
|
527
613
|
hash = self.class.keys.each_with_object({}) do |k,m|
|
528
614
|
m[k] = instance_variable_get("@#{k}".to_sym)
|
@@ -531,7 +617,6 @@ get the idea:
|
|
531
617
|
Octothorpe.new(hash)
|
532
618
|
end
|
533
619
|
|
534
|
-
|
535
620
|
def set_merge(hash)
|
536
621
|
self.class.keys.each do |key|
|
537
622
|
value = hash[key]
|
@@ -541,11 +626,37 @@ get the idea:
|
|
541
626
|
|
542
627
|
end
|
543
628
|
|
629
|
+
|
544
630
|
Extensions
|
545
631
|
----------
|
546
632
|
|
547
|
-
There are
|
633
|
+
There are some mixins that you can use to extend the functionality of Pod4 models. Have a look
|
548
634
|
at the comments at the top of the mixin in question if you want details.
|
549
635
|
|
550
636
|
* typecasting -- force columns to be a specific ruby type, validation helpers, some encoding stuff
|
551
637
|
* encrypting -- encrypt text columns
|
638
|
+
* tweaking -- adds DSL commands to support custom methods on the interface.
|
639
|
+
|
640
|
+
|
641
|
+
Gotchas
|
642
|
+
-------
|
643
|
+
|
644
|
+
Some hopefully-not-too-unexpected behaviour:
|
645
|
+
|
646
|
+
* If you change attributes on a record, then call #delete or #read on it, we don't warn you that
|
647
|
+
your changes are lost.
|
648
|
+
|
649
|
+
* If you attempt to update an autoincrement ID field, we don't write that change to the database
|
650
|
+
and we don't warn you about that.
|
651
|
+
|
652
|
+
* As mentioned above, we only run validate on #create, #read, #update and #delete. So you can
|
653
|
+
change the attributes of a record to something invalid without it immediately warning you. (You
|
654
|
+
can always run #validate yourself, though.)
|
655
|
+
|
656
|
+
* Again, as mentioned above, the array of model instances returned by #list will all be status
|
657
|
+
:unknown. This is because we have run neither #read nor #validate against them.
|
658
|
+
|
659
|
+
* I can't stop you writing to `@model_id` or `@model_status` in your model. I have no idea what
|
660
|
+
might happen if you do, but I doubt that it would ever be a good idea. (In a non-autoincrement
|
661
|
+
model, write to your ID field directly instead; `@model_id` will be updated when you call
|
662
|
+
#create, #update or of course #read.)
|