Module: SchemaPlus::ActiveRecord::ConnectionAdapters::AbstractAdapter

Defined in:
lib/schema_plus/active_record/connection_adapters/abstract_adapter.rb

Overview

SchemaPlus adds several methods to ActiveRecord::ConnectionAdapters::AbstractAdapter. In most cases you don’t call these directly, but rather the methods that define things are called by schema statements, and methods that query things are called by ActiveRecord::Base.

Defined Under Namespace

Modules: SchemaCreation

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object

:nodoc:



14
15
16
# File 'lib/schema_plus/active_record/connection_adapters/abstract_adapter.rb', line 14

def self.included(base) #:nodoc:
  base.alias_method_chain :initialize, :schema_plus
end

Instance Method Details

#add_column_options!(sql, options) ⇒ Object



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/schema_plus/active_record/connection_adapters/abstract_adapter.rb', line 116

def add_column_options!(sql, options)
  if options_include_default?(options)
    default = options[:default]
    if default.is_a? Hash
      value = default[:value]
      expr = sql_for_function(default[:expr]) || default[:expr] if default[:expr]
    else
      value = default
      expr = sql_for_function(default)
    end
    if expr
      raise ArgumentError, "Invalid default expression" unless default_expr_valid?(expr)
      sql << " DEFAULT #{expr}"
    else
      sql << " DEFAULT #{quote(value, options[:column])}" unless value.nil?
    end
  end
  # must explicitly check for :null to allow change_column to work on migrations
  if options[:null] == false
    sql << " NOT NULL"
  end
end

#add_foreign_key(table_name, column_names, references_table_name, references_column_names, options = {}) ⇒ Object

Define a foreign key constraint. Valid options are :on_update, :on_delete, and :deferrable, with values as described at ConnectionAdapters::ForeignKeyDefinition

(NOTE: Sqlite3 does not support altering a table to add foreign-key constraints; they must be included in the table specification when it’s created. If you’re using Sqlite3, this method will raise an error.)



59
60
61
62
# File 'lib/schema_plus/active_record/connection_adapters/abstract_adapter.rb', line 59

def add_foreign_key(table_name, column_names, references_table_name, references_column_names, options = {})
  foreign_key = ForeignKeyDefinition.new(options[:name] || ForeignKeyDefinition.default_name(table_name, column_names), table_name, column_names, ::ActiveRecord::Migrator.proper_table_name(references_table_name), references_column_names, options[:on_update], options[:on_delete], options[:deferrable])
  execute "ALTER TABLE #{quote_table_name(table_name)} ADD #{foreign_key.to_sql}"
end

#create_view(view_name, definition, options = {}) ⇒ Object

Create a view given the SQL definition. Specify :force => true to first drop the view if it already exists.



39
40
41
42
43
# File 'lib/schema_plus/active_record/connection_adapters/abstract_adapter.rb', line 39

def create_view(view_name, definition, options={})
  definition = definition.to_sql if definition.respond_to? :to_sql
  execute "DROP VIEW IF EXISTS #{quote_table_name(view_name)}" if options[:force]
  execute "CREATE VIEW #{quote_table_name(view_name)} AS #{definition}"
end

#default_expr_valid?(expr) ⇒ Boolean

(abstract) Return true if the passed expression can be used as a column default value. (For most databases the specific expression doesn’t matter, and the adapter’s function would return a constant true if default expressions are supported or false if they’re not.)

Returns:

  • (Boolean)


166
# File 'lib/schema_plus/active_record/connection_adapters/abstract_adapter.rb', line 166

def default_expr_valid?(expr) raise "Internal Error: Connection adapter didn't override abstract function"; end

#drop_table(name, options = {}) ⇒ Object

Extends rails’ drop_table to include these options:

:cascade
:if_exists


77
78
79
80
81
82
83
# File 'lib/schema_plus/active_record/connection_adapters/abstract_adapter.rb', line 77

def drop_table(name, options = {})
  sql = "DROP TABLE"
  sql += " IF EXISTS" if options[:if_exists]
  sql += " #{quote_table_name(name)}"
  sql += " CASCADE" if options[:cascade]
  execute sql
end

#drop_view(view_name) ⇒ Object

Drop the named view



46
47
48
# File 'lib/schema_plus/active_record/connection_adapters/abstract_adapter.rb', line 46

def drop_view(view_name)
  execute "DROP VIEW #{quote_table_name(view_name)}"
end

#foreign_keys(table_name, name = nil) ⇒ Object

(abstract) Return the ForeignKeyDefinition objects for foreign key constraints defined on this table



155
# File 'lib/schema_plus/active_record/connection_adapters/abstract_adapter.rb', line 155

def foreign_keys(table_name, name = nil) raise "Internal Error: Connection adapter didn't override abstract function"; [] end

#initialize_with_schema_plus(*args) ⇒ Object

:nodoc:



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/schema_plus/active_record/connection_adapters/abstract_adapter.rb', line 18

def initialize_with_schema_plus(*args) #:nodoc:
  initialize_without_schema_plus(*args)
  adapter = case adapter_name
              # name of MySQL adapter depends on mysql gem
              # * with mysql gem adapter is named MySQL
              # * with mysql2 gem adapter is named Mysql2
              # Here we handle this and hopefully futher adapter names
            when /^MySQL/i                 then 'MysqlAdapter'
            when 'PostgreSQL', 'PostGIS'   then 'PostgresqlAdapter'
            when 'SQLite'                  then 'Sqlite3Adapter'
            end or raise "SchemaPlus: Unsupported adapter name #{adapter_name.inspect}"
              # use 'end or raise' instead of 'else raise' to get
              # 100% C0 code coverage despite having no test case
              # for this.
  adapter_module = SchemaPlus::ActiveRecord::ConnectionAdapters.const_get(adapter)
  self.class.send(:include, adapter_module) unless self.class.include?(adapter_module)
  extend(SchemaPlus::ActiveRecord::ForeignKeys)
end

#remove_foreign_key(table_name, foreign_key_name) ⇒ Object

Remove a foreign key constraint

(NOTE: Sqlite3 does not support altering a table to remove foreign-key constraints. If you’re using Sqlite3, this method will raise an error.)



69
70
71
# File 'lib/schema_plus/active_record/connection_adapters/abstract_adapter.rb', line 69

def remove_foreign_key(table_name, foreign_key_name)
  execute "ALTER TABLE #{quote_table_name(table_name)} DROP CONSTRAINT #{foreign_key_name}"
end

#rename_indexes_and_foreign_keys(oldname, newname) ⇒ Object

called from individual adpaters, after renaming table from old name to



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/schema_plus/active_record/connection_adapters/abstract_adapter.rb', line 87

def rename_indexes_and_foreign_keys(oldname, newname) #:nodoc:
  indexes(newname).select{|index| index.name == index_name(oldname, index.columns)}.each do |index|
    rename_index(newname, index.name, index_name(newname, index.columns))
  end
  foreign_keys(newname).each do |fk|
    index = indexes(newname).find{|index| index.name == ForeignKeyDefinition.auto_index_name(oldname, fk.column_names)}
    begin
      remove_foreign_key(newname, fk.name)
    rescue NotImplementedError
      # sqlite3 can't remove foreign keys, so just skip it
    end
    # rename the index only when the fk constraint doesn't exist.
    # mysql doesn't allow the rename (which is a delete & add)
    # if the index is on a foreign key constraint
    rename_index(newname, index.name, ForeignKeyDefinition.auto_index_name(newname, index.columns)) if index
    begin
      add_foreign_key(newname, fk.column_names, fk.references_table_name, fk.references_column_names, :name => fk.name.sub(/#{oldname}/, newname), :on_update => fk.on_update, :on_delete => fk.on_delete, :deferrable => fk.deferrable)
    rescue NotImplementedError
      # sqlite3 can't add foreign keys, so just skip it
    end
  end
end

#reverse_foreign_keys(table_name, name = nil) ⇒ Object

(abstract) Return the ForeignKeyDefinition objects for foreign key constraints defined on other tables that reference this table



159
# File 'lib/schema_plus/active_record/connection_adapters/abstract_adapter.rb', line 159

def reverse_foreign_keys(table_name, name = nil) raise "Internal Error: Connection adapter didn't override abstract function"; [] end

#sql_for_function(function_name) ⇒ Object

(abstract) Return SQL definition for a given canonical function_name symbol. Currently, the only function to support is :now, which should return a DATETIME object for the current time.



171
# File 'lib/schema_plus/active_record/connection_adapters/abstract_adapter.rb', line 171

def sql_for_function(function_name) raise "Internal Error: Connection adapter didn't override abstract function"; end

#supports_partial_indexes?Boolean

Returns true if the database supports parital indexes (abstract; only Postgresql returns true)

Returns:

  • (Boolean)


112
113
114
# File 'lib/schema_plus/active_record/connection_adapters/abstract_adapter.rb', line 112

def supports_partial_indexes?
  false
end

#view_definition(view_name, name = nil) ⇒ Object

(abstract) Returns the SQL definition of a given view. This is the literal SQL would come after ‘CREATVE VIEW viewname AS ’ in the SQL statement to create a view.



151
# File 'lib/schema_plus/active_record/connection_adapters/abstract_adapter.rb', line 151

def view_definition(view_name, name = nil) raise "Internal Error: Connection adapter didn't override abstract function"; end

#views(name = nil) ⇒ Object

(abstract) Returns the names of all views, as an array of strings



146
# File 'lib/schema_plus/active_record/connection_adapters/abstract_adapter.rb', line 146

def views(name = nil) raise "Internal Error: Connection adapter didn't override abstract function"; [] end