iron_trail 0.0.1 → 0.0.2

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: d4743b8660d0a3f59c82131213a4e9b85396c0efa83f2a00c2678dcb2a2d57a7
4
- data.tar.gz: 6d53fef0dbb300ce504c8065616142ba012cb697647a5f588d4f2bea3935e293
3
+ metadata.gz: fbae2be821b8553a0ddf746fd9d30b3b7420b27e80e293b0716d78bf60c2c4dd
4
+ data.tar.gz: 9525cad670a20bc43414a56a0ea87734e82c908f175a82545cbe0c386f7fec86
5
5
  SHA512:
6
- metadata.gz: 7bc826ad0ff24c91b6e7d9bac08fb7c5a0f893142a91315804aafe68a95bc96e3be5b9b98ed83de9f4d293daab9b1bbce3432579116db79fa3c47ca8b184b0a7
7
- data.tar.gz: b43255cfbe9833075c44335eaaeb5e2067e942d99f4ff3b8e35aee42c9960cdfe6e1e96cfe5c75fd2b4ae53c8dbef580dae2768cf308f92b2bb2d5a5e06ec667
6
+ metadata.gz: b6a32637f82a839336850df3f5b8a090a367b87eb519db903c41681de33578ea3b4d13f9ed15301985a29ce0b82c2bfacd98651da1e266373a639741453e2925
7
+ data.tar.gz: 8bb96a201f38d6923d864f65d92b3bec8cab90df9ad30144716d8ea0943d8fad25f46b4433a6e868177454cef3c6f8e7c738d22e7c83354162f897c3e7882795
@@ -7,23 +7,25 @@ module IronTrail
7
7
  class MigrationGenerator < Rails::Generators::Base
8
8
  include ::Rails::Generators::Migration
9
9
 
10
- source_root File.expand_path('templates', __dir__)
10
+ source_root File.expand_path("templates", __dir__)
11
11
 
12
- desc 'Generates a migration adding the iron trail changes table'
12
+ desc "Generates a migration adding the iron trail changes table"
13
13
  def create_changes_migration_file
14
+ migration_dir = File.expand_path("db/migrate")
15
+
14
16
  migration_template(
15
- 'create_irontrail_changes.rb.erb',
16
- 'db/migrate/create_irontrail_changes.rb'
17
+ "create_irontrail_changes.rb.erb",
18
+ "db/migrate/create_irontrail_changes.rb"
17
19
  )
18
20
 
19
21
  migration_template(
20
- 'create_irontrail_support_tables.rb.erb',
21
- 'db/migrate/create_irontrail_support_tables.rb'
22
+ "create_irontrail_support_tables.rb.erb",
23
+ "db/migrate/create_irontrail_support_tables.rb"
22
24
  )
23
25
 
24
26
  migration_template(
25
- 'create_irontrail_trigger_function.rb.erb',
26
- 'db/migrate/create_irontrail_trigger_function.rb'
27
+ "create_irontrail_trigger_function.rb.erb",
28
+ "db/migrate/create_irontrail_trigger_function.rb"
27
29
  )
28
30
  end
29
31
 
@@ -3,7 +3,12 @@
3
3
  module IronTrail
4
4
  class Association < ::ActiveRecord::Associations::HasManyAssociation
5
5
  def association_scope
6
+ klass = self.klass
7
+ reflection = self.reflection
6
8
  scope = klass.unscoped
9
+ owner = self.owner
10
+
11
+ chain = [::ActiveRecord::Reflection::RuntimeReflection.new(reflection, self)]
7
12
 
8
13
  foreign_key = reflection.join_foreign_key
9
14
  pk_value = owner._read_attribute(foreign_key)
@@ -20,7 +20,7 @@ module IronTrail
20
20
 
21
21
  args.each do |col_name, value|
22
22
  scope.where!(
23
- ::Arel::Nodes::SqlLiteral.new("rec_delta->#{connection.quote(col_name)}->>#{Integer(ary_index)}").eq(
23
+ ::Arel::Nodes::SqlLiteral.new("rec_delta->#{connection.quote col_name}->>#{Integer(ary_index)}").eq(
24
24
  ::Arel::Nodes::BindParam.new(value)
25
25
  )
26
26
  )
@@ -28,7 +28,7 @@ module IronTrail
28
28
  # directly.
29
29
  # It is possible to call Array#clear to empty the array and remove default
30
30
  # should that be desired.
31
- def ignored_tables=(_v)
31
+ def ignored_tables=(v)
32
32
  raise 'Overwriting ignored_tables is not allow. Instead, add or remove to it explicitly.'
33
33
  end
34
34
  end
@@ -46,12 +46,12 @@ module IronTrail
46
46
  LIMIT 1;
47
47
  SQL
48
48
 
49
- connection.execute(stmt).to_a.count.positive?
49
+ connection.execute(stmt).to_a.count > 0
50
50
  end
51
51
 
52
52
  def remove_functions(cascade:)
53
- query = +'DROP FUNCTION irontrail_log_row'
54
- query << ' CASCADE' if cascade
53
+ query = +"DROP FUNCTION irontrail_log_row"
54
+ query << " CASCADE" if cascade
55
55
 
56
56
  connection.execute(query)
57
57
  end
@@ -83,6 +83,18 @@ module IronTrail
83
83
  end
84
84
  end
85
85
 
86
+ def disable_for_all_ignored_tables
87
+ affected_tables = collect_tracked_table_names & (
88
+ OWN_TABLES + (IronTrail.config.ignored_tables || [])
89
+ )
90
+
91
+ affected_tables.each do |table_name|
92
+ disable_tracking_for_table(table_name)
93
+ end
94
+
95
+ affected_tables
96
+ end
97
+
86
98
  def collect_tables_tracking_status
87
99
  ignored_tables = OWN_TABLES + (IronTrail.config.ignored_tables || [])
88
100
 
@@ -96,7 +108,7 @@ module IronTrail
96
108
  end
97
109
 
98
110
  def disable_tracking_for_table(table_name)
99
- # NOTE: will disable even if table is ignored as this allows
111
+ # Note: will disable even if table is ignored as this allows
100
112
  # one to fix ignored tables mnore easily. Since the table is already
101
113
  # ignored, it is an expected destructive operation.
102
114
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  module IronTrail
4
4
  module Migration
5
- def method_missing(method, *args) # rubocop:disable Style/MissingRespondToMissing
5
+ def method_missing(method, *args)
6
6
  running_from_schema = is_a?(ActiveRecord::Schema) ||
7
7
  (defined?(ActiveRecord::Schema::Definition) && is_a?(ActiveRecord::Schema::Definition))
8
8
 
@@ -11,7 +11,9 @@ module IronTrail
11
11
  return result unless IronTrail.enabled? && method == :create_table
12
12
 
13
13
  start_at_version = IronTrail.config.track_migrations_starting_at_version
14
- return result if !running_from_schema && start_at_version && version < (Integer(start_at_version))
14
+ if !running_from_schema && start_at_version
15
+ return result if self.version < Integer(start_at_version)
16
+ end
15
17
 
16
18
  table_name = args.first.to_s
17
19
  return result if IronTrail.ignore_table?(table_name)
@@ -27,10 +29,7 @@ module IronTrail
27
29
  if db_fun.function_present?
28
30
  db_fun.enable_tracking_for_table(table_name)
29
31
  else
30
- Rails.logger.warn(
31
- "IronTrail will not create trigger for table #{table_name} " \
32
- 'because the trigger function does not exist in the database.'
33
- )
32
+ Rails.logger.warn("IronTrail will not create trigger for table #{table_name} because the trigger function does not exist in the database.")
34
33
  end
35
34
 
36
35
  result
@@ -8,7 +8,7 @@ module IronTrail
8
8
  # own AR reflection and association classes.
9
9
  module Model
10
10
  def self.included(mod)
11
- mod.include(ClassMethods)
11
+ mod.include ClassMethods
12
12
 
13
13
  ::ActiveRecord::Reflection.add_reflection(
14
14
  mod,
@@ -2,7 +2,7 @@
2
2
 
3
3
  module IronTrail
4
4
  class QueryTransformer
5
- METADATA_MAX_LENGTH = 1_048_576 # 1 MiB
5
+ METADATA_MAX_LENGTH = 1048576 # 1 MiB
6
6
 
7
7
  attr_reader :transformer_proc
8
8
 
@@ -24,10 +24,7 @@ module IronTrail
24
24
  metadata = JSON.dump(current_metadata)
25
25
 
26
26
  if metadata.length > METADATA_MAX_LENGTH
27
- Rails.logger.warn(
28
- "IronTrail metadata is longer than maximum length! #{metadata.length} > #{METADATA_MAX_LENGTH}"
29
- )
30
-
27
+ Rails.logger.warn("IronTrail metadata is longer than maximum length! #{metadata.length} > #{METADATA_MAX_LENGTH}")
31
28
  next query
32
29
  end
33
30
 
@@ -2,13 +2,13 @@
2
2
 
3
3
  module IronTrail
4
4
  class Reflection < ::ActiveRecord::Reflection::AssociationReflection
5
- def collection? = true
5
+ def collection?; true; end
6
6
 
7
7
  def association_class
8
8
  ::IronTrail::Association
9
9
  end
10
10
 
11
- def join_scope(table, foreign_table, _foreign_klass)
11
+ def join_scope(table, foreign_table, foreign_klass)
12
12
  scope = klass_join_scope(table, nil)
13
13
 
14
14
  foreign_key_column_names = Array(join_foreign_key)
@@ -26,7 +26,7 @@ module IronTrail
26
26
  ::Arel::Nodes::As.new(
27
27
  foreign_table[foreign_key_column_name],
28
28
  ::Arel::Nodes::SqlLiteral.new('text')
29
- )
29
+ ),
30
30
  ]
31
31
  )
32
32
 
@@ -1,3 +1,66 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ if ENV['RAILS_ENV'] == 'production'
4
+ raise 'This file should not be required in production. ' \
5
+ 'Change the RAILS_ENV env var temporarily to override this.'
6
+ end
7
+
3
8
  require 'iron_trail'
9
+
10
+ module IronTrail
11
+ module Testing
12
+ class << self
13
+ attr_accessor :enabled
14
+
15
+ def enable!
16
+ DbFunctions.new(ActiveRecord::Base.connection).install_functions
17
+ @enabled = true
18
+ end
19
+
20
+ def disable!
21
+ # We "disable" it by replacing the trigger function by a no-op one.
22
+ # This should be faster than adding/removing triggers from several
23
+ # tables every time.
24
+ sql = <<~SQL
25
+ CREATE OR REPLACE FUNCTION irontrail_log_row()
26
+ RETURNS TRIGGER AS $$
27
+ BEGIN
28
+ RETURN NULL;
29
+ END;
30
+ $$ LANGUAGE plpgsql;
31
+ SQL
32
+
33
+ ActiveRecord::Base.connection.execute(sql)
34
+ @enabled = false
35
+ end
36
+
37
+ def with_iron_trail(want_enabled:, &block)
38
+ was_enabled = IronTrail::Testing.enabled
39
+
40
+ if want_enabled
41
+ ::IronTrail::Testing.enable! unless was_enabled
42
+ else
43
+ ::IronTrail::Testing.disable! if was_enabled
44
+ end
45
+
46
+ block.call
47
+ ensure
48
+ if want_enabled && !was_enabled
49
+ ::IronTrail::Testing.disable!
50
+ elsif !want_enabled && was_enabled
51
+ ::IronTrail::Testing.enable!
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ RSpec.configure do |config|
59
+ config.around(:each, iron_trail: true) do |example|
60
+ IronTrail::Testing.with_iron_trail(want_enabled: true) { example.run }
61
+ end
62
+ config.around(:each, iron_trail: false) do |example|
63
+ raise "Using iron_trail: false does not do what you might think it does. To disable iron_trail, " \
64
+ "use IronTrail::Testing.with_iron_trail(want_enabled: false) { ... } instead."
65
+ end
66
+ end
@@ -1,5 +1,5 @@
1
- # frozen_string_literal: true
1
+ # frozen_literal_string: true
2
2
 
3
3
  module IronTrail
4
- VERSION = '0.0.1'
4
+ VERSION = '0.0.2'
5
5
  end
data/lib/iron_trail.rb CHANGED
@@ -29,9 +29,9 @@ module IronTrail
29
29
 
30
30
  module SchemaDumper
31
31
  def trailer(stream)
32
- stream.print("\n IronTrail.post_schema_load(self, missing_tracking: @irontrail_missing_track)\n")
32
+ stream.print "\n IronTrail.post_schema_load(self, missing_tracking: @irontrail_missing_track)\n"
33
33
 
34
- super
34
+ super(stream)
35
35
  end
36
36
  end
37
37
 
@@ -87,9 +87,11 @@ module IronTrail
87
87
  end
88
88
 
89
89
  def_delegators :store_instance,
90
- :store_metadata,
91
- :merge_metadata,
92
- :current_metadata
90
+ :store_metadata,
91
+ :merge_metadata,
92
+ :current_metadata
93
+
94
+
93
95
  end
94
96
  end
95
97
 
@@ -1,45 +1,76 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ module IronTrail::RakeHelper
4
+ class << self
5
+ def db_functions
6
+ IronTrail::DbFunctions.new(ActiveRecord::Base.connection)
7
+ end
8
+
9
+ def abort_when_unsafe!
10
+ run_unsafe = %w[true 1 yes].include?(ENV['IRONTRAIL_RUN_UNSAFE'])
11
+ return unless Rails.env.production? && !run_unsafe
12
+
13
+ puts "Aborting: operation is dangerous in a production environment. " + \
14
+ "Override this behavior by setting the IRONTRAIL_RUN_UNSAFE=1 env var."
15
+
16
+ exit(1)
17
+ end
18
+ end
19
+ end
20
+
3
21
  namespace :iron_trail do
4
22
  namespace :tracking do
5
23
  desc 'Enables tracking for all missing tables.'
6
24
  task enable: :environment do
7
- tables = db_functions.collect_tables_tracking_status[:missing]
8
- unless tables.length.positive?
9
- puts 'All tables are being tracked already (no missing tables found).'
10
- puts 'If you think this is wrong, check your ignored_tables list.'
25
+ tables = IronTrail::RakeHelper.db_functions.collect_tables_tracking_status[:missing]
26
+ unless tables.length > 0
27
+ puts "All tables are being tracked already (no missing tables found)."
28
+ puts "If you think this is wrong, check your ignored_tables list."
11
29
  return
12
30
  end
13
31
 
14
32
  puts "Will start tracking #{tables.length} tables."
15
33
  tables.each do |table_name|
16
- db_functions.enable_tracking_for_table(table_name)
34
+ IronTrail::RakeHelper.db_functions.enable_tracking_for_table(table_name)
35
+ end
36
+ end
37
+
38
+ desc 'Disabled tracking for any ignored table that might still have the trigger enabled.'
39
+ task disable_on_ignored: :environment do
40
+ affected_tables = IronTrail::RakeHelper.db_functions.disable_for_all_ignored_tables
41
+
42
+ unless affected_tables.empty?
43
+ puts "Removed tracking from #{affected_tables.length} tables:"
44
+
45
+ affected_tables.each do |table_name|
46
+ puts "\t#{table_name}"
47
+ end
17
48
  end
18
49
  end
19
50
 
20
51
  desc 'Disables tracking all tables. Dangerous!'
21
52
  task disable: :environment do
22
- abort_when_unsafe!
53
+ IronTrail::RakeHelper.abort_when_unsafe!
23
54
 
24
- tables = db_functions.collect_tables_tracking_status[:tracked]
55
+ tables = IronTrail::RakeHelper.db_functions.collect_tables_tracking_status[:tracked]
25
56
  puts "Will stop tracking #{tables.length} tables."
26
57
  tables.each do |table_name|
27
- db_functions.disable_tracking_for_table(table_name)
58
+ IronTrail::RakeHelper.db_functions.disable_tracking_for_table(table_name)
28
59
  end
29
60
 
30
- tables = db_functions.collect_tables_tracking_status[:tracked]
31
- if tables.length.positive?
32
- puts "WARNING: Something went wrong. There are still #{tables.length} " \
33
- 'tables being tracked.'
61
+ tables = IronTrail::RakeHelper.db_functions.collect_tables_tracking_status[:tracked]
62
+ if tables.length > 0
63
+ puts "WARNING: Something went wrong. There are still #{tables.length}" + \
64
+ " tables being tracked."
34
65
  else
35
- puts 'Done!'
66
+ puts "Done!"
36
67
  end
37
68
  end
38
69
 
39
70
  desc 'Shows which tables are tracking, missing and ignored.'
40
71
  task status: :environment do
41
- status = db_functions.collect_tables_tracking_status
42
- ignored = IronTrail.config.ignored_tables || []
72
+ status = IronTrail::RakeHelper.db_functions.collect_tables_tracking_status
73
+ ignored = (IronTrail.config.ignored_tables || [])
43
74
 
44
75
  # We likely want to keep this structure of text untouched as someone
45
76
  # could use it to perform automation (e.g. monitoring).
@@ -47,36 +78,20 @@ namespace :iron_trail do
47
78
  puts "Missing #{status[:missing].length} tables."
48
79
  puts "There are #{ignored.length} ignored tables."
49
80
 
50
- puts 'Tracked tables:'
81
+ puts "Tracked tables:"
51
82
  status[:tracked].sort.each do |table_name|
52
83
  puts "\t#{table_name}"
53
84
  end
54
85
 
55
- puts 'Missing tables:'
86
+ puts "Missing tables:"
56
87
  status[:missing].sort.each do |table_name|
57
88
  puts "\t#{table_name}"
58
89
  end
59
90
 
60
- puts 'Ignored tables:'
91
+ puts "Ignored tables:"
61
92
  ignored.sort.each do |table_name|
62
93
  puts "\t#{table_name}"
63
94
  end
64
95
  end
65
-
66
- private
67
-
68
- def db_functions
69
- @db_functions ||= IronTrail::DbFunctions.new(ActiveRecord::Base.connection)
70
- end
71
-
72
- def abort_when_unsafe!
73
- run_unsafe = %w[true 1 yes].include?(ENV['IRONTRAIL_RUN_UNSAFE'])
74
- return unless Rails.env.production? && !run_unsafe
75
-
76
- puts 'Aborting: operation is dangerous in a production environment. ' \
77
- 'Override this behavior by setting the IRONTRAIL_RUN_UNSAFE=1 env var.'
78
-
79
- exit(1)
80
- end
81
96
  end
82
97
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iron_trail
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - André Diego Piske
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-11-26 00:00:00.000000000 Z
11
+ date: 2024-12-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -39,61 +39,33 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.5'
41
41
  - !ruby/object:Gem::Dependency
42
- name: appraisal
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '2.5'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '2.5'
55
- - !ruby/object:Gem::Dependency
56
- name: rubocop
42
+ name: pg_party
57
43
  requirement: !ruby/object:Gem::Requirement
58
44
  requirements:
59
45
  - - "~>"
60
46
  - !ruby/object:Gem::Version
61
- version: '1.69'
47
+ version: '1.8'
62
48
  type: :development
63
49
  prerelease: false
64
50
  version_requirements: !ruby/object:Gem::Requirement
65
51
  requirements:
66
52
  - - "~>"
67
53
  - !ruby/object:Gem::Version
68
- version: '1.69'
69
- - !ruby/object:Gem::Dependency
70
- name: debug
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
54
+ version: '1.8'
83
55
  - !ruby/object:Gem::Dependency
84
- name: pg_party
56
+ name: appraisal
85
57
  requirement: !ruby/object:Gem::Requirement
86
58
  requirements:
87
59
  - - "~>"
88
60
  - !ruby/object:Gem::Version
89
- version: '1.8'
61
+ version: '2.5'
90
62
  type: :development
91
63
  prerelease: false
92
64
  version_requirements: !ruby/object:Gem::Requirement
93
65
  requirements:
94
66
  - - "~>"
95
67
  - !ruby/object:Gem::Version
96
- version: '1.8'
68
+ version: '2.5'
97
69
  - !ruby/object:Gem::Dependency
98
70
  name: rake
99
71
  requirement: !ruby/object:Gem::Requirement
@@ -195,8 +167,7 @@ files:
195
167
  homepage: https://github.com/trusted/iron_trail
196
168
  licenses:
197
169
  - MIT
198
- metadata:
199
- rubygems_mfa_required: 'true'
170
+ metadata: {}
200
171
  post_install_message:
201
172
  rdoc_options: []
202
173
  require_paths: