pax_global_header 0000666 0000000 0000000 00000000064 12151724773 0014523 g ustar 00root root 0000000 0000000 52 comment=2b699b1ab5e70e2d9faa80a3a7db955ccb4c7a7b
ruby-foreigner-1.4.1/ 0000775 0000000 0000000 00000000000 12151724773 0014465 5 ustar 00root root 0000000 0000000 ruby-foreigner-1.4.1/MIT-LICENSE 0000664 0000000 0000000 00000002054 12151724773 0016122 0 ustar 00root root 0000000 0000000 Copyright (c) 2009 [name of plugin creator]
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
ruby-foreigner-1.4.1/README.rdoc 0000664 0000000 0000000 00000004215 12151724773 0016275 0 ustar 00root root 0000000 0000000 = Foreigner
{
}[http://travis-ci.org/matthuhiggins/foreigner]
Foreigner introduces a few methods to your migrations for adding and removing foreign key constraints. It also dumps foreign keys to schema.rb.
The following adapters are supported:
* mysql2
* postgres
* sqlite (foreign key methods are a no-op)
== Installation
Add the following to your Gemfile:
gem 'foreigner'
== API Examples
Foreigner adds two methods to migrations.
* add_foreign_key(from_table, to_table, options)
* remove_foreign_key(from_table, options)
(Options are documented in connection_adapters/abstract/schema_definitions.rb):
For example, given the following model:
class Comment < ActiveRecord::Base
belongs_to :post
end
class Post < ActiveRecord::Base
has_many :comments, dependent: :delete_all
end
You should add a foreign key in your migration:
add_foreign_key(:comments, :posts)
The :dependent option can be moved from the has_many definition to the foreign key:
add_foreign_key(:comments, :posts, dependent: :delete)
If the column is named article_id instead of post_id, use the :column option:
add_foreign_key(:comments, :posts, column: 'article_id')
A name can be specified for the foreign key constraint:
add_foreign_key(:comments, :posts, name: 'comment_article_foreign_key')
== Change Table Methods
Foreigner adds extra methods to create_table and change_table.
Create a new table with a foreign key:
create_table :products do |t|
t.string :name
t.integer :factory_id
t.foreign_key :factories
end
Add a missing foreign key to comments:
change_table :comments do |t|
t.foreign_key :posts, dependent: :delete
end
Remove an unwanted foreign key:
change_table :comments do |t|
t.remove_foreign_key :users
end
== Foreigner Add-ons
* {immigrant}[https://github.com/jenseng/immigrant] - generate a migration that includes all missing foreign keys.
* {sqlserver-foreigner}[https://github.com/cleblanc87/sqlserver-foreigner] - A plugin for SQL Server.
== License
Copyright (c) 2012 Matthew Higgins, released under the MIT license
ruby-foreigner-1.4.1/Rakefile 0000664 0000000 0000000 00000000617 12151724773 0016136 0 ustar 00root root 0000000 0000000 require 'rake'
# begin
# require 'bundler/setup'
# rescue LoadError
# puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
# end
desc 'Default: run unit tests.'
task :default => :test
require 'rake/testtask'
desc 'Test the foreigner plugin.'
Rake::TestTask.new(:test) do |t|
t.libs << 'lib'
t.libs << 'test'
t.pattern = 'test/**/*_test.rb'
t.verbose = true
end
ruby-foreigner-1.4.1/checksums.yaml.gz 0000664 0000000 0000000 00000000415 12151724773 0017755 0 ustar 00root root 0000000 0000000 ‹ Ÿ¬aQe;N@Dûœ"²½»ö:='ð—Š¥âôl(¡´FOó<·ÛíòþöŠ÷ËõúYK{ØËÇ÷ý*ÔÓP7¯ÆèeËÔb{ ÷Â`=Ü/ó°¯_®o1_X†VÄœ*îAijX|
Ðx¶.¤½–š-27©R˜0C¥l¤©à´•²fM`,G¡I•kž&Om{—ìNÏ*î)2l¢-rb%Tiv¤[4äï?›rW•J{'QQJ²W¸ŸåH5娳U=áìÇ
(<¬ÝÒXå»OÖâ&ä:%Eùhçs6°ÏÖ@†+éòÄA,O¢ ruby-foreigner-1.4.1/lib/ 0000775 0000000 0000000 00000000000 12151724773 0015233 5 ustar 00root root 0000000 0000000 ruby-foreigner-1.4.1/lib/foreigner.rb 0000664 0000000 0000000 00000002143 12151724773 0017540 0 ustar 00root root 0000000 0000000 require 'active_support/all'
module Foreigner
extend ActiveSupport::Autoload
autoload :Adapter
autoload :SchemaDumper
module ConnectionAdapters
extend ActiveSupport::Autoload
autoload :Sql2003
autoload_under 'abstract' do
autoload :ForeignKeyDefinition
autoload :SchemaDefinitions
autoload :SchemaStatements
autoload :Table
autoload :TableDefinition
end
end
module Migration
autoload :CommandRecorder, 'foreigner/migration/command_recorder'
end
end
Foreigner::Adapter.register 'mysql', 'foreigner/connection_adapters/mysql_adapter'
Foreigner::Adapter.register 'mysql2', 'foreigner/connection_adapters/mysql2_adapter'
Foreigner::Adapter.register 'jdbcmysql', 'foreigner/connection_adapters/mysql2_adapter'
Foreigner::Adapter.register 'postgresql', 'foreigner/connection_adapters/postgresql_adapter'
Foreigner::Adapter.register 'jdbcpostgresql', 'foreigner/connection_adapters/postgresql_adapter'
Foreigner::Adapter.register 'sqlite3', 'foreigner/connection_adapters/noop_adapter'
require 'foreigner/loader'
require 'foreigner/railtie' if defined?(Rails)
ruby-foreigner-1.4.1/lib/foreigner/ 0000775 0000000 0000000 00000000000 12151724773 0017213 5 ustar 00root root 0000000 0000000 ruby-foreigner-1.4.1/lib/foreigner/adapter.rb 0000664 0000000 0000000 00000001207 12151724773 0021160 0 ustar 00root root 0000000 0000000 module Foreigner
class Adapter
class_attribute :registered
self.registered = {}
class << self
def register(adapter_name, file_name)
registered[adapter_name] = file_name
end
def load!
if registered.key?(configured_name)
require registered[configured_name]
else
p "Database adapter #{configured_name} not supported. Use:\n" +
"Foreigner::Adapter.register '#{configured_name}', 'path/to/adapter'"
end
end
def configured_name
@configured_name ||= ActiveRecord::Base.connection_pool.spec.config[:adapter]
end
end
end
end
ruby-foreigner-1.4.1/lib/foreigner/connection_adapters/ 0000775 0000000 0000000 00000000000 12151724773 0023235 5 ustar 00root root 0000000 0000000 ruby-foreigner-1.4.1/lib/foreigner/connection_adapters/abstract/ 0000775 0000000 0000000 00000000000 12151724773 0025040 5 ustar 00root root 0000000 0000000 ruby-foreigner-1.4.1/lib/foreigner/connection_adapters/abstract/foreign_key_definition.rb 0000664 0000000 0000000 00000000225 12151724773 0032075 0 ustar 00root root 0000000 0000000 module Foreigner
module ConnectionAdapters
class ForeignKeyDefinition < Struct.new(:from_table, :to_table, :options) #:nodoc:
end
end
end ruby-foreigner-1.4.1/lib/foreigner/connection_adapters/abstract/schema_definitions.rb 0000664 0000000 0000000 00000000547 12151724773 0031226 0 ustar 00root root 0000000 0000000 module Foreigner
module ConnectionAdapters
module SchemaDefinitions
def self.included(base)
base::Table.class_eval do
include Foreigner::ConnectionAdapters::Table
end
base::TableDefinition.class_eval do
include Foreigner::ConnectionAdapters::TableDefinition
end
end
end
end
end
ruby-foreigner-1.4.1/lib/foreigner/connection_adapters/abstract/schema_statements.rb 0000664 0000000 0000000 00000006770 12151724773 0031106 0 ustar 00root root 0000000 0000000 module Foreigner
module ConnectionAdapters
module SchemaStatements
def self.included(base)
base::AbstractAdapter.class_eval do
include Foreigner::ConnectionAdapters::AbstractAdapter
end
end
end
module AbstractAdapter
def create_table(table_name, *args, &block)
definition = nil
super do |td|
definition = td # This is my trick to get the definition
block.call(td)
end
definition.foreign_keys.each do |to_table, options_list|
options_list.each do |options|
add_foreign_key(table_name, to_table, options)
end
end
end
def supports_foreign_keys?
false
end
# Adds a new foreign key to the +from_table+, referencing the primary key of +to_table+
#
# The foreign key will be named after the from and to tables unless you pass
# :name as an option.
#
# ===== Examples
# ====== Creating a foreign key
# add_foreign_key(:comments, :posts)
# generates
# ALTER TABLE `comments` ADD CONSTRAINT
# `comments_post_id_fk` FOREIGN KEY (`post_id`) REFERENCES `posts` (`id`)
#
# ====== Creating a named foreign key
# add_foreign_key(:comments, :posts, name: 'comments_belongs_to_posts')
# generates
# ALTER TABLE `comments` ADD CONSTRAINT
# `comments_belongs_to_posts` FOREIGN KEY (`post_id`) REFERENCES `posts` (`id`)
#
# ====== Creating a cascading foreign_key on a custom column
# add_foreign_key(:people, :people, column: 'best_friend_id', dependent: :nullify)
# generates
# ALTER TABLE `people` ADD CONSTRAINT
# `people_best_friend_id_fk` FOREIGN KEY (`best_friend_id`) REFERENCES `people` (`id`)
# ON DELETE SET NULL
#
# === Supported options
# [:column]
# Specify the column name on the from_table that references the to_table. By default this is guessed
# to be the singular name of the to_table with "_id" suffixed. So a to_table of :posts will use "post_id"
# as the default :column.
# [:primary_key]
# Specify the column name on the to_table that is referenced by this foreign key. By default this is
# assumed to be "id".
# [:name]
# Specify the name of the foreign key constraint. This defaults to use from_table and foreign key column.
# [:dependent]
# If set to :delete, the associated records in from_table are deleted when records in to_table table are deleted.
# If set to :nullify, the foreign key column is set to +NULL+.
# [:options]
# Any extra options you want appended to the foreign key definition.
def add_foreign_key(from_table, to_table, options = {})
end
# Remove the given foreign key from the table.
#
# ===== Examples
# ====== Remove the suppliers_company_id_fk in the suppliers table.
# remove_foreign_key :suppliers, :companies
# ====== Remove the foreign key named accounts_branch_id_fk in the accounts table.
# remove_foreign_key :accounts, column: :branch_id
# ====== Remove the foreign key named party_foreign_key in the accounts table.
# remove_foreign_key :accounts, name: :party_foreign_key
def remove_foreign_key(from_table, options)
end
# Return the foreign keys for the schema_dumper
def foreign_keys(table_name)
[]
end
end
end
end
ruby-foreigner-1.4.1/lib/foreigner/connection_adapters/abstract/table.rb 0000664 0000000 0000000 00000004060 12151724773 0026454 0 ustar 00root root 0000000 0000000 module Foreigner
module ConnectionAdapters
module Table
extend ActiveSupport::Concern
included do
alias_method_chain :references, :foreign_keys
end
# Adds a new foreign key to the table. +to_table+ can be a single Symbol, or
# an Array of Symbols. See SchemaStatements#add_foreign_key
#
# ===== Examples
# ====== Creating a simple foreign key
# t.foreign_key(:people)
# ====== Defining the column
# t.foreign_key(:people, column: :sender_id)
# ====== Creating a named foreign key
# t.foreign_key(:people, column: :sender_id, name: 'sender_foreign_key')
# ====== Defining the column of the +to_table+.
# t.foreign_key(:people, column: :sender_id, primary_key: :person_id)
def foreign_key(to_table, options = {})
@base.add_foreign_key(@table_name, to_table, options)
end
# Remove the given foreign key from the table.
#
# ===== Examples
# ====== Remove the suppliers_company_id_fk in the suppliers table.
# change_table :suppliers do |t|
# t.remove_foreign_key :companies
# end
# ====== Remove the foreign key named accounts_branch_id_fk in the accounts table.
# change_table :accounts do |t|
# t.remove_foreign_key column: :branch_id
# end
# ====== Remove the foreign key named party_foreign_key in the accounts table.
# change_table :accounts do |t|
# t.remove_foreign_key name: :party_foreign_key
# end
def remove_foreign_key(options)
@base.remove_foreign_key(@table_name, options)
end
# Deprecated
def references_with_foreign_keys(*args)
options = args.extract_options!
if fk_options = options.delete(:foreign_key)
p ActiveSupport::Deprecation.send(:deprecation_message, caller,
":foreign_key in t.references is deprecated. " \
"Use t.foreign_key instead")
end
references_without_foreign_keys(*(args.dup << options))
end
end
end
end ruby-foreigner-1.4.1/lib/foreigner/connection_adapters/abstract/table_definition.rb 0000664 0000000 0000000 00000000444 12151724773 0030666 0 ustar 00root root 0000000 0000000 module Foreigner
module ConnectionAdapters
module TableDefinition
def foreign_key(to_table, options = {})
foreign_keys[to_table] ||= []
foreign_keys[to_table] << options
end
def foreign_keys
@foreign_keys ||= {}
end
end
end
end ruby-foreigner-1.4.1/lib/foreigner/connection_adapters/mysql2_adapter.rb 0000664 0000000 0000000 00000003551 12151724773 0026515 0 ustar 00root root 0000000 0000000 module Foreigner
module ConnectionAdapters
module Mysql2Adapter
include Foreigner::ConnectionAdapters::Sql2003
def remove_foreign_key_sql(table, options)
if Hash === options
foreign_key_name = foreign_key_name(table, options[:column], options)
else
foreign_key_name = foreign_key_name(table, "#{options.to_s.singularize}_id")
end
"DROP FOREIGN KEY #{quote_column_name(foreign_key_name)}"
end
def foreign_keys(table_name)
fk_info = select_all %{
SELECT fk.referenced_table_name as 'to_table'
,fk.referenced_column_name as 'primary_key'
,fk.column_name as 'column'
,fk.constraint_name as 'name'
FROM information_schema.key_column_usage fk
WHERE fk.referenced_column_name is not null
AND fk.table_schema = '#{@config[:database]}'
AND fk.table_name = '#{table_name}'
}
create_table_info = select_one("SHOW CREATE TABLE #{quote_table_name(table_name)}")["Create Table"]
fk_info.map do |row|
options = {:column => row['column'], :name => row['name'], :primary_key => row['primary_key']}
if create_table_info =~ /CONSTRAINT #{quote_column_name(row['name'])} FOREIGN KEY .* REFERENCES .* ON DELETE (CASCADE|SET NULL|RESTRICT)/
options[:dependent] = case $1
when 'CASCADE' then :delete
when 'SET NULL' then :nullify
when 'RESTRICT' then :restrict
end
end
ForeignKeyDefinition.new(table_name, row['to_table'], options)
end
end
end
end
end
[:Mysql2Adapter, :JdbcAdapter].each do |adapter|
begin
ActiveRecord::ConnectionAdapters.const_get(adapter).class_eval do
include Foreigner::ConnectionAdapters::Mysql2Adapter
end
rescue
end
end ruby-foreigner-1.4.1/lib/foreigner/connection_adapters/mysql_adapter.rb 0000664 0000000 0000000 00000000133 12151724773 0026424 0 ustar 00root root 0000000 0000000 p "WARNING: Please upgrade to mysql2. The old mysql adapter is not supported by foreigner." ruby-foreigner-1.4.1/lib/foreigner/connection_adapters/noop_adapter.rb 0000664 0000000 0000000 00000000165 12151724773 0026237 0 ustar 00root root 0000000 0000000 module Foreigner
module ConnectionAdapters
module NoopAdapter
# Used mainly for sqlite3
end
end
end ruby-foreigner-1.4.1/lib/foreigner/connection_adapters/postgresql_adapter.rb 0000664 0000000 0000000 00000002754 12151724773 0027475 0 ustar 00root root 0000000 0000000 module Foreigner
module ConnectionAdapters
module PostgreSQLAdapter
include Foreigner::ConnectionAdapters::Sql2003
def foreign_keys(table_name)
fk_info = select_all %{
SELECT t2.relname AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confdeltype AS dependency
FROM pg_constraint c
JOIN pg_class t1 ON c.conrelid = t1.oid
JOIN pg_class t2 ON c.confrelid = t2.oid
JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
JOIN pg_namespace t3 ON c.connamespace = t3.oid
WHERE c.contype = 'f'
AND t1.relname = '#{table_name}'
AND t3.nspname = ANY (current_schemas(false))
ORDER BY c.conname
}
fk_info.map do |row|
options = {:column => row['column'], :name => row['name'], :primary_key => row['primary_key']}
options[:dependent] = case row['dependency']
when 'c' then :delete
when 'n' then :nullify
when 'r' then :restrict
end
ForeignKeyDefinition.new(table_name, row['to_table'], options)
end
end
end
end
end
[:PostgreSQLAdapter, :JdbcAdapter].each do |adapter|
begin
ActiveRecord::ConnectionAdapters.const_get(adapter).class_eval do
include Foreigner::ConnectionAdapters::PostgreSQLAdapter
end
rescue
end
end ruby-foreigner-1.4.1/lib/foreigner/connection_adapters/sql2003.rb 0000664 0000000 0000000 00000004264 12151724773 0024674 0 ustar 00root root 0000000 0000000 module Foreigner
module ConnectionAdapters
module Sql2003
def supports_foreign_keys?
true
end
def drop_table(*args)
options = args.extract_options!
if options[:force]
disable_referential_integrity { super }
else
super
end
end
def add_foreign_key(from_table, to_table, options = {})
sql = "ALTER TABLE #{quote_table_name(from_table)} #{add_foreign_key_sql(from_table, to_table, options)}"
execute(sql)
end
def add_foreign_key_sql(from_table, to_table, options = {})
column = options[:column] || "#{to_table.to_s.singularize}_id"
foreign_key_name = foreign_key_name(from_table, column, options)
primary_key = options[:primary_key] || "id"
dependency = dependency_sql(options[:dependent])
sql =
"ADD CONSTRAINT #{quote_column_name(foreign_key_name)} " +
"FOREIGN KEY (#{quote_column_name(column)}) " +
"REFERENCES #{quote_table_name(ActiveRecord::Migrator.proper_table_name(to_table))}(#{primary_key})"
sql << " #{dependency}" if dependency.present?
sql << " #{options[:options]}" if options[:options]
sql
end
def remove_foreign_key(table, options)
execute "ALTER TABLE #{quote_table_name(table)} #{remove_foreign_key_sql(table, options)}"
end
def remove_foreign_key_sql(table, options)
if Hash === options
foreign_key_name = foreign_key_name(table, options[:column], options)
else
foreign_key_name = foreign_key_name(table, "#{options.to_s.singularize}_id")
end
"DROP CONSTRAINT #{quote_column_name(foreign_key_name)}"
end
private
def foreign_key_name(table, column, options = {})
if options[:name]
options[:name]
else
"#{table}_#{column}_fk"
end
end
def dependency_sql(dependency)
case dependency
when :nullify then "ON DELETE SET NULL"
when :delete then "ON DELETE CASCADE"
when :restrict then "ON DELETE RESTRICT"
else ""
end
end
end
end
end ruby-foreigner-1.4.1/lib/foreigner/loader.rb 0000664 0000000 0000000 00000001035 12151724773 0021005 0 ustar 00root root 0000000 0000000 module Foreigner
def self.load
ActiveRecord::ConnectionAdapters.module_eval do
include Foreigner::ConnectionAdapters::SchemaStatements
include Foreigner::ConnectionAdapters::SchemaDefinitions
end
ActiveRecord::SchemaDumper.class_eval do
include Foreigner::SchemaDumper
end
if defined?(ActiveRecord::Migration::CommandRecorder)
ActiveRecord::Migration::CommandRecorder.class_eval do
include Foreigner::Migration::CommandRecorder
end
end
Foreigner::Adapter.load!
end
end ruby-foreigner-1.4.1/lib/foreigner/migration/ 0000775 0000000 0000000 00000000000 12151724773 0021204 5 ustar 00root root 0000000 0000000 ruby-foreigner-1.4.1/lib/foreigner/migration/command_recorder.rb 0000664 0000000 0000000 00000001220 12151724773 0025027 0 ustar 00root root 0000000 0000000 module Foreigner
module Migration
module CommandRecorder
def add_foreign_key(*args)
record(:add_foreign_key, args)
end
def remove_foreign_key(*args)
record(:remove_foreign_key, args)
end
def invert_add_foreign_key(args)
from_table, to_table, add_options = *args
add_options ||= {}
if add_options[:name]
options = {:name => add_options[:name]}
elsif add_options[:column]
options = {:column => add_options[:column]}
else
options = to_table
end
[:remove_foreign_key, [from_table, options]]
end
end
end
end ruby-foreigner-1.4.1/lib/foreigner/railtie.rb 0000664 0000000 0000000 00000000276 12151724773 0021176 0 ustar 00root root 0000000 0000000 module Foreigner
class Railtie < Rails::Railtie
initializer 'foreigner.load_adapter' do
ActiveSupport.on_load :active_record do
Foreigner.load
end
end
end
end ruby-foreigner-1.4.1/lib/foreigner/schema_dumper.rb 0000664 0000000 0000000 00000004152 12151724773 0022356 0 ustar 00root root 0000000 0000000 module Foreigner
module SchemaDumper
extend ActiveSupport::Concern
included do
alias_method_chain :tables, :foreign_keys
end
module ClassMethods
def dump_foreign_key(foreign_key)
statement_parts = [ ('add_foreign_key ' + remove_prefix_and_suffix(foreign_key.from_table).inspect) ]
statement_parts << remove_prefix_and_suffix(foreign_key.to_table).inspect
statement_parts << (':name => ' + foreign_key.options[:name].inspect)
if foreign_key.options[:column] != "#{remove_prefix_and_suffix(foreign_key.to_table).singularize}_id"
statement_parts << (':column => ' + foreign_key.options[:column].inspect)
end
if foreign_key.options[:primary_key] != 'id'
statement_parts << (':primary_key => ' + foreign_key.options[:primary_key].inspect)
end
if foreign_key.options[:dependent].present?
statement_parts << (':dependent => ' + foreign_key.options[:dependent].inspect)
end
statement_parts.join(', ')
end
def remove_prefix_and_suffix(table)
table.gsub(/^(#{ActiveRecord::Base.table_name_prefix})(.+)(#{ActiveRecord::Base.table_name_suffix})$/, "\\2")
end
end
def tables_with_foreign_keys(stream)
tables_without_foreign_keys(stream)
@connection.tables.sort.each do |table|
next if ['schema_migrations', ignore_tables].flatten.any? do |ignored|
case ignored
when String; table == ignored
when Regexp; table =~ ignored
else
raise StandardError, 'ActiveRecord::SchemaDumper.ignore_tables accepts an array of String and / or Regexp values.'
end
end
foreign_keys(table, stream)
end
end
private
def foreign_keys(table_name, stream)
if (foreign_keys = @connection.foreign_keys(table_name)).any?
add_foreign_key_statements = foreign_keys.map do |foreign_key|
' ' + self.class.dump_foreign_key(foreign_key)
end
stream.puts add_foreign_key_statements.sort.join("\n")
stream.puts
end
end
end
end
ruby-foreigner-1.4.1/metadata.yml 0000664 0000000 0000000 00000005742 12151724773 0017000 0 ustar 00root root 0000000 0000000 --- !ruby/object:Gem::Specification
name: foreigner
version: !ruby/object:Gem::Version
version: 1.4.1
platform: ruby
authors:
- Matthew Higgins
autorequire:
bindir: bin
cert_chain: []
date: 2013-04-07 00:00:00.000000000 Z
dependencies:
- !ruby/object:Gem::Dependency
name: activerecord
requirement: !ruby/object:Gem::Requirement
requirements:
- - '>='
- !ruby/object:Gem::Version
version: 3.0.0
type: :runtime
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - '>='
- !ruby/object:Gem::Version
version: 3.0.0
- !ruby/object:Gem::Dependency
name: activerecord
requirement: !ruby/object:Gem::Requirement
requirements:
- - '>='
- !ruby/object:Gem::Version
version: 3.1.0
type: :development
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - '>='
- !ruby/object:Gem::Version
version: 3.1.0
description: Adds helpers to migrations and dumps foreign keys to schema.rb
email: developer@matthewhiggins.com
executables: []
extensions: []
extra_rdoc_files:
- README.rdoc
files:
- MIT-LICENSE
- Rakefile
- README.rdoc
- lib/foreigner/adapter.rb
- lib/foreigner/connection_adapters/abstract/foreign_key_definition.rb
- lib/foreigner/connection_adapters/abstract/schema_definitions.rb
- lib/foreigner/connection_adapters/abstract/schema_statements.rb
- lib/foreigner/connection_adapters/abstract/table.rb
- lib/foreigner/connection_adapters/abstract/table_definition.rb
- lib/foreigner/connection_adapters/mysql2_adapter.rb
- lib/foreigner/connection_adapters/mysql_adapter.rb
- lib/foreigner/connection_adapters/noop_adapter.rb
- lib/foreigner/connection_adapters/postgresql_adapter.rb
- lib/foreigner/connection_adapters/sql2003.rb
- lib/foreigner/loader.rb
- lib/foreigner/migration/command_recorder.rb
- lib/foreigner/railtie.rb
- lib/foreigner/schema_dumper.rb
- lib/foreigner.rb
- test/foreigner/adapter_test.rb
- test/foreigner/connection_adapters/abstract/schema_statements_test.rb
- test/foreigner/connection_adapters/abstract/table_definition_test.rb
- test/foreigner/connection_adapters/mysql2_adapter_test.rb
- test/foreigner/connection_adapters/mysql_adapter_test.rb
- test/foreigner/connection_adapters/postgresql_adapter_test.rb
- test/foreigner/connection_adapters/sql2003_test.rb
- test/foreigner/migration/command_recorder_test.rb
- test/foreigner/schema_dumper_test.rb
- test/helper.rb
homepage: http://github.com/matthuhiggins/foreigner
licenses: []
metadata: {}
post_install_message:
rdoc_options: []
require_paths:
- lib
required_ruby_version: !ruby/object:Gem::Requirement
requirements:
- - '>='
- !ruby/object:Gem::Version
version: 1.8.7
required_rubygems_version: !ruby/object:Gem::Requirement
requirements:
- - '>='
- !ruby/object:Gem::Version
version: 1.3.5
requirements: []
rubyforge_project: foreigner
rubygems_version: 2.0.0
signing_key:
specification_version: 4
summary: Foreign Keys for Rails
test_files: []
ruby-foreigner-1.4.1/test/ 0000775 0000000 0000000 00000000000 12151724773 0015444 5 ustar 00root root 0000000 0000000 ruby-foreigner-1.4.1/test/foreigner/ 0000775 0000000 0000000 00000000000 12151724773 0017424 5 ustar 00root root 0000000 0000000 ruby-foreigner-1.4.1/test/foreigner/adapter_test.rb 0000664 0000000 0000000 00000000461 12151724773 0022431 0 ustar 00root root 0000000 0000000 require 'helper'
class Foreigner::AdapterTest < ActiveSupport::TestCase
test "load" do
Foreigner::Adapter.register 'foo', 'bar'
Foreigner::Adapter.expects(:configured_name).at_least_once.returns('foo')
Foreigner::Adapter.expects(:require).with('bar')
Foreigner::Adapter.load!
end
end ruby-foreigner-1.4.1/test/foreigner/connection_adapters/ 0000775 0000000 0000000 00000000000 12151724773 0023446 5 ustar 00root root 0000000 0000000 ruby-foreigner-1.4.1/test/foreigner/connection_adapters/abstract/ 0000775 0000000 0000000 00000000000 12151724773 0025251 5 ustar 00root root 0000000 0000000 ruby-foreigner-1.4.1/test/foreigner/connection_adapters/abstract/schema_statements_test.rb 0000664 0000000 0000000 00000000152 12151724773 0032342 0 ustar 00root root 0000000 0000000 require 'helper'
class Foreigner::ConnectionAdapters::SchemaStatementsTest < ActiveSupport::TestCase
end ruby-foreigner-1.4.1/test/foreigner/connection_adapters/abstract/table_definition_test.rb 0000664 0000000 0000000 00000001225 12151724773 0032134 0 ustar 00root root 0000000 0000000 require 'helper'
class Foreigner::ConnectionAdapters::TableDefinitionsTest < ActiveSupport::TestCase
class TestDefinition
include Foreigner::ConnectionAdapters::TableDefinition
end
test "foreign_key used once" do
definition = TestDefinition.new
definition.foreign_key :poops, and: :one;
assert_equal [{ and: :one }], definition.foreign_keys[:poops]
end
test "foreign_key used twice" do
definition = TestDefinition.new
definition.foreign_key :nodes, column: :from_id
definition.foreign_key :nodes, column: :to_id
assert_equal [{ column: :from_id }, { column: :to_id }],
definition.foreign_keys[:nodes]
end
end ruby-foreigner-1.4.1/test/foreigner/connection_adapters/mysql2_adapter_test.rb 0000664 0000000 0000000 00000001604 12151724773 0027762 0 ustar 00root root 0000000 0000000 require 'helper'
require 'foreigner/connection_adapters/mysql2_adapter'
class Foreigner::Mysql2AdapterTest < Foreigner::UnitTest
class Mysql2Adapter
include TestAdapterMethods
include Foreigner::ConnectionAdapters::Mysql2Adapter
end
setup do
@adapter = Mysql2Adapter.new
end
test 'remove_foreign_key_sql by table' do
assert_equal(
"DROP FOREIGN KEY `suppliers_company_id_fk`",
@adapter.remove_foreign_key_sql(:suppliers, :companies)
)
end
test 'remove_foreign_key_sql by name' do
assert_equal(
"DROP FOREIGN KEY `belongs_to_supplier`",
@adapter.remove_foreign_key_sql(:suppliers, :name => "belongs_to_supplier")
)
end
test 'remove_foreign_key_sql by column' do
assert_equal(
"DROP FOREIGN KEY `suppliers_ship_to_id_fk`",
@adapter.remove_foreign_key_sql(:suppliers, :column => "ship_to_id")
)
end
end ruby-foreigner-1.4.1/test/foreigner/connection_adapters/mysql_adapter_test.rb 0000664 0000000 0000000 00000000477 12151724773 0027707 0 ustar 00root root 0000000 0000000 require 'helper'
class Foreigner::MysqlAdapterTest < Foreigner::UnitTest
test 'warning' do
output = capture(:stdout) do
require 'foreigner/connection_adapters/mysql_adapter'
end
assert_match /WARNING: Please upgrade to mysql2. The old mysql adapter is not supported by foreigner./, output
end
end ruby-foreigner-1.4.1/test/foreigner/connection_adapters/postgresql_adapter_test.rb 0000664 0000000 0000000 00000000310 12151724773 0030727 0 ustar 00root root 0000000 0000000 require 'helper'
require 'foreigner/connection_adapters/postgresql_adapter'
class Foreigner::PostgreSQLAdapterTest < Foreigner::UnitTest
include Foreigner::ConnectionAdapters::PostgreSQLAdapter
end ruby-foreigner-1.4.1/test/foreigner/connection_adapters/sql2003_test.rb 0000664 0000000 0000000 00000006655 12151724773 0026152 0 ustar 00root root 0000000 0000000 require 'helper'
class Foreigner::Sql2003Test < Foreigner::UnitTest
class TestAdapter
include TestAdapterMethods
include Foreigner::ConnectionAdapters::Sql2003
end
setup do
@adapter = TestAdapter.new
end
test 'drop_table without force' do
@adapter.drop_table 'shoes'
assert !@adapter.instance_variable_get(:@disable_referential_integrity)
end
test 'drop_table with force' do
@adapter.drop_table 'shoes', force: true
assert @adapter.instance_variable_get(:@disable_referential_integrity)
end
test 'add_without_options' do
assert_equal(
"ALTER TABLE `employees` ADD CONSTRAINT `employees_company_id_fk` FOREIGN KEY (`company_id`) REFERENCES `companies`(id)",
@adapter.add_foreign_key(:employees, :companies)
)
end
test 'add_with_name' do
assert_equal(
"ALTER TABLE `employees` ADD CONSTRAINT `favorite_company_fk` FOREIGN KEY (`company_id`) REFERENCES `companies`(id)",
@adapter.add_foreign_key(:employees, :companies, :name => 'favorite_company_fk')
)
end
test 'add_with_column' do
assert_equal(
"ALTER TABLE `employees` ADD CONSTRAINT `employees_last_employer_id_fk` FOREIGN KEY (`last_employer_id`) REFERENCES `companies`(id)",
@adapter.add_foreign_key(:employees, :companies, :column => 'last_employer_id')
)
end
test 'add_with_column_and_name' do
assert_equal(
"ALTER TABLE `employees` ADD CONSTRAINT `favorite_company_fk` FOREIGN KEY (`last_employer_id`) REFERENCES `companies`(id)",
@adapter.add_foreign_key(:employees, :companies, :column => 'last_employer_id', :name => 'favorite_company_fk')
)
end
test 'add_with_delete_dependency' do
assert_equal(
"ALTER TABLE `employees` ADD CONSTRAINT `employees_company_id_fk` FOREIGN KEY (`company_id`) REFERENCES `companies`(id) " +
"ON DELETE CASCADE",
@adapter.add_foreign_key(:employees, :companies, :dependent => :delete)
)
end
test 'add_with_nullify_dependency' do
assert_equal(
"ALTER TABLE `employees` ADD CONSTRAINT `employees_company_id_fk` FOREIGN KEY (`company_id`) REFERENCES `companies`(id) " +
"ON DELETE SET NULL",
@adapter.add_foreign_key(:employees, :companies, :dependent => :nullify)
)
end
test 'add_with_restrict_dependency' do
assert_equal(
"ALTER TABLE `employees` ADD CONSTRAINT `employees_company_id_fk` FOREIGN KEY (`company_id`) REFERENCES `companies`(id) " +
"ON DELETE RESTRICT",
@adapter.add_foreign_key(:employees, :companies, :dependent => :restrict)
)
end
test 'add_with_options' do
assert_equal(
"ALTER TABLE `employees` ADD CONSTRAINT `employees_company_id_fk` FOREIGN KEY (`company_id`) REFERENCES `companies`(id) " +
"on delete foo",
@adapter.add_foreign_key(:employees, :companies, :options => 'on delete foo')
)
end
test 'remove_by_table' do
assert_equal(
"ALTER TABLE `suppliers` DROP CONSTRAINT `suppliers_company_id_fk`",
@adapter.remove_foreign_key(:suppliers, :companies)
)
end
test 'remove_by_name' do
assert_equal(
"ALTER TABLE `suppliers` DROP CONSTRAINT `belongs_to_supplier`",
@adapter.remove_foreign_key(:suppliers, :name => "belongs_to_supplier")
)
end
test 'remove_by_column' do
assert_equal(
"ALTER TABLE `suppliers` DROP CONSTRAINT `suppliers_ship_to_id_fk`",
@adapter.remove_foreign_key(:suppliers, :column => "ship_to_id")
)
end
end ruby-foreigner-1.4.1/test/foreigner/migration/ 0000775 0000000 0000000 00000000000 12151724773 0021415 5 ustar 00root root 0000000 0000000 ruby-foreigner-1.4.1/test/foreigner/migration/command_recorder_test.rb 0000664 0000000 0000000 00000002504 12151724773 0026305 0 ustar 00root root 0000000 0000000 require 'helper'
ActiveRecord::Migration::CommandRecorder.class_eval do
include ::Foreigner::Migration::CommandRecorder
end
class Foreigner::CommandRecorderTest < Foreigner::UnitTest
def setup
@recorder = ActiveRecord::Migration::CommandRecorder.new
end
test 'invert_add_foreign_key' do
@recorder.add_foreign_key(:employees, :companies)
remove = @recorder.inverse.first
assert_equal [:remove_foreign_key, [:employees, :companies]], remove
end
test 'invert_add_foreign_key with column' do
@recorder.add_foreign_key(:employees, :companies, :column => :place_id)
remove = @recorder.inverse.first
assert_equal [:remove_foreign_key, [:employees, {:column => :place_id}]], remove
end
test 'invert_add_foreign_key with name' do
@recorder.add_foreign_key(:employees, :companies, :name => 'the_best_fk', :column => :place_id)
remove = @recorder.inverse.first
assert_equal [:remove_foreign_key, [:employees, {:name => 'the_best_fk'}]], remove
@recorder.record :rename_table, [:old, :new]
rename = @recorder.inverse.first
assert_equal [:rename_table, [:new, :old]], rename
end
test 'remove_foreign_key is irreversible' do
@recorder.remove_foreign_key(:employees, :companies)
assert_raise ActiveRecord::IrreversibleMigration do
@recorder.inverse
end
end
end ruby-foreigner-1.4.1/test/foreigner/schema_dumper_test.rb 0000664 0000000 0000000 00000004633 12151724773 0023632 0 ustar 00root root 0000000 0000000 require 'helper'
class Foreigner::SchemaDumperTest < Foreigner::UnitTest
class MockConnection
def tables
[ 'foo', 'bar' ]
end
end
class MockSchemaDumper
cattr_accessor :ignore_tables
attr_accessor :processed_tables
def initialize
@connection = MockConnection.new
@processed_tables = []
end
def tables(stream)
end
def foreign_keys(table, stream)
processed_tables << table
end
include Foreigner::SchemaDumper
end
test 'dump_foreign_key' do
assert_dump "add_foreign_key \"foos\", \"bars\", :name => \"lulz\"", Foreigner::ConnectionAdapters::ForeignKeyDefinition.new('foos', 'bars', column: 'bar_id', primary_key: 'id', name: 'lulz')
assert_dump "add_foreign_key \"foos\", \"bars\", :name => \"lulz\", :primary_key => \"uuid\"", Foreigner::ConnectionAdapters::ForeignKeyDefinition.new('foos', 'bars', column: 'bar_id', primary_key: 'uuid', name: 'lulz')
assert_dump "add_foreign_key \"foos\", \"bars\", :name => \"lulz\", :dependent => :delete", Foreigner::ConnectionAdapters::ForeignKeyDefinition.new('foos', 'bars', column: 'bar_id', primary_key: 'id', name: 'lulz', dependent: :delete)
assert_dump "add_foreign_key \"foos\", \"bars\", :name => \"lulz\", :column => \"mamma_id\"", Foreigner::ConnectionAdapters::ForeignKeyDefinition.new('foos', 'bars', column: 'mamma_id', primary_key: 'id', name: 'lulz')
end
test 'all tables' do
MockSchemaDumper.ignore_tables = []
dumper = MockSchemaDumper.new
dumper.tables(StringIO.new)
assert_equal ['bar', 'foo'].to_set, dumper.processed_tables.to_set
end
test 'ignores tables' do
MockSchemaDumper.ignore_tables = ['foo']
dumper = MockSchemaDumper.new
dumper.tables(StringIO.new)
assert_equal ['bar'].to_set, dumper.processed_tables.to_set
end
test 'removes table name suffix and prefix' do
begin
ActiveRecord::Base.table_name_prefix = 'pre_'
ActiveRecord::Base.table_name_suffix = '_suf'
assert_dump "add_foreign_key \"foos\", \"bars\", :name => \"lulz\"", Foreigner::ConnectionAdapters::ForeignKeyDefinition.new('pre_foos_suf', 'pre_bars_suf', column: 'bar_id', primary_key: 'id', name: 'lulz')
ensure
ActiveRecord::Base.table_name_suffix = ActiveRecord::Base.table_name_prefix = ''
end
end
private
def assert_dump(expected, definition)
assert_equal expected, MockSchemaDumper.dump_foreign_key(definition)
end
end
ruby-foreigner-1.4.1/test/helper.rb 0000664 0000000 0000000 00000002014 12151724773 0017245 0 ustar 00root root 0000000 0000000 require 'bundler/setup'
Bundler.require(:default)
require 'test/unit'
require 'active_record'
require 'mocha'
# Foreigner::Adapter.registered.values.each do |file_name|
# require file_name
# end
module TestAdapterMethods
def execute(sql, name = nil)
sql_statements << sql
sql
end
def quote_table_name(name)
quote_column_name(name).gsub('.', '`.`')
end
def quote_column_name(name)
"`#{name}`"
end
def sql_statements
@sql_statements ||= []
end
def drop_table(name, options = {})
end
def disable_referential_integrity
@disable_referential_integrity = true
yield
end
private
def execute(sql, name = nil)
sql_statements << sql
sql
end
end
module Foreigner
class UnitTest < ActiveSupport::TestCase
end
class IntegrationTest < ActiveSupport::TestCase
def with_migration(&blk)
migration = Class.new(ActiveRecord::Migration)
migration.singleton_class do
define_method(:up, &blk)
end
migration
end
end
end