chrono_model 1.2.2 → 3.0.1

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.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +19 -20
  3. data/README.md +73 -62
  4. data/lib/active_record/connection_adapters/chronomodel_adapter.rb +14 -14
  5. data/lib/active_record/tasks/chronomodel_database_tasks.rb +40 -39
  6. data/lib/chrono_model/adapter/ddl.rb +168 -153
  7. data/lib/chrono_model/adapter/indexes.rb +99 -94
  8. data/lib/chrono_model/adapter/migrations.rb +81 -104
  9. data/lib/chrono_model/adapter/migrations_modules/stable.rb +41 -0
  10. data/lib/chrono_model/adapter/tsrange.rb +20 -5
  11. data/lib/chrono_model/adapter/upgrade.rb +89 -91
  12. data/lib/chrono_model/adapter.rb +59 -31
  13. data/lib/chrono_model/chrono.rb +17 -0
  14. data/lib/chrono_model/conversions.rb +14 -8
  15. data/lib/chrono_model/db_console.rb +5 -0
  16. data/lib/chrono_model/patches/as_of_time_holder.rb +2 -2
  17. data/lib/chrono_model/patches/as_of_time_relation.rb +3 -13
  18. data/lib/chrono_model/patches/association.rb +15 -12
  19. data/lib/chrono_model/patches/batches.rb +13 -0
  20. data/lib/chrono_model/patches/db_console.rb +20 -4
  21. data/lib/chrono_model/patches/join_node.rb +4 -4
  22. data/lib/chrono_model/patches/preloader.rb +41 -11
  23. data/lib/chrono_model/patches/relation.rb +51 -8
  24. data/lib/chrono_model/patches.rb +3 -1
  25. data/lib/chrono_model/railtie.rb +13 -27
  26. data/lib/chrono_model/time_gate.rb +3 -3
  27. data/lib/chrono_model/time_machine/history_model.rb +65 -31
  28. data/lib/chrono_model/time_machine/time_query.rb +65 -49
  29. data/lib/chrono_model/time_machine/timeline.rb +52 -28
  30. data/lib/chrono_model/time_machine.rb +57 -25
  31. data/lib/chrono_model/utilities.rb +3 -3
  32. data/lib/chrono_model/version.rb +3 -1
  33. data/lib/chrono_model.rb +31 -36
  34. metadata +24 -263
  35. data/.gitignore +0 -21
  36. data/.rspec +0 -2
  37. data/.travis.yml +0 -41
  38. data/Gemfile +0 -4
  39. data/README.sql +0 -161
  40. data/Rakefile +0 -25
  41. data/chrono_model.gemspec +0 -33
  42. data/gemfiles/rails_5.0.gemfile +0 -6
  43. data/gemfiles/rails_5.1.gemfile +0 -6
  44. data/gemfiles/rails_5.2.gemfile +0 -6
  45. data/lib/chrono_model/json.rb +0 -28
  46. data/spec/aruba/dbconsole_spec.rb +0 -25
  47. data/spec/aruba/fixtures/database_with_default_username_and_password.yml +0 -14
  48. data/spec/aruba/fixtures/database_without_username_and_password.yml +0 -11
  49. data/spec/aruba/fixtures/empty_structure.sql +0 -27
  50. data/spec/aruba/fixtures/migrations/56/20160812190335_create_impressions.rb +0 -10
  51. data/spec/aruba/fixtures/migrations/56/20171115195229_add_temporal_extension_to_impressions.rb +0 -10
  52. data/spec/aruba/fixtures/railsapp/config/application.rb +0 -17
  53. data/spec/aruba/fixtures/railsapp/config/boot.rb +0 -5
  54. data/spec/aruba/fixtures/railsapp/config/environments/development.rb +0 -38
  55. data/spec/aruba/migrations_spec.rb +0 -48
  56. data/spec/aruba/rake_task_spec.rb +0 -71
  57. data/spec/chrono_model/adapter/base_spec.rb +0 -157
  58. data/spec/chrono_model/adapter/ddl_spec.rb +0 -243
  59. data/spec/chrono_model/adapter/indexes_spec.rb +0 -72
  60. data/spec/chrono_model/adapter/migrations_spec.rb +0 -312
  61. data/spec/chrono_model/conversions_spec.rb +0 -43
  62. data/spec/chrono_model/history_models_spec.rb +0 -32
  63. data/spec/chrono_model/json_ops_spec.rb +0 -59
  64. data/spec/chrono_model/time_machine/as_of_spec.rb +0 -188
  65. data/spec/chrono_model/time_machine/changes_spec.rb +0 -50
  66. data/spec/chrono_model/time_machine/counter_cache_race_spec.rb +0 -46
  67. data/spec/chrono_model/time_machine/default_scope_spec.rb +0 -37
  68. data/spec/chrono_model/time_machine/history_spec.rb +0 -104
  69. data/spec/chrono_model/time_machine/keep_cool_spec.rb +0 -27
  70. data/spec/chrono_model/time_machine/manipulations_spec.rb +0 -84
  71. data/spec/chrono_model/time_machine/model_identification_spec.rb +0 -46
  72. data/spec/chrono_model/time_machine/sequence_spec.rb +0 -74
  73. data/spec/chrono_model/time_machine/sti_spec.rb +0 -100
  74. data/spec/chrono_model/time_machine/time_query_spec.rb +0 -261
  75. data/spec/chrono_model/time_machine/timeline_spec.rb +0 -63
  76. data/spec/chrono_model/time_machine/timestamps_spec.rb +0 -43
  77. data/spec/chrono_model/time_machine/transactions_spec.rb +0 -69
  78. data/spec/config.travis.yml +0 -5
  79. data/spec/config.yml.example +0 -9
  80. data/spec/spec_helper.rb +0 -33
  81. data/spec/support/adapter/helpers.rb +0 -53
  82. data/spec/support/adapter/structure.rb +0 -44
  83. data/spec/support/aruba.rb +0 -44
  84. data/spec/support/connection.rb +0 -70
  85. data/spec/support/matchers/base.rb +0 -56
  86. data/spec/support/matchers/column.rb +0 -99
  87. data/spec/support/matchers/function.rb +0 -79
  88. data/spec/support/matchers/index.rb +0 -69
  89. data/spec/support/matchers/schema.rb +0 -39
  90. data/spec/support/matchers/table.rb +0 -275
  91. data/spec/support/time_machine/helpers.rb +0 -47
  92. data/spec/support/time_machine/structure.rb +0 -111
  93. data/sql/json_ops.sql +0 -56
  94. data/sql/uninstall-json_ops.sql +0 -24
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fa9d6f8ee80241092713836e372cf3cb568639e403511ba2c48ba33275f6c1a8
4
- data.tar.gz: '055794bce8014501e3eea0a180abe04278f1aba62015d3f5b98d75499c6faba1'
3
+ metadata.gz: 222db0e6673e7171d44dac2163b5048ebf6b459c18fa2a2609a3051fce8c6591
4
+ data.tar.gz: 871fdf28717c85267e6b783f1f2d6ba3a24b1261e974e53a25de28d745bc8579
5
5
  SHA512:
6
- metadata.gz: 380cbab091ab178aea031fee4e8343797a5e461e98b233a8c732b7cc0f9bd584497fa3b1bcc8703f6d8b74b972aeed2a257f6aba9ca7a2d932b4e72e7c211506
7
- data.tar.gz: c601c91ce05f426aef3c75b37ba9920170666523abff9b219ab09816e6c17f42146131d5ffcc89d233d5d7ec94d6ac5592e6a8160dd8207b9a48c3ff51feb629
6
+ metadata.gz: 0bf942259052f134ea38de898307a65f20a6b448d8e8ff99a09ae06cd751f9834e1eb22abd4498c880005b8fc91f44ecebea4702be8c174570c50027dce13a75
7
+ data.tar.gz: 2b894f82a0cb9687d59dca9c3427a854cf6dc02191a08df71a215dfc577a8d1dd58632d44eb179395f097aa7d2391a7c738968d0f4c68f16cc14fffd2d18e034
data/LICENSE CHANGED
@@ -1,24 +1,23 @@
1
- Copyright (c) 2012-2014 Marcello Barnaba <m.barnaba@ifad.org>
2
- Copyright (c) 2012-2014 Peter J. Brindisi <p.brindisi@ifad.org>
3
- Copyright (c) 2012-2014 IFAD
4
-
5
1
  MIT License
6
2
 
7
- Permission is hereby granted, free of charge, to any person obtaining
8
- a copy of this software and associated documentation files (the
9
- "Software"), to deal in the Software without restriction, including
10
- without limitation the rights to use, copy, modify, merge, publish,
11
- distribute, sublicense, and/or sell copies of the Software, and to
12
- permit persons to whom the Software is furnished to do so, subject to
13
- the following conditions:
3
+ Copyright (c) 2012-2024 Marcello Barnaba <m.barnaba@ifad.org>
4
+ Copyright (c) 2012-2024 Peter J. Brindisi <p.brindisi@ifad.org>
5
+ Copyright (c) 2012-2024 IFAD
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
14
13
 
15
- The above copyright notice and this permission notice shall be
16
- included in all copies or substantial portions of the Software.
14
+ The above copyright notice and this permission notice shall be included in all
15
+ copies or substantial portions of the Software.
17
16
 
18
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ SOFTWARE.
data/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  [![Gem Version][gem-version-badge]][gem-version]
7
7
  [![Inlinedocs][docs-analysis-badge]][docs-analysis]
8
8
 
9
- ![{A Delorean that we all love}][delorean-image]
9
+ ![A Delorean that we all love][delorean-image]
10
10
 
11
11
  ChronoModel implements what Oracle sells as "Flashback Queries", with standard
12
12
  SQL on free PostgreSQL. Academically speaking, ChronoModel implements a
@@ -62,9 +62,9 @@ All timestamps are _forcibly_ stored in as UTC, bypassing the
62
62
 
63
63
  ## Requirements
64
64
 
65
- * Ruby >= 2.3
66
- * Active Record >= 5.0. See the [detailed supported versions matrix on travis](https://travis-ci.org/ifad/chronomodel)
67
- * PostgreSQL >= 9.4 (legacy support for 9.3)
65
+ * Ruby >= 3.0
66
+ * Active Record >= 7.0. See the [detailed supported versions matrix on Ruby GitHub Actions workflows](https://github.com/ifad/chronomodel/blob/master/.github/workflows)
67
+ * PostgreSQL >= 9.4
68
68
  * The `btree_gist` PostgreSQL extension
69
69
 
70
70
  With Homebrew:
@@ -96,6 +96,13 @@ development:
96
96
  username: ...
97
97
  ```
98
98
 
99
+ Configure Active Record in your `config/application.rb` to use the `:sql` schema
100
+ format:
101
+
102
+ ```rb
103
+ config.active_record.schema_format = :sql
104
+ ```
105
+
99
106
  ## Schema creation
100
107
 
101
108
  ChronoModel hooks all `ActiveRecord::Migration` methods to make them temporal
@@ -141,7 +148,7 @@ validity from midnight, January 1st, 1 CE. You can set a specific validity with
141
148
  the `:validity` option:
142
149
 
143
150
  ```ruby
144
- change_table :your_table, :temporal => true, :copy_data => true, :validity => '1977-01-01'
151
+ change_table :your_table, temporal: true, copy_data: true, validity: '1977-01-01'
145
152
  ```
146
153
 
147
154
  Please note that `change_table` requires you to use *old_style* `up` and
@@ -156,9 +163,9 @@ history.
156
163
  You can also choose which fields are to be journaled, passing the following
157
164
  options to `create_table`:
158
165
 
159
- * `:journal => %w( fld1 fld2 .. .. )` - record changes in the history only when changing specified fields
160
- * `:no_journal => %w( fld1 fld2 .. )` - do not record changes to the specified fields
161
- * `:full_journal => true` - record changes to *all* fields, including `updated_at`.
166
+ * `journal: %w( fld1 fld2 .. .. )` - record changes in the history only when changing specified fields
167
+ * `no_journal: %w( fld1 fld2 .. )` - do not record changes to the specified fields
168
+ * `full_journal: true` - record changes to *all* fields, including `updated_at`.
162
169
 
163
170
  These options are stored as JSON in the [COMMENT][pg-comment] area of the
164
171
  public view, alongside with the ChronoModel version that created them.
@@ -195,7 +202,7 @@ to your `create_table`. Example:
195
202
  Include the `ChronoModel::TimeMachine` module in your model.
196
203
 
197
204
  ```ruby
198
- module Country < ActiveRecord::Base
205
+ class Country < ActiveRecord::Base
199
206
  include ChronoModel::TimeMachine
200
207
 
201
208
  has_many :compositions
@@ -310,31 +317,19 @@ only against ActiveRecord by using
310
317
 
311
318
  Ensure to run the full test suite before pushing.
312
319
 
313
- ## Usage with JSON (*not* JSONB) columns
314
-
315
- **DEPRECATED**: Please migrate to JSONB. It has an equality operator built-in,
316
- it's faster and stricter, and offers many more indexing abilities and better
317
- performance than JSON. It is going to be desupported soon because PostgreSQL 10
318
- does not support these anymore.
319
-
320
- The [JSON][pg-json-type] does not provide an [equality operator][pg-json-func].
321
- As both unnecessary update suppression and selective journaling require
322
- comparing the OLD and NEW rows fields, this fails by default.
323
-
324
- ChronoModel provides a naive and heavyweight JSON equality operator using
325
- [pl/python][pg-json-opclass] and associated Postgres objects.
326
-
327
- To set up you can use
328
-
329
- ```ruby
330
- require 'chrono_model/json'
331
- ChronoModel::Json.create
332
- ```
333
-
334
320
  ## Caveats
335
321
 
322
+ * Considering the nature of modern applications, it's crucial to understand
323
+ that the database time does not necessarily align with the application time
324
+ due to the delay introduced by communication between the application and
325
+ the database server. Consequently, there is no assurance that the application
326
+ time will always be less than the database time. Therefore, relying solely
327
+ on `created_at` and `updated_at` fields as timestamps to determine the state
328
+ of an object at a specific point in time within the application could
329
+ lead to inaccuracies.
330
+
336
331
  * Rails 4+ support requires disabling tsrange parsing support, as it
337
- [is broken][r4-tsrange-broken] and [incomplete][r4-tsrange-incomplete]
332
+ [is broken][r4-tsrange-broken] and [incomplete][r4-tsrange-incomplete]
338
333
  as of now, mainly due to a [design clash with ruby][pg-tsrange-and-ruby].
339
334
 
340
335
  * The triggers and temporal indexes cannot be saved in schema.rb. The AR
@@ -345,14 +340,27 @@ ChronoModel::Json.create
345
340
  `db:structure:load`.
346
341
  Two helper tasks are also added, `db:data:dump` and `db:data:load`.
347
342
 
348
- * The choice of using subqueries instead of [Common Table Expressions]
349
- [pg-ctes] was dictated by the fact that CTEs [currently act as an
350
- optimization fence][pg-cte-optimization-fence].
343
+ * The choice of using subqueries instead of [Common Table Expressions][pg-ctes]
344
+ was dictated by the fact that CTEs [currently act as an optimization
345
+ fence][pg-cte-optimization-fence].
351
346
  If it will be possible [to opt-out of the fence][pg-cte-opt-out-fence]
352
347
  in the future, they will be probably be used again as they were [in the
353
348
  past][cm-cte-impl], because the resulting queries were more readable,
354
349
  and do not inhibit using `.from()` on the `AR::Relation`.
355
350
 
351
+ * Foreign keys are not supported. [See issue #174][gh-issue-174]
352
+
353
+ * There may be unexpected results when combining eager loading and joins.
354
+ [See issue #186][gh-issue-186]
355
+
356
+ * Global ID ignores historical objects. [See issue #192][gh-issue-192]
357
+
358
+ * Different historical objects are considered the identical. [See issue
359
+ #206][gh-issue-206]
360
+
361
+ * Use with caution when implementing inline editing features, as Chronomodel
362
+ creates a new record for each modification. This will lead to increased
363
+ storage requirements and bloated history
356
364
 
357
365
  ## Contributing
358
366
 
@@ -376,41 +384,40 @@ while using it in many important projects.
376
384
  This software is Made in Italy :it: :smile:.
377
385
 
378
386
 
379
- [build-status]: https://travis-ci.org/ifad/chronomodel
380
- [build-status-badge]: https://travis-ci.org/ifad/chronomodel.svg
381
- [code-analysis]: https://codeclimate.com/github/ifad/chronomodel
382
- [code-analysis-badge]: https://codeclimate.com/github/ifad/chronomodel.svg
383
- [docs-analysis]: http://inch-ci.org/github/ifad/chronomodel
384
- [docs-analysis-badge]: http://inch-ci.org/github/ifad/chronomodel.svg?branch=master
387
+ [build-status]: https://github.com/ifad/chronomodel/actions
388
+ [build-status-badge]: https://github.com/ifad/chronomodel/actions/workflows/ruby.yml/badge.svg
389
+ [code-analysis]: https://codeclimate.com/github/ifad/chronomodel/maintainability
390
+ [code-analysis-badge]: https://api.codeclimate.com/v1/badges/cdee7327938dc2eaff99/maintainability
391
+ [docs-analysis]: https://inch-ci.org/github/ifad/chronomodel
392
+ [docs-analysis-badge]: https://inch-ci.org/github/ifad/chronomodel.svg?branch=master
385
393
  [gem-version]: https://rubygems.org/gems/chrono_model
386
394
  [gem-version-badge]: https://badge.fury.io/rb/chrono_model.svg
387
395
  [test-coverage]: https://codeclimate.com/github/ifad/chronomodel
388
396
  [test-coverage-badge]: https://codeclimate.com/github/ifad/chronomodel/badges/coverage.svg
389
397
 
390
398
  [delorean-image]: https://i.imgur.com/DD77F4s.jpg
391
- [rebelle-society]: http://www.rebellesociety.com/2012/10/11/the-writers-way-week-two-facing-procrastination/chronos_oeuvre_grand1/
392
-
393
- [wp-scd-2]: http://en.wikipedia.org/wiki/Slowly_changing_dimension#Type_2
394
- [wp-scd-4]: http://en.wikipedia.org/wiki/Slowly_changing_dimension#Type_4
395
-
396
- [pg-updatable-views]: http://www.postgresql.org/docs/9.4/static/sql-createview.html#SQL-CREATEVIEW-UPDATABLE-VIEWS
397
- [pg-table-inheritance]: http://www.postgresql.org/docs/9.4/static/ddl-inherit.html
398
- [pg-instead-of-triggers]: http://www.postgresql.org/docs/9.4/static/sql-createtrigger.html
399
- [pg-triggers]: http://www.postgresql.org/docs/9.4/static/trigger-definition.html
400
- [pg-schema]: http://www.postgresql.org/docs/9.4/static/ddl-schemas.html
401
- [pg-current-timestamp]: http://www.postgresql.org/docs/9.4/interactive/functions-datetime.html#FUNCTIONS-DATETIME-TABLE
402
- [pg-partitioning]: http://www.postgresql.org/docs/9.4/static/ddl-partitioning.html
403
- [pg-partitioning-excl-constraints]: http://www.postgresql.org/docs/9.4/static/ddl-partitioning.html#DDL-PARTITIONING-CONSTRAINT-EXCLUSION
404
- [pg-gist-indexes]: http://www.postgresql.org/docs/9.4/static/gist.html
405
- [pg-exclusion-constraints]: http://www.postgresql.org/docs/9.4/static/sql-createtable.html#SQL-CREATETABLE-EXCLUDE
406
- [pg-btree-gist]: http://www.postgresql.org/docs/9.4/static/btree-gist.html
407
- [pg-comment]: http://www.postgresql.org/docs/9.4/static/sql-comment.html
399
+
400
+ [wp-scd-2]: https://en.wikipedia.org/wiki/Slowly_changing_dimension#Type_2
401
+ [wp-scd-4]: https://en.wikipedia.org/wiki/Slowly_changing_dimension#Type_4
402
+
403
+ [pg-updatable-views]: https://www.postgresql.org/docs/9.4/sql-createview.html#SQL-CREATEVIEW-UPDATABLE-VIEWS
404
+ [pg-table-inheritance]: https://www.postgresql.org/docs/9.4/ddl-inherit.html
405
+ [pg-instead-of-triggers]: https://www.postgresql.org/docs/9.4/sql-createtrigger.html
406
+ [pg-triggers]: https://www.postgresql.org/docs/9.4/trigger-definition.html
407
+ [pg-schema]: https://www.postgresql.org/docs/9.4/ddl-schemas.html
408
+ [pg-current-timestamp]: https://www.postgresql.org/docs/9.4/functions-datetime.html#FUNCTIONS-DATETIME-TABLE
409
+ [pg-partitioning]: https://www.postgresql.org/docs/9.4/ddl-partitioning.html
410
+ [pg-partitioning-excl-constraints]: https://www.postgresql.org/docs/9.4/ddl-partitioning.html#DDL-PARTITIONING-CONSTRAINT-EXCLUSION
411
+ [pg-gist-indexes]: https://www.postgresql.org/docs/9.4/gist.html
412
+ [pg-exclusion-constraints]: https://www.postgresql.org/docs/9.4/sql-createtable.html#SQL-CREATETABLE-EXCLUDE
413
+ [pg-btree-gist]: https://www.postgresql.org/docs/9.4/btree-gist.html
414
+ [pg-comment]: https://www.postgresql.org/docs/9.4/sql-comment.html
408
415
  [pg-tsrange-and-ruby]: https://bugs.ruby-lang.org/issues/6864
409
- [pg-ctes]: http://www.postgresql.org/docs/9.4/static/queries-with.html
410
- [pg-cte-optimization-fence]: http://archives.postgresql.org/pgsql-hackers/2012-09/msg00700.php
411
- [pg-cte-opt-out-fence]: http://archives.postgresql.org/pgsql-hackers/2012-10/msg00024.php
412
- [pg-json-type]: http://www.postgresql.org/docs/9.4/static/datatype-json.html
413
- [pg-json-func]: http://www.postgresql.org/docs/9.4/static/functions-json.html
416
+ [pg-ctes]: https://www.postgresql.org/docs/9.4/queries-with.html
417
+ [pg-cte-optimization-fence]: https://www.postgresql.org/message-id/201209191305.44674.db@kavod.com
418
+ [pg-cte-opt-out-fence]: https://www.postgresql.org/message-id/CAHyXU0zpM5+Dsb_pKxDmm-ZoWUAt=SkHHaiK_DBqcmtxTas6Nw@mail.gmail.com
419
+ [pg-json-type]: https://www.postgresql.org/docs/9.4/datatype-json.html
420
+ [pg-json-func]: https://www.postgresql.org/docs/9.4/functions-json.html
414
421
  [pg-json-opclass]: https://github.com/ifad/chronomodel/blob/master/sql/json_ops.sql
415
422
 
416
423
  [r4-tsrange-broken]: https://github.com/rails/rails/pull/13793#issuecomment-34608093
@@ -421,3 +428,7 @@ This software is Made in Italy :it: :smile:.
421
428
  [cm-cte-impl]: https://github.com/ifad/chronomodel/commit/18f4c4b
422
429
 
423
430
  [gh-pzac]: https://github.com/pzac
431
+ [gh-issue-174]: https://github.com/ifad/chronomodel/issues/174
432
+ [gh-issue-186]: https://github.com/ifad/chronomodel/issues/186
433
+ [gh-issue-192]: https://github.com/ifad/chronomodel/issues/192
434
+ [gh-issue-206]: https://github.com/ifad/chronomodel/issues/206
@@ -1,16 +1,22 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'chrono_model'
2
4
 
3
5
  module ActiveRecord
6
+ # TODO: Remove when dropping Rails < 7.2 compatibility
4
7
  module ConnectionHandling
8
+ def chronomodel_adapter_class
9
+ ChronoModel::Adapter
10
+ end
5
11
 
6
12
  # Install the new adapter in ActiveRecord. This approach is required because
7
13
  # the PG adapter defines +add_column+ itself, thus making impossible to use
8
14
  # super() in overridden Module methods.
9
15
  #
10
16
  def chronomodel_connection(config) # :nodoc:
11
- conn_params = config.symbolize_keys
17
+ return chronomodel_adapter_class.new(config) if ActiveRecord::VERSION::STRING >= '7.1'
12
18
 
13
- conn_params.delete_if { |_, v| v.nil? }
19
+ conn_params = config.symbolize_keys.compact
14
20
 
15
21
  # Map ActiveRecords param names to PGs.
16
22
  conn_params[:user] = conn_params.delete(:username) if conn_params[:username]
@@ -20,24 +26,18 @@ module ActiveRecord
20
26
  valid_conn_param_keys = PG::Connection.conndefaults_hash.keys + [:requiressl]
21
27
  conn_params.slice!(*valid_conn_param_keys)
22
28
 
23
- # The postgres drivers don't allow the creation of an unconnected PG::Connection object,
24
- # so just pass a nil connection object for the time being.
25
- adapter = ChronoModel::Adapter.new(nil, logger, conn_params, config)
29
+ conn = PG.connect(conn_params)
30
+
31
+ adapter = ChronoModel::Adapter.new(conn, logger, conn_params, config)
26
32
 
27
33
  unless adapter.chrono_supported?
28
- raise ChronoModel::Error, "Your database server is not supported by ChronoModel. "\
29
- "Currently, only PostgreSQL >= 9.3 is supported."
34
+ raise ChronoModel::Error, 'Your database server is not supported by ChronoModel. ' \
35
+ 'Currently, only PostgreSQL >= 9.3 is supported.'
30
36
  end
31
37
 
32
38
  adapter.chrono_setup!
33
39
 
34
- return adapter
40
+ adapter
35
41
  end
36
-
37
- module Connectionadapters
38
- ChronoModelAdapter = ::ChronoModel::Adapter
39
- end
40
-
41
42
  end
42
43
  end
43
-
@@ -1,11 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Tasks
3
5
  class ChronomodelDatabaseTasks < PostgreSQLDatabaseTasks
6
+ CHRONOMODEL_SCHEMAS = [
7
+ ChronoModel::Adapter::TEMPORAL_SCHEMA,
8
+ ChronoModel::Adapter::HISTORY_SCHEMA
9
+ ].freeze
4
10
 
5
11
  def structure_dump(*arguments)
6
-
7
- with_chronomodel_schema_search_path do
8
- super(*arguments)
12
+ if schema_search_path.present?
13
+ with_chronomodel_schema_search_path { super }
14
+ else
15
+ super
9
16
  end
10
17
 
11
18
  # The structure.sql includes CREATE SCHEMA statements, but as these are executed
@@ -17,70 +24,64 @@ module ActiveRecord
17
24
  filename = arguments.first
18
25
  sql = File.read(filename).gsub(/CREATE SCHEMA (?!IF NOT EXISTS)/, '\&IF NOT EXISTS ')
19
26
  File.open(filename, 'w') { |file| file << sql }
20
-
21
- remove_sql_header_comments(filename)
22
27
  end
23
28
 
24
29
  def data_dump(target)
25
- set_psql_env
30
+ psql_env
26
31
 
27
- args = ['-c', '-f', target]
28
- args << configuration['database']
32
+ args = ['-c', '-f', target.to_s]
33
+ args << chronomodel_configuration[:database]
29
34
 
30
- run_cmd "pg_dump", args, 'dumping data'
35
+ run_cmd 'pg_dump', args, 'dumping data'
31
36
  end
32
37
 
33
38
  def data_load(source)
34
- set_psql_env
39
+ psql_env
35
40
 
36
41
  args = ['-f', source]
37
- args << configuration['database']
42
+ args << chronomodel_configuration[:database]
38
43
 
39
- run_cmd "psql", args, 'loading data'
44
+ run_cmd 'psql', args, 'loading data'
40
45
  end
41
46
 
42
47
  private
43
48
 
49
+ def chronomodel_configuration
50
+ @chronomodel_configuration ||= @configuration_hash
51
+ end
52
+
44
53
  # If a schema search path is defined in the configuration file, it will
45
54
  # be used by the database tasks class to dump only the specified search
46
55
  # path. Here we add also ChronoModel's temporal and history schemas to
47
56
  # the search path and yield.
48
57
  #
49
58
  def with_chronomodel_schema_search_path
50
- original_schema_search_path = configuration['schema_search_path']
51
-
52
- if original_schema_search_path.present?
53
- configuration['schema_search_path'] = original_schema_search_path.split(',').concat([
54
- ChronoModel::Adapter::TEMPORAL_SCHEMA,
55
- ChronoModel::Adapter::HISTORY_SCHEMA
56
- ]).join(',')
57
- end
59
+ patch_configuration!
58
60
 
59
61
  yield
60
-
61
62
  ensure
62
- configuration['schema_search_path'] = original_schema_search_path
63
+ reset_configuration!
63
64
  end
64
65
 
65
- unless method_defined? :remove_sql_header_comments
66
- def remove_sql_header_comments(filename)
67
- sql_comment_begin = '--'
68
- removing_comments = true
69
- tempfile = Tempfile.open("uncommented_structure.sql")
70
- begin
71
- File.foreach(filename) do |line|
72
- unless removing_comments && (line.start_with?(sql_comment_begin) || line.blank?)
73
- tempfile << line
74
- removing_comments = false
75
- end
76
- end
77
- ensure
78
- tempfile.close
79
- end
80
- FileUtils.mv(tempfile.path, filename)
81
- end
66
+ def patch_configuration!
67
+ @original_schema_search_path = schema_search_path
68
+
69
+ chronomodel_schema_search_path = "#{schema_search_path},#{CHRONOMODEL_SCHEMAS.join(',')}"
70
+
71
+ @configuration_hash = @configuration_hash.dup
72
+ @configuration_hash[:schema_search_path] = chronomodel_schema_search_path
73
+ @configuration_hash.freeze
82
74
  end
83
75
 
76
+ def reset_configuration!
77
+ @configuration_hash = @configuration_hash.dup
78
+ @configuration_hash[:schema_search_path] = @original_schema_search_path
79
+ @configuration_hash.freeze
80
+ end
81
+
82
+ def schema_search_path
83
+ @schema_search_path ||= chronomodel_configuration[:schema_search_path]
84
+ end
84
85
  end
85
86
  end
86
87
  end