hoardable 0.12.5 → 0.12.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 931223031ac56883e27e5f11da07eae3b59793ca8a2c77ce4e20f67cdb730174
4
- data.tar.gz: 452472091834577883a5d56ea8b1af4375120648eaff066119edc2459c2cf035
3
+ metadata.gz: f56e0b270664927191148ea5ad8bcf4f4511c482c1964d4746f31513eb23b25f
4
+ data.tar.gz: b69b35c7aa7f3eb013b1444c3b26115f012c8a7617ba457ce248074eca2706e0
5
5
  SHA512:
6
- metadata.gz: 414a407c30d2aa0f504cd89773a83dd0b775bbbed51c8f7dbaa4225141aa34d301aac6167b6ce3553af02f03e8e2d1a053b58b4f9946814d5fb1b17282f86817
7
- data.tar.gz: 995256175f51743332171ec32e232bdf01abb7288df8987d75b4e164499cf99610dc8605a9956fed3eb0edbb736b46ae24906fdf00cf5c14fa9ec99d752647d2
6
+ metadata.gz: 39c6176733cb67efc47e9d7985fa30427090e02c21c6abb6d54e9d2b88c975c430b4e0eafa4976457704a16c1fd8ef68c0245269f67adf0cf4a13d4e5a42c2f4
7
+ data.tar.gz: 975229330ca851b4d847113a3e76bd0a0ff59a86cf39a5cfa73e11f456d475a0b51df82a90ab51a6035ab1f934ce7fa87607925679fd620c4dab25ec44979cf4
data/README.md CHANGED
@@ -36,11 +36,8 @@ bin/rails g hoardable:install
36
36
  bin/rails db:migrate
37
37
  ```
38
38
 
39
- This will generate a PostgreSQL function and an initiailzer.
40
-
41
- _Note:_ It is recommended to set `config.active_record.schema_format = :sql` in `application.rb`, so
42
- that the function and triggers in the migrations that prevent updates to the versions table get
43
- captured in your schema.
39
+ This will generate PostgreSQL functions, an initiailzer, and set `config.active_record.schema_format
40
+ = :sql` in `application.rb`.
44
41
 
45
42
  ### Model Installation
46
43
 
@@ -393,7 +390,7 @@ class Post < ActiveRecord::Base
393
390
  end
394
391
  ```
395
392
 
396
- ## Action Text
393
+ ### Action Text
397
394
 
398
395
  Hoardable provides support for ActiveRecord models with `has_rich_text`. First, you must create a
399
396
  temporal table for `ActionText::RichText`:
@@ -426,6 +423,18 @@ Hoardable.at(datetime) do
426
423
  end
427
424
  ```
428
425
 
426
+ ### Known Gotchas
427
+
428
+ #### Rails Fixtures
429
+
430
+ Rails uses a method called
431
+ [`disable_referential_integrity`](https://github.com/rails/rails/blob/06e9fbd954ab113108a7982357553fdef285bff1/activerecord/lib/active_record/connection_adapters/postgresql/referential_integrity.rb#L7)
432
+ when inserting fixtures into the database. This disables PostgreSQL triggers, which Hoardable relies
433
+ on for assigning `hoardable_id` from the primary key’s value. If you would still like to use
434
+ fixtures, you must specify the primary key’s value and `hoardable_id` to the same identifier value
435
+ in the fixture. This is not an issue with fixture replacement libraries like `factory_girl` or
436
+ [`world_factory`](https://github.com/FutureProofRetail/world_factory) however.
437
+
429
438
  ## Gem Comparison
430
439
 
431
440
  #### [`paper_trail`](https://github.com/paper-trail-gem/paper_trail)
@@ -26,6 +26,10 @@ module Hoardable
26
26
  migration_template 'install.rb.erb', 'db/migrate/install_hoardable.rb'
27
27
  end
28
28
 
29
+ def change_schema_format_to_sql
30
+ application 'config.active_record.schema_format = :sql'
31
+ end
32
+
29
33
  def self.next_migration_number(dir)
30
34
  ::ActiveRecord::Generators::Base.next_migration_number(dir)
31
35
  end
@@ -3,7 +3,7 @@
3
3
  class InstallHoardable < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
4
4
  def up
5
5
  execute(
6
- <<~SQL
6
+ <<~SQL.squish
7
7
  DO $$
8
8
  BEGIN
9
9
  IF NOT EXISTS (
@@ -51,9 +51,10 @@ class InstallHoardable < ActiveRecord::Migration[<%= ActiveRecord::Migration.cur
51
51
  SQL
52
52
  )
53
53
  end
54
+
54
55
  def down
55
56
  execute(
56
- <<~SQL
57
+ <<~SQL.squish
57
58
  DROP TYPE IF EXISTS hoardable_operation;
58
59
  DROP FUNCTION IF EXISTS hoardable_version_prevent_update();
59
60
  DROP FUNCTION IF EXISTS hoardable_source_set_id();
@@ -40,8 +40,36 @@ module Hoardable
40
40
  )
41
41
  end
42
42
 
43
+ def has_one_find_conditions(reflection)
44
+ {
45
+ reflection.type => source_record.class.name.sub(/Version$/, ''),
46
+ reflection.foreign_key => source_record.hoardable_id,
47
+ 'name' => (reflection.name.to_s.sub(/^rich_text_/, '') if reflection.class_name.match?(/RichText$/))
48
+ }.reject { |k, v| k.nil? || v.nil? }
49
+ end
50
+
51
+ def has_one_at_timestamp
52
+ Hoardable.instance_variable_get('@at') || source_record.updated_at
53
+ rescue NameError
54
+ raise(UpdatedAtColumnMissingError, source_record.class.table_name)
55
+ end
56
+
43
57
  def source_attributes_without_primary_key
44
- source_record.attributes_before_type_cast.without(source_primary_key)
58
+ source_record.attributes_before_type_cast.without(source_primary_key, *generated_column_names).merge(
59
+ source_record.class.select(refreshable_column_names).find(source_record.id).slice(refreshable_column_names)
60
+ )
61
+ end
62
+
63
+ def generated_column_names
64
+ @generated_column_names ||= source_record.class.columns.select(&:virtual?).map(&:name)
65
+ rescue NoMethodError
66
+ []
67
+ end
68
+
69
+ def refreshable_column_names
70
+ @refreshable_column_names ||= source_record.class.columns.select(&:default_function).reject do |column|
71
+ column.name == source_primary_key || column.name.in?(generated_column_names)
72
+ end.map(&:name)
45
73
  end
46
74
 
47
75
  def initialize_temporal_range
@@ -34,9 +34,12 @@ module Hoardable
34
34
  end.freeze
35
35
  private_constant :HOARDABLE_VERSION_UPDATES
36
36
 
37
- SUPPORTS_ENCRYPTED_ACTION_TEXT = ActiveRecord.version >= ::Gem::Version.new('7.0')
37
+ SUPPORTS_ENCRYPTED_ACTION_TEXT = ActiveRecord.version >= ::Gem::Version.new('7.0.4')
38
38
  private_constant :SUPPORTS_ENCRYPTED_ACTION_TEXT
39
39
 
40
+ SUPPORTS_VIRTUAL_COLUMNS = ActiveRecord.version >= ::Gem::Version.new('7.0.0')
41
+ private_constant :SUPPORTS_VIRTUAL_COLUMNS
42
+
40
43
  @context = {}
41
44
  @config = CONFIG_KEYS.to_h do |key|
42
45
  [key, true]
@@ -17,28 +17,14 @@ module Hoardable
17
17
  def #{name}
18
18
  reflection = _reflections['#{name}']
19
19
  return super if reflection.klass.name.match?(/^ActionText/)
20
+ return super unless (timestamp = hoardable_client.has_one_at_timestamp)
20
21
 
21
- super&.at(hoardable_at_timestamp) ||
22
- reflection.klass.at(hoardable_at_timestamp).find_by(
23
- {
24
- reflection.type => self.class.name.sub(/Version$/, ''),
25
- reflection.foreign_key => hoardable_id
26
- }.reject { |key, _| key.blank? }
27
- )
22
+ super&.at(timestamp) ||
23
+ reflection.klass.at(timestamp).find_by(hoardable_client.has_one_find_conditions(reflection))
28
24
  end
29
25
  RUBY
30
26
  end
31
27
  end
32
-
33
- included do
34
- private
35
-
36
- def hoardable_at_timestamp
37
- Hoardable.instance_variable_get('@at') || updated_at
38
- rescue NameError
39
- raise(UpdatedAtColumnMissingError, self.class.table_name)
40
- end
41
- end
42
28
  end
43
29
  private_constant :HasOne
44
30
  end
@@ -75,6 +75,8 @@ module Hoardable
75
75
  #
76
76
  # @param datetime [DateTime, Time]
77
77
  def at(datetime)
78
+ return self if datetime.nil? || !created_at
79
+
78
80
  version_at(datetime) || (self if created_at < datetime)
79
81
  end
80
82
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Hoardable
4
- VERSION = '0.12.5'
4
+ VERSION = '0.12.9'
5
5
  end
@@ -86,7 +86,7 @@ module Hoardable
86
86
 
87
87
  transaction do
88
88
  hoardable_source.tap do |reverted|
89
- reverted.update!(hoardable_source_attributes.without(self.class.superclass.primary_key))
89
+ reverted.reload.update!(hoardable_source_attributes.without(self.class.superclass.primary_key))
90
90
  reverted.instance_variable_set(:@hoardable_version, self)
91
91
  reverted.run_callbacks(:reverted)
92
92
  end
@@ -130,7 +130,10 @@ module Hoardable
130
130
  end
131
131
 
132
132
  def hoardable_source_attributes
133
- attributes_before_type_cast.without(self.class.column_names - self.class.superclass.column_names)
133
+ attributes_before_type_cast.without(
134
+ (self.class.column_names - self.class.superclass.column_names) +
135
+ (SUPPORTS_VIRTUAL_COLUMNS ? self.class.columns.select(&:virtual?).map(&:name) : [])
136
+ )
134
137
  end
135
138
  end
136
139
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hoardable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.5
4
+ version: 0.12.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - justin talbott
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-10-14 00:00:00.000000000 Z
11
+ date: 2022-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord