module PgHaMigrations::UnsafeStatements
Public Class Methods
delegate_unsafe_method_to_migration_base_class(method_name)
click to toggle source
# File lib/pg_ha_migrations/unsafe_statements.rb, line 24 def self.delegate_unsafe_method_to_migration_base_class(method_name) define_method("unsafe_#{method_name}") do |*args, &block| if PgHaMigrations.config.check_for_dependent_objects disallow_migration_method_if_dependent_objects!(method_name, arguments: args) end execute_ancestor_statement(method_name, *args, &block) end end
disable_or_delegate_default_method(method_name, error_message, allow_reentry_from_compatibility_module: false)
click to toggle source
# File lib/pg_ha_migrations/unsafe_statements.rb, line 2 def self.disable_or_delegate_default_method(method_name, error_message, allow_reentry_from_compatibility_module: false) define_method(method_name) do |*args, &block| if PgHaMigrations.config.check_for_dependent_objects disallow_migration_method_if_dependent_objects!(method_name, arguments: args) end if PgHaMigrations.config.disable_default_migration_methods # Most migration methods are only ever called by a migration and # therefore aren't re-entrant or callable from another migration # method, but `execute` is called directly by at least one of the # implementations in `ActiveRecord::Migration::Compatibility` so # we have to explicitly handle that case by allowing execution of # the original implementation by its original name. unless allow_reentry_from_compatibility_module && caller[0] =~ /lib\/active_record\/migration\/compatibility.rb/ raise PgHaMigrations::UnsafeMigrationError, error_message end end execute_ancestor_statement(method_name, *args, &block) end end
Public Instance Methods
execute_ancestor_statement(method_name, *args, &block)
click to toggle source
# File lib/pg_ha_migrations/unsafe_statements.rb, line 81 def execute_ancestor_statement(method_name, *args, &block) # Dispatching here is a bit complicated: we need to execute the method # belonging to the first member of the inheritance chain (besides # UnsafeStatements). If don't find the method in the inheritance chain, # we need to rely on the ActiveRecord::Migration#method_missing # implementation since much of ActiveRecord::Migration's functionality # is not implemented in real methods but rather by proxying. # # For example, ActiveRecord::Migration doesn't define #create_table. # Instead ActiveRecord::Migration#method_missing proxies the method # to the connection. However some migration compatibility version # subclasses _do_ explicitly define #create_table, so we can't rely # on only one way of finding the proper dispatch target. # Exclude our `raise` guard implementations. ancestors_without_unsafe_statements = self.class.ancestors - [PgHaMigrations::UnsafeStatements] delegate_method = self.method(method_name) candidate_method = delegate_method # Find the first usable method in the ancestor chain # or stop looking if there are no more possible # implementations. until candidate_method.nil? || ancestors_without_unsafe_statements.include?(candidate_method.owner) candidate_method = candidate_method.super_method end if candidate_method delegate_method = candidate_method end # If we failed to find a concrete implementation from the # inheritance chain, use ActiveRecord::Migrations# method_missing # otherwise use the method from the inheritance chain. if delegate_method.owner == PgHaMigrations::UnsafeStatements method_missing(method_name, *args, &block) else delegate_method.call(*args, &block) end end
unsafe_add_index(table, column_names, options = {})
click to toggle source
# File lib/pg_ha_migrations/unsafe_statements.rb, line 71 def unsafe_add_index(table, column_names, options = {}) if ((ActiveRecord::VERSION::MAJOR == 5 && ActiveRecord::VERSION::MINOR >= 2) || ActiveRecord::VERSION::MAJOR > 5) && column_names.is_a?(String) && /\W/.match?(column_names) && options.key?(:opclass) raise PgHaMigrations::InvalidMigrationError, "ActiveRecord drops the :opclass option when supplying a string containing an expression or list of columns; instead either supply an array of columns or include the opclass in the string for each column" end execute_ancestor_statement(:add_index, table, column_names, options) end
unsafe_create_table(table, options={}, &block)
click to toggle source
# File lib/pg_ha_migrations/unsafe_statements.rb, line 63 def unsafe_create_table(table, options={}, &block) if options[:force] && !PgHaMigrations.config.allow_force_create_table raise PgHaMigrations::UnsafeMigrationError.new(":force is NOT SAFE! Explicitly call unsafe_drop_table first if you want to recreate an existing table") end execute_ancestor_statement(:create_table, table, options, &block) end