Class: ActiveRecord::ConnectionAdapters::TableDefinition

Inherits:
Object
  • Object
show all
Includes:
Constraints::Postgresql
Defined in:
lib/activerecord_constraints.rb

Instance Method Summary collapse

Methods included from Constraints::Sql

#check_str, #column_to_str, #deferrable_str, #has_constraint, #initially_str, #name_str, #reference_str, #suffix_str, #table_str, #to_db_string, #unique_str

Instance Method Details

#check(*args) ⇒ Object

Specify a check table constrant. In the simple case, this can be done as:

create_table :users do |t|
  t.string  :name,     :null    => false
  t.string  :password, :null    => false
  t.boolean :admin,    :default => false
  t.timestamps
  t.check "password_check(password)"
end

Alternate forms for the above are:

  1. To give the constraint a name of “password_constraint”:

    t.check "password_check(password)", :name => "password_constraint"
    
  2. Flip the above around:

    t.check "password_constraint", expr => "password_check(password)"
    
  3. Same but perhaps more obvious:

    t.check name => "password_constraint", expr => "password_check(password)"
    

The expression must be specified, the name of the constraint is always optional



424
425
426
427
# File 'lib/activerecord_constraints.rb', line 424

def check(*args)
  ActiveRecord::Base.logger.debug("IN: TableDefinition#check")
  extra_str << ", #{check_str(column, options, false)}"
end

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

As the table is being defined, we capture the call to column. column (now called column_with_constraints returns self which is a TableDefinition. TableDefinition#[] returns the column for the name passed. We add an @options attribute for later use (see ColumnDefinition#options=).



296
297
298
299
300
301
# File 'lib/activerecord_constraints.rb', line 296

def column_with_constraints(name, type, options = { })
  ActiveRecord::Base.logger.debug("IN: TableDefinition#column_with_constraints for #{name}")
  ret = column_without_constraints(name, type, options)
  ret[name].options = options
  ret
end

#fk(*names) ⇒ Object

fk stands for foreign key. This is more like a macro that defines a column that is a foreign key. This:

create_table :foos do |t|
  # Make a foreign key to the id column in the bars table
  t.fk :bar_id
end

is the equivalent of this:

create_table :foos do |t|
  # Make a foreign key to the id column in the bars table
  t.integer :bar_id, :null => false, :reference => true,
      :delete => :cascade, :deferrable => true
end

which is the same as this:

create_table :foos do |t|
  # Make a foreign key to the id column in the bars table
  t.integer :bar_id, :null => false, :reference => true,
      :delete => :cascade, :deferrable => true,
      :table_name => :bars, :foreign_key => :id
end

These defaults were chosen because despite common practice, nulls in databases should be avoided, the constraint needs to be deferrable to get fixtures to work, and cascade on delete keeps things simple.

But this should work also:

create_table :foos do |t|
  # Make a foreign key to the id column in the bars table
  t.fk :bar_id, :toad_id, :banana_id, :delete => :no_action
end


352
353
354
355
356
357
358
359
360
# File 'lib/activerecord_constraints.rb', line 352

def fk(*names)
  options = {
    :null => false,
    :reference => true,
    :delete => :cascade,
    :deferrable => true
  }.merge(names.last.is_a?(Hash) ? names.pop : { })
  self.integer(*names, options)
end

#reference(column, options = { }) ⇒ Object

Pass a column and options (which may be empty). The column name of foo_id, by default, creates a reference to table foos, column id. :table_name may be passed in options to specify the foreign table name. :foreign_key may be passed to specify the foreign column. Both the passed in column (first argument) as well as thee :foreign_key option may be an array. :delete option may be passed in with the appropriate value such as :restrict, :cascade, etc.

This might be broken because “deferrable” is not available where it use to be before.



398
399
400
401
# File 'lib/activerecord_constraints.rb', line 398

def reference(column, options = { })
  ActiveRecord::Base.logger.debug("IN: TableDefinition#reference")
  extra_str << ", #{reference_str(column, options, false)}"
end

#to_sql_with_constraintsObject

to_sql is called to transform the table definition into an sql statement. We insert ourselves into that so that we can append the extra string needed for the constraints added by the unique and references table definition methods.



308
309
310
311
# File 'lib/activerecord_constraints.rb', line 308

def to_sql_with_constraints
  ActiveRecord::Base.logger.debug("IN: TableDefinition#to_sql_with_constraints")
  to_sql_without_constraints + extra_str
end

#unique(*args) ⇒ Object

Add a “unique” method to TableDefinition. e.g.

create_table :users do |t|
  t.string  :name,  :null    => false
  t.boolean :admin, :default => false
  t.timestamps
  t.unique :name
end

A list of UNIQUE can be specified by simply listing the columns:

t.unique :name1, :name2, :name3

This produces separate constraints. To produce a specification where a set of columns needs to be unique, put the column names inside an array. Both can be done at the same time:

t.unique [ :name1, :name2 ], :name3

produces where the tulple (name1, name2) must be unique and the name3 column must also be unique.



379
380
381
382
383
# File 'lib/activerecord_constraints.rb', line 379

def unique(*args)
  ActiveRecord::Base.logger.debug("IN: TableDefinition#unique")
  options = { :unique => true }.merge(args.last.is_a?(Hash) ? args.pop : { })
  args.each { |arg| extra_str << ", #{unique_str(arg, options, false)}" }
end