Class: PgSqlTriggers::TriggerStructureDumper
- Inherits:
-
Object
- Object
- PgSqlTriggers::TriggerStructureDumper
- Defined in:
- lib/pg_sql_triggers/trigger_structure_dumper.rb
Overview
Builds a SQL snapshot of PostgreSQL triggers for db/trigger_structure.sql and emits schema.rb annotations so teams know triggers are outside schema.rb.
Class Method Summary collapse
- .default_path ⇒ Object
- .dump_to(path = nil, connection: ActiveRecord::Base.connection) ⇒ Object
- .generate_sql(connection: ActiveRecord::Base.connection) ⇒ Object
- .load_from(path = nil, connection: ActiveRecord::Base.connection) ⇒ Object
- .managed_trigger_names(connection) ⇒ Object
- .resolve_path(override = nil) ⇒ Object
- .schema_rb_annotation(connection: ActiveRecord::Base.connection) ⇒ Object
Class Method Details
.default_path ⇒ Object
18 19 20 21 22 |
# File 'lib/pg_sql_triggers/trigger_structure_dumper.rb', line 18 def default_path raise "Rails.root is required" unless defined?(Rails) && Rails.respond_to?(:root) && Rails.root Rails.root.join("db/trigger_structure.sql") end |
.dump_to(path = nil, connection: ActiveRecord::Base.connection) ⇒ Object
24 25 26 27 28 29 |
# File 'lib/pg_sql_triggers/trigger_structure_dumper.rb', line 24 def dump_to(path = nil, connection: ActiveRecord::Base.connection) target = resolve_path(path) target.dirname.mkpath target.write(generate_sql(connection: connection)) target end |
.generate_sql(connection: ActiveRecord::Base.connection) ⇒ Object
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/pg_sql_triggers/trigger_structure_dumper.rb', line 42 def generate_sql(connection: ActiveRecord::Base.connection) header = <<~SQL -- pg_sql_triggers trigger_structure.sql -- Generated at: #{Time.now.utc.iso8601} -- -- Apply with: bin/rails trigger:load -- Prefer checking this file into version control alongside db/triggers migrations. SQL rows = trigger_rows(connection) parts = [header] rows.each do |row| trigger_name = row["trigger_name"] || row[:trigger_name] parts << "" parts << "-- Trigger: #{trigger_name}" append_definition(parts, row["function_definition"] || row[:function_definition]) append_definition(parts, row["trigger_definition"] || row[:trigger_definition]) end parts.join("\n").strip.concat("\n") end |
.load_from(path = nil, connection: ActiveRecord::Base.connection) ⇒ Object
31 32 33 34 35 36 37 38 39 40 |
# File 'lib/pg_sql_triggers/trigger_structure_dumper.rb', line 31 def load_from(path = nil, connection: ActiveRecord::Base.connection) target = resolve_path(path) raise Errno::ENOENT, target.to_s unless target.file? sql = target.read return if sql.strip.empty? connection.raw_connection.exec(sql) nil end |
.managed_trigger_names(connection) ⇒ Object
82 83 84 85 86 87 88 |
# File 'lib/pg_sql_triggers/trigger_structure_dumper.rb', line 82 def managed_trigger_names(connection) return [] unless connection.table_exists?("pg_sql_triggers_registry") connection.select_values( "SELECT trigger_name FROM pg_sql_triggers_registry ORDER BY trigger_name" ) end |
.resolve_path(override = nil) ⇒ Object
11 12 13 14 15 16 |
# File 'lib/pg_sql_triggers/trigger_structure_dumper.rb', line 11 def resolve_path(override = nil) base = override || PgSqlTriggers.trigger_structure_sql_path resolved = base.respond_to?(:call) ? base.call : base resolved ||= default_path Pathname(resolved.to_s) end |
.schema_rb_annotation(connection: ActiveRecord::Base.connection) ⇒ Object
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/pg_sql_triggers/trigger_structure_dumper.rb', line 65 def schema_rb_annotation(connection: ActiveRecord::Base.connection) names = managed_trigger_names(connection) lines = [] lines << " # ---------------------------------------------------------------------------" lines << " # pg_sql_triggers: PostgreSQL triggers are not captured in schema.rb." lines << " # After db:schema:load, run: bin/rails trigger:migrate (or trigger:load)." lines << " # SQL snapshot: db/trigger_structure.sql (bin/rails trigger:dump)." lines << " # For full fidelity use config.active_record.schema_format = :sql." lines << if names.any? " # Managed triggers (#{names.length}): #{names.join(', ')}" else " # Managed triggers: (none registered in pg_sql_triggers_registry)" end lines << " # ---------------------------------------------------------------------------" lines.join("\n") end |