class Breathing::Trigger
Attributes
log_table_name[R]
model[R]
Public Class Methods
new(model, log_table_name)
click to toggle source
# File lib/breathing/trigger.rb, line 8 def initialize(model, log_table_name) @model = model @log_table_name = log_table_name end
Public Instance Methods
create()
click to toggle source
# File lib/breathing/trigger.rb, line 13 def create exists_trigger_names = ActiveRecord::Base.connection.triggers.keys trigger_name = "#{log_table_name}_insert_#{model.table_name}" create_insert_trigger(trigger_name, model) if exists_trigger_names.exclude?(trigger_name) trigger_name = "#{log_table_name}_update_#{model.table_name}" create_update_trigger(trigger_name, model) if exists_trigger_names.exclude?(trigger_name) trigger_name = "#{log_table_name}_delete_#{model.table_name}" create_delete_trigger(trigger_name, model) if exists_trigger_names.exclude?(trigger_name) end
drop()
click to toggle source
# File lib/breathing/trigger.rb, line 26 def drop trigger_names = %w[insert update delete].map { |action| "#{log_table_name}_#{action}_#{model.table_name}" } trigger_names.each do |trigger_name| begin sql = "DROP TRIGGER IF EXISTS #{trigger_name}" if postgresql? sql << " ON #{model.table_name} CASCADE;" sql << " DROP FUNCTION IF EXISTS #{trigger_name} CASCADE;" end puts sql ActiveRecord::Base.connection.execute(sql) rescue StandardError => e puts "#{e.message} trigger_name:#{trigger_name}" end end end
Private Instance Methods
create_delete_trigger(trigger_name, model)
click to toggle source
# File lib/breathing/trigger.rb, line 77 def create_delete_trigger(trigger_name, model) create_trigger(trigger_name).on(model.table_name).after(:delete) do <<-SQL INSERT INTO #{log_table_name} (created_at, action, table_name, transaction_id, before_data, after_data) VALUES (CURRENT_TIMESTAMP, 'DELETE', '#{model.table_name}', OLD.id, #{row_to_json(model.columns, 'OLD')}, '{}'); SQL end end
create_insert_trigger(trigger_name, model)
click to toggle source
# File lib/breathing/trigger.rb, line 55 def create_insert_trigger(trigger_name, model) create_trigger(trigger_name).on(model.table_name).after(:insert) do <<-SQL INSERT INTO #{log_table_name} (created_at, action, table_name, transaction_id, before_data, after_data) VALUES (CURRENT_TIMESTAMP, 'INSERT', '#{model.table_name}', NEW.id, '{}', #{row_to_json(model.columns, 'NEW')}); SQL end end
create_trigger(name)
click to toggle source
# File lib/breathing/trigger.rb, line 50 def create_trigger(name) puts "CREATE TRIGGER #{name}" ActiveRecord::Base.connection.create_trigger(name) # hairtrigger gem end
create_update_trigger(trigger_name, model)
click to toggle source
# File lib/breathing/trigger.rb, line 66 def create_update_trigger(trigger_name, model) create_trigger(trigger_name).on(model.table_name).before(:update).of(:updated_at) do <<-SQL INSERT INTO #{log_table_name} (created_at, action, table_name, transaction_id, before_data, after_data) VALUES (CURRENT_TIMESTAMP, 'UPDATE', '#{model.table_name}', NEW.id, #{row_to_json(model.columns, 'OLD')}, #{row_to_json(model.columns, 'NEW')}); SQL end end
postgresql?()
click to toggle source
# File lib/breathing/trigger.rb, line 46 def postgresql? ActiveRecord::Base.connection.adapter_name == 'PostgreSQL' end
row_to_json(columns, state)
click to toggle source
# File lib/breathing/trigger.rb, line 88 def row_to_json(columns, state) if postgresql? "row_to_json(#{state}.*)" else json_object_values = columns.each.with_object([]) do |column, array| array << "'#{column.name}'" array << "#{state}.#{column.name}" end "JSON_OBJECT(#{json_object_values.join(',')})" end end