Module: SchemaPlus::ActiveRecord::ConnectionAdapters::TableDefinition

Includes:
SchemaPlus::ActiveRecord::ColumnOptionsHandler
Defined in:
lib/schema_plus/active_record/connection_adapters/table_definition.rb

Overview

SchemaPlus adds several methods to TableDefinition, allowing indexes and foreign key constraints to be defined within a create_table block of a migration, allowing for better encapsulation and more DRY definitions.

For example, without SchemaPlus you might define a table like this:

create_table :widgets do |t|
   t.string :name
end
add_index :widgets, :name

But with SchemaPlus, the index can be defined within the create_table block, so you don't need to repeat the table name:

create_table :widgets do |t|
   t.string :name
   t.index :name
end

Even more DRY, you can define the index as part of the column definition, via:

create_table :widgets do |t|
   t.string :name, :index => true
end

For details about the :index option (including unique and multi-column indexes), see the documentation for Migration::ClassMethods#add_column

SchemaPlus also supports creation of foreign key constraints analogously, using Migration::ClassMethods#add_foreign_key or TableDefinition#foreign_key or as part of the column definition, for example:

create_table :posts do |t|  # not DRY
   t.integer :author_id
end
add_foreign_key :posts, :author_id, :references => :authors

create_table :posts do |t|  # DRYer
   t.integer :author_id
   t.foreign_key :author_id, :references => :authors
end

create_table :posts do |t|  # Dryest
   t.integer :author_id, :foreign_key => true
end

NOTE: In the standard configuration, SchemaPlus automatically creates foreign key constraints for columns whose names end in _id. So the above examples are redundant, unless automatic creation was disabled at initialization in the global Config.

SchemaPlus likewise by default automatically creates foreign key constraints for columns defined via t.references. However, SchemaPlus does not create foreign key constraints if the :polymorphic option is true

Finally, the configuration for foreign keys can be overriden on a per-table basis by passing Config options to Migration::ClassMethods#create_table, such as

create_table :students, :foreign_keys => {:auto_create => false} do
   t.integer :student_id
end

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from SchemaPlus::ActiveRecord::ColumnOptionsHandler

#schema_plus_handle_column_options, #schema_plus_normalize_column_options

Instance Attribute Details

#foreign_keysObject (readonly)

:nodoc:


70
71
72
# File 'lib/schema_plus/active_record/connection_adapters/table_definition.rb', line 70

def foreign_keys
  @foreign_keys
end

#schema_plus_configObject

:nodoc:


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

def schema_plus_config
  @schema_plus_config
end

Class Method Details

.included(base) ⇒ Object

:nodoc:


72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/schema_plus/active_record/connection_adapters/table_definition.rb', line 72

def self.included(base) #:nodoc:
  base.class_eval do
    alias_method_chain :initialize, :schema_plus
    alias_method_chain :column, :schema_plus
    alias_method_chain :references, :schema_plus
    alias_method_chain :belongs_to, :schema_plus
    alias_method_chain :primary_key, :schema_plus

    if ::ActiveRecord::VERSION::MAJOR.to_i < 4
      attr_accessor :name
      attr_accessor :indexes
      alias_method_chain :to_sql, :schema_plus
    end
  end
end

Instance Method Details

#belongs_to_with_schema_plus(*args) ⇒ Object

need detect :polymorphic at this level, because rails strips it out before calling #column (twice, once for _id and once for _type)


120
121
122
123
124
125
126
127
# File 'lib/schema_plus/active_record/connection_adapters/table_definition.rb', line 120

def belongs_to_with_schema_plus(*args) #:nodoc:
  options = args.extract_options!
  options[:references] = nil if options[:polymorphic]
  schema_plus_normalize_column_options(options)
  options[:_index] = options.delete(:index) unless options[:polymorphic] # usurp index creation from AR
  args << options
  belongs_to_without_schema_plus(*args)
end

#column_with_schema_plus(name, type, options = {}) ⇒ Object

:nodoc:


129
130
131
132
133
134
135
136
137
138
139
# File 'lib/schema_plus/active_record/connection_adapters/table_definition.rb', line 129

def column_with_schema_plus(name, type, options = {}) #:nodoc:
  schema_plus_normalize_column_options(options)
  # prevent AR from seeing :index => false as a request for an index
  if noindex = options[:index] == false
    options.delete(:index)
  end
  column_without_schema_plus(name, type, options)
  options[:index] = false if noindex
  schema_plus_handle_column_options(self.name, name, options, :config => schema_plus_config)
  self
end

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


154
155
156
157
158
159
# File 'lib/schema_plus/active_record/connection_adapters/table_definition.rb', line 154

def foreign_key(column_names, references_table_name, references_column_names, options = {})
  options.merge!(:column_names => column_names, :references_column_names => references_column_names)
  options.reverse_merge!(:name => ForeignKeyDefinition.default_name(self.name, column_names))
  @foreign_keys << ForeignKeyDefinition.new(self.name, AbstractAdapter.proper_table_name(references_table_name), options)
  self
end

#index(column_name, options = {}) ⇒ Object


149
150
151
# File 'lib/schema_plus/active_record/connection_adapters/table_definition.rb', line 149

def index(column_name, options={})
  @indexes << ::ActiveRecord::ConnectionAdapters::IndexDefinition.new(self.name, column_name, options)
end

#initialize_with_schema_plus(*args) ⇒ Object

:nodoc:


88
89
90
91
92
93
94
# File 'lib/schema_plus/active_record/connection_adapters/table_definition.rb', line 88

def initialize_with_schema_plus(*args) #:nodoc:
  initialize_without_schema_plus(*args)
  @foreign_keys = []
  if ::ActiveRecord::VERSION::MAJOR.to_i < 4
    @indexes = []
  end
end

#primary_key_with_schema_plus(name, type = :primary_key, options = {}) ⇒ Object

:nodoc:


97
98
99
# File 'lib/schema_plus/active_record/connection_adapters/table_definition.rb', line 97

def primary_key_with_schema_plus(name, options = {}) #:nodoc:
  column(name, :primary_key, options)
end

#references_with_schema_plus(*args) ⇒ Object

need detect :polymorphic at this level, because rails strips it out before calling #column (twice, once for _id and once for _type)


109
110
111
112
113
114
115
116
# File 'lib/schema_plus/active_record/connection_adapters/table_definition.rb', line 109

def references_with_schema_plus(*args) #:nodoc:
  options = args.extract_options!
  options[:references] = nil if options[:polymorphic]
  schema_plus_normalize_column_options(options)
  options[:_index] = options.delete(:index) unless options[:polymorphic] # usurp index creation from AR
  args << options
  references_without_schema_plus(*args)
end

#to_sql_with_schema_plusObject

:nodoc:


141
142
143
144
145
# File 'lib/schema_plus/active_record/connection_adapters/table_definition.rb', line 141

def to_sql_with_schema_plus #:nodoc:
  sql = to_sql_without_schema_plus
  sql << ', ' << @foreign_keys.map(&:to_sql) * ', ' unless @foreign_keys.empty?
  sql
end