kvs-foreigner 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 [name of plugin creator]
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,106 @@
1
+ Foreigner
2
+ =========
3
+
4
+ Rails does not come with methods to add foreign keys. Foreigner introduces a few
5
+ methods to your migrations for adding and removing foreign key constraints.
6
+
7
+ Since each adapter implements the API, migrations using Foreigner will continue to
8
+ work on databases that do not support foreign keys, such as sqlite3.
9
+
10
+ Installation
11
+ ------------
12
+
13
+ Install as a plugin:
14
+
15
+ ruby script/plugin install git://github.com/matthuhiggins/foreigner.git
16
+
17
+ Install as a gem by adding the following to environment.rb:
18
+
19
+ config.gem "matthuhiggins-foreigner", :lib => "foreigner"
20
+
21
+ API
22
+ ---
23
+
24
+ An adapter implementing the Foreigner API implements three methods.
25
+ (Options are documented in connection_adapters/abstract/schema_definitions.rb):
26
+
27
+ add_foreign_key(from_table, to_table, options)
28
+ remove_foreign_key(from_table, options)
29
+ foreign_keys(table_name)
30
+
31
+ Example
32
+ -------
33
+
34
+ The most common use of foreign keys is to reference a table that a model belongs to.
35
+ For example, given the following model:
36
+
37
+ class Comment < ActiveRecord::Base
38
+ belongs_to :post
39
+ end
40
+
41
+ class Post < ActiveRecord::Base
42
+ has_many :comments, :dependent => :delete_all
43
+ end
44
+
45
+ You should add a foreign key in your migration:
46
+
47
+ add_foreign_key(:comments, :posts)
48
+
49
+ The :dependent option can be moved from the has_many definition to the foreign key:
50
+
51
+ add_foreign_key(:comments, :posts, :dependent => :delete)
52
+
53
+ If the column is named article_id instead of post_id, use the :column option:
54
+
55
+ add_foreign_key(:comments, :posts, :column => 'article_id')
56
+
57
+ Lastly, a name can be specified for the foreign key constraint:
58
+
59
+ add_foreign_key(:comments, :posts, :name => 'comment_article_foreign_key')
60
+
61
+ Create/Change Table Shorthand
62
+ -----------------------------
63
+
64
+ Foreigner adds extra behavior to create_table and change_table, which lets you define foreign keys using shorthand.
65
+
66
+ Create the comments table with a foreign key to posts:
67
+
68
+ create_table :comments do |t|
69
+ t.integer :post_id
70
+ t.foreign_key :posts
71
+ end
72
+
73
+ Add a missing foreign key to comments:
74
+
75
+ change_table :comments do |t|
76
+ t.foreign_key :posts, :dependent => :delete
77
+ end
78
+
79
+ t.foreign_key accepts the same options as add_foreign_key.
80
+
81
+
82
+ Additional t.references option
83
+ ------------------------------
84
+
85
+ Foreigner extends table.references with the :foreign_key option. Pass true, and the default
86
+ foreign key options are used:
87
+
88
+ create_table :comments do |t|
89
+ t.references :post, :foreign_key => true
90
+ end
91
+
92
+ An options hash can also be passed. It accepts the same options as add_foreign_key:
93
+
94
+ change_table :comments do |t|
95
+ t.references :author, :foreign_key => {:dependent => :destroy}
96
+ end
97
+
98
+ By default, t.references will not generate a foreign key.
99
+
100
+ schema.rb
101
+ ---------
102
+
103
+ Similar to indexes, the foreign keys in your database are automatically dumped to schema.rb.
104
+ This allows you to use foreign keys without fighting Rails!
105
+
106
+ Copyright (c) 2009 Matthew Higgins, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the foreigner plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.libs << 'test'
12
+ t.pattern = 'test/**/*_test.rb'
13
+ t.verbose = true
14
+ end
15
+
16
+ desc 'Generate documentation for the foreigner plugin.'
17
+ Rake::RDocTask.new(:rdoc) do |rdoc|
18
+ rdoc.rdoc_dir = 'rdoc'
19
+ rdoc.title = 'Foreigner'
20
+ rdoc.options << '--line-numbers' << '--inline-source'
21
+ rdoc.rdoc_files.include('README')
22
+ rdoc.rdoc_files.include('lib/**/*.rb')
23
+ end
data/lib/foreigner.rb ADDED
@@ -0,0 +1,21 @@
1
+ require 'foreigner/connection_adapters/abstract/schema_statements'
2
+ require 'foreigner/connection_adapters/abstract/schema_definitions'
3
+ require 'foreigner/connection_adapters/sql_2003'
4
+ require 'foreigner/schema_dumper'
5
+
6
+ module ActiveRecord
7
+ module ConnectionAdapters
8
+ include Foreigner::ConnectionAdapters::SchemaStatements
9
+ include Foreigner::ConnectionAdapters::SchemaDefinitions
10
+ end
11
+
12
+ SchemaDumper.class_eval do
13
+ include Foreigner::SchemaDumper
14
+ end
15
+
16
+ Base.class_eval do
17
+ if %w(MySQL PostgreSQL).include? connection.adapter_name
18
+ require "foreigner/connection_adapters/#{connection.adapter_name.downcase}_adapter"
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,155 @@
1
+ module Foreigner
2
+ module ConnectionAdapters
3
+ class ForeignKeyDefinition < Struct.new(:from_table, :to_table, :options) #:nodoc:
4
+ end
5
+
6
+ module SchemaDefinitions
7
+ def self.included(base)
8
+ base::TableDefinition.class_eval do
9
+ include Foreigner::ConnectionAdapters::TableDefinition
10
+ end
11
+
12
+ base::Table.class_eval do
13
+ include Foreigner::ConnectionAdapters::Table
14
+ end
15
+ end
16
+ end
17
+
18
+ module TableDefinition
19
+ class ForeignKey < Struct.new(:base, :to_table, :options)
20
+ def to_sql
21
+ base.foreign_key_definition(to_table, options)
22
+ end
23
+ alias to_s :to_sql
24
+ end
25
+
26
+ def self.included(base)
27
+ base.class_eval do
28
+ include InstanceMethods
29
+ alias_method_chain :references, :foreign_keys
30
+ alias_method_chain :to_sql, :foreign_keys
31
+ end
32
+ end
33
+
34
+ module InstanceMethods
35
+ # Adds a :foreign_key option to TableDefinition.references.
36
+ # If :foreign_key is true, a foreign key constraint is added to the table.
37
+ # You can also specify a hash, which is passed as foreign key options.
38
+ #
39
+ # ===== Examples
40
+ # ====== Add goat_id column and a foreign key to the goats table.
41
+ # t.references(:goat, :foreign_key => true)
42
+ # ====== Add goat_id column and a cascading foreign key to the goats table.
43
+ # t.references(:goat, :foreign_key => {:dependent => :delete})
44
+ #
45
+ # Note: No foreign key is created if :polymorphic => true is used.
46
+ # Note: If no name is specified, the database driver creates one for you!
47
+ def references_with_foreign_keys(*args)
48
+ options = args.extract_options!
49
+ fk_options = options.delete(:foreign_key)
50
+
51
+ if fk_options && !options[:polymorphic]
52
+ fk_options = {} if fk_options == true
53
+ args.each { |to_table| foreign_key(to_table, fk_options) }
54
+ end
55
+
56
+ references_without_foreign_keys(*(args << options))
57
+ end
58
+
59
+ # Defines a foreign key for the table. +to_table+ can be a single Symbol, or
60
+ # an Array of Symbols. See SchemaStatements#add_foreign_key
61
+ #
62
+ # ===== Examples
63
+ # ====== Creating a simple foreign key
64
+ # t.foreign_key(:people)
65
+ # ====== Defining the column
66
+ # t.foreign_key(:people, :column => :sender_id)
67
+ # ====== Creating a named foreign key
68
+ # t.foreign_key(:people, :column => :sender_id, :name => 'sender_foreign_key')
69
+ # ====== Defining the column of the +to_table+.
70
+ # t.foreign_key(:people, :column => :sender_id, :primary_key => :person_id)
71
+ def foreign_key(to_table, options = {})
72
+ if @base.supports_foreign_keys?
73
+ to_table = to_table.to_s.pluralize if ActiveRecord::Base.pluralize_table_names
74
+ foreign_keys << ForeignKey.new(@base, to_table, options)
75
+ end
76
+ end
77
+
78
+ def to_sql_with_foreign_keys
79
+ sql = to_sql_without_foreign_keys
80
+ sql << ', ' << (foreign_keys * ', ') if foreign_keys.present?
81
+ sql
82
+ end
83
+
84
+ private
85
+ def foreign_keys
86
+ @foreign_keys ||= []
87
+ end
88
+ end
89
+ end
90
+
91
+ module Table
92
+ def self.included(base)
93
+ base.class_eval do
94
+ include InstanceMethods
95
+ alias_method_chain :references, :foreign_keys
96
+ end
97
+ end
98
+
99
+ module InstanceMethods
100
+ # Adds a new foreign key to the table. +to_table+ can be a single Symbol, or
101
+ # an Array of Symbols. See SchemaStatements#add_foreign_key
102
+ #
103
+ # ===== Examples
104
+ # ====== Creating a simple foreign key
105
+ # t.foreign_key(:people)
106
+ # ====== Defining the column
107
+ # t.foreign_key(:people, :column => :sender_id)
108
+ # ====== Creating a named foreign key
109
+ # t.foreign_key(:people, :column => :sender_id, :name => 'sender_foreign_key')
110
+ # ====== Defining the column of the +to_table+.
111
+ # t.foreign_key(:people, :column => :sender_id, :primary_key => :person_id)
112
+ def foreign_key(to_table, options = {})
113
+ @base.add_foreign_key(@table_name, to_table, options)
114
+ end
115
+
116
+ # Remove the given foreign key from the table.
117
+ #
118
+ # ===== Examples
119
+ # ====== Remove the suppliers_company_id_fk in the suppliers table.
120
+ # t.remove_foreign_key :companies
121
+ # ====== Remove the foreign key named accounts_branch_id_fk in the accounts table.
122
+ # remove_foreign_key :column => :branch_id
123
+ # ====== Remove the foreign key named party_foreign_key in the accounts table.
124
+ # remove_index :name => :party_foreign_key
125
+ def remove_foreign_key(options = {})
126
+ @base.remove_foreign_key(@table_name, options)
127
+ end
128
+
129
+ # Adds a :foreign_key option to TableDefinition.references.
130
+ # If :foreign_key is true, a foreign key constraint is added to the table.
131
+ # You can also specify a hash, which is passed as foreign key options.
132
+ #
133
+ # ===== Examples
134
+ # ====== Add goat_id column and a foreign key to the goats table.
135
+ # t.references(:goat, :foreign_key => true)
136
+ # ====== Add goat_id column and a cascading foreign key to the goats table.
137
+ # t.references(:goat, :foreign_key => {:dependent => :delete})
138
+ #
139
+ # Note: No foreign key is created if :polymorphic => true is used.
140
+ def references_with_foreign_keys(*args)
141
+ options = args.extract_options!
142
+ polymorphic = options[:polymorphic]
143
+ fk_options = options.delete(:foreign_key)
144
+
145
+ references_without_foreign_keys(*(args << options))
146
+
147
+ if fk_options && !polymorphic
148
+ fk_options = {} if fk_options == true
149
+ args.each { |to_table| foreign_key(to_table, fk_options) }
150
+ end
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,75 @@
1
+ module Foreigner
2
+ module ConnectionAdapters
3
+ module SchemaStatements
4
+ def self.included(base)
5
+ base::AbstractAdapter.class_eval do
6
+ include Foreigner::ConnectionAdapters::AbstractAdapter
7
+ end
8
+ end
9
+ end
10
+
11
+ module AbstractAdapter
12
+ def supports_foreign_keys?
13
+ false
14
+ end
15
+
16
+ # Adds a new foreign key to the +from_table+, referencing the primary key of +to_table+
17
+ #
18
+ # The foreign key will be named after the from and to tables unless you pass
19
+ # <tt>:name</tt> as an option.
20
+ #
21
+ # ===== Examples
22
+ # ====== Creating a foreign key
23
+ # add_foreign_key(:comments, :posts)
24
+ # generates
25
+ # ALTER TABLE `comments` ADD CONSTRAINT
26
+ # `comments_post_id_fk` FOREIGN KEY (`post_id`) REFERENCES `posts` (`id`)
27
+ #
28
+ # ====== Creating a named foreign key
29
+ # add_foreign_key(:comments, :posts, :name => 'comments_belongs_to_posts')
30
+ # generates
31
+ # ALTER TABLE `comments` ADD CONSTRAINT
32
+ # `comments_belongs_to_posts` FOREIGN KEY (`post_id`) REFERENCES `posts` (`id`)
33
+ #
34
+ # ====== Creating a cascading foreign_key on a custom column
35
+ # add_foreign_key(:people, :people, :column => 'best_friend_id', :dependent => :nullify)
36
+ # generates
37
+ # ALTER TABLE `people` ADD CONSTRAINT
38
+ # `people_best_friend_id_fk` FOREIGN KEY (`best_friend_id`) REFERENCES `people` (`id`)
39
+ # ON DELETE SET NULL
40
+ #
41
+ # === Supported options
42
+ # [:column]
43
+ # Specify the column name on the from_table that references the to_table. By default this is guessed
44
+ # to be the singular name of the to_table with "_id" suffixed. So a to_table of :posts will use "post_id"
45
+ # as the default <tt>:column</tt>.
46
+ # [:primary_key]
47
+ # Specify the column name on the to_table that is referenced by this foreign key. By default this is
48
+ # assumed to be "id".
49
+ # [:name]
50
+ # Specify the name of the foreign key constraint. This defaults to use from_table and foreign key column.
51
+ # [:dependent]
52
+ # If set to <tt>:delete</tt>, the associated records in from_table are deleted when records in to_table table are deleted.
53
+ # If set to <tt>:nullify</tt>, the foreign key column is set to +NULL+.
54
+ def add_foreign_key(from_table, to_table, options = {})
55
+ end
56
+
57
+ # Remove the given foreign key from the table.
58
+ #
59
+ # ===== Examples
60
+ # ====== Remove the suppliers_company_id_fk in the suppliers table.
61
+ # remove_foreign_key :suppliers, :companies
62
+ # ====== Remove the foreign key named accounts_branch_id_fk in the accounts table.
63
+ # remove_foreign_key :accounts, :column => :branch_id
64
+ # ====== Remove the foreign key named party_foreign_key in the accounts table.
65
+ # remove_foreign_key :accounts, :name => :party_foreign_key
66
+ def remove_foreign_key(from_table, options)
67
+ end
68
+
69
+ # Return the foreign keys for the schema_dumper
70
+ def foreign_keys(table_name)
71
+ []
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,43 @@
1
+ module Foreigner
2
+ module ConnectionAdapters
3
+ module MysqlAdapter
4
+ include Foreigner::ConnectionAdapters::Sql2003
5
+
6
+ def foreign_keys(table_name)
7
+ fk_info = select_all %{
8
+ SELECT fk.referenced_table_name as 'to_table'
9
+ ,fk.referenced_column_name as 'primary_key'
10
+ ,fk.column_name as 'column'
11
+ ,fk.constraint_name as 'name'
12
+ FROM information_schema.key_column_usage fk
13
+ WHERE fk.referenced_column_name is not null
14
+ AND fk.table_schema = '#{@config[:database]}'
15
+ AND fk.table_name = '#{table_name}'
16
+ }
17
+
18
+ create_table_info = select_one("SHOW CREATE TABLE #{quote_table_name(table_name)}")["Create Table"]
19
+
20
+ fk_info.map do |row|
21
+ options = {:column => row['column'], :name => row['name'], :primary_key => row['primary_key']}
22
+
23
+ if create_table_info =~ /CONSTRAINT #{quote_column_name(row['name'])} FOREIGN KEY .* REFERENCES .* ON DELETE (CASCADE|SET NULL)/
24
+ if $1 == 'CASCADE'
25
+ options[:dependent] = :delete
26
+ elsif $1 == 'SET NULL'
27
+ options[:dependent] = :nullify
28
+ end
29
+ end
30
+ ForeignKeyDefinition.new(table_name, row['to_table'], options)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ module ActiveRecord
38
+ module ConnectionAdapters
39
+ MysqlAdapter.class_eval do
40
+ include Foreigner::ConnectionAdapters::MysqlAdapter
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,48 @@
1
+ module Foreigner
2
+ module ConnectionAdapters
3
+ module PostgreSQLAdapter
4
+ include Foreigner::ConnectionAdapters::Sql2003
5
+
6
+ def foreign_keys(table_name)
7
+ fk_info = select_all %{
8
+ SELECT tc.constraint_name as name
9
+ ,ccu.table_name as to_table
10
+ ,ccu.column_name as primary_key
11
+ ,kcu.column_name as column
12
+ ,rc.delete_rule as dependency
13
+ FROM information_schema.table_constraints tc
14
+ JOIN information_schema.key_column_usage kcu
15
+ USING (constraint_catalog, constraint_schema, constraint_name)
16
+ JOIN information_schema.referential_constraints rc
17
+ USING (constraint_catalog, constraint_schema, constraint_name)
18
+ JOIN information_schema.constraint_column_usage ccu
19
+ USING (constraint_catalog, constraint_schema, constraint_name)
20
+ WHERE tc.constraint_type = 'FOREIGN KEY'
21
+ AND tc.constraint_catalog = '#{@config[:database]}'
22
+ AND tc.table_name = '#{table_name}'
23
+ }
24
+
25
+ fk_info.map do |row|
26
+ options = {:column => row['column'], :name => row['name'], :primary_key => row['primary_key']}
27
+
28
+ if row['dependency'] == 'CASCADE'
29
+ options[:dependent] = :delete
30
+ elsif row['dependency'] == 'SET NULL'
31
+ options[:dependent] = :nullify
32
+ elsif row['dependency'] == 'SET DEFAULT'
33
+ options[:dependent] = :default
34
+ end
35
+ ForeignKeyDefinition.new(table_name, row['to_table'], options)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ module ActiveRecord
43
+ module ConnectionAdapters
44
+ PostgreSQLAdapter.class_eval do
45
+ include Foreigner::ConnectionAdapters::PostgreSQLAdapter
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,59 @@
1
+ module Foreigner
2
+ module ConnectionAdapters
3
+ module Sql2003
4
+ def supports_foreign_keys?
5
+ true
6
+ end
7
+
8
+ def add_foreign_key(from_table, to_table, options = {})
9
+ column = options[:column] || "#{to_table.to_s.singularize}_id"
10
+ foreign_key_name = foreign_key_name(from_table, column, options)
11
+
12
+ sql =
13
+ "ALTER TABLE #{quote_table_name(from_table)} " +
14
+ "ADD CONSTRAINT #{quote_column_name(foreign_key_name)} " +
15
+ foreign_key_definition(to_table, options)
16
+
17
+ execute(sql)
18
+ end
19
+
20
+ def foreign_key_definition(to_table, options = {})
21
+ column = options[:column] || "#{to_table.to_s.singularize}_id"
22
+ primary_key = options[:primary_key] || "id"
23
+ dependency = dependency_sql(options[:dependent])
24
+
25
+ sql = "FOREIGN KEY (#{quote_column_name(column)}) REFERENCES #{quote_table_name(to_table)}(#{primary_key})"
26
+ sql << " #{dependency}" unless dependency.blank?
27
+ sql
28
+ end
29
+
30
+ def remove_foreign_key(table, options)
31
+ if Hash === options
32
+ foreign_key_name = foreign_key_name(table, options[:column], options)
33
+ else
34
+ foreign_key_name = foreign_key_name(table, "#{options.to_s.singularize}_id")
35
+ end
36
+
37
+ execute "ALTER TABLE #{quote_table_name(table)} DROP FOREIGN KEY #{quote_column_name(foreign_key_name)}"
38
+ end
39
+
40
+ private
41
+ def foreign_key_name(table, column, options = {})
42
+ if options[:name]
43
+ options[:name]
44
+ else
45
+ "#{table}_#{column}_fk"
46
+ end
47
+ end
48
+
49
+ def dependency_sql(dependency)
50
+ case dependency
51
+ when :nullify then "ON DELETE SET NULL"
52
+ when :delete then "ON DELETE CASCADE"
53
+ when :default then "ON DELETE SET DEFAULT"
54
+ else ""
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,45 @@
1
+ module Foreigner
2
+ module SchemaDumper
3
+ def self.included(base)
4
+ base.class_eval do
5
+ include InstanceMethods
6
+ alias_method_chain :tables, :foreign_keys
7
+ end
8
+ end
9
+
10
+ module InstanceMethods
11
+ def tables_with_foreign_keys(stream)
12
+ tables_without_foreign_keys(stream)
13
+ @connection.tables.sort.each do |table|
14
+ foreign_keys(table, stream)
15
+ end
16
+ end
17
+
18
+ private
19
+ def foreign_keys(table_name, stream)
20
+ if (foreign_keys = @connection.foreign_keys(table_name)).any?
21
+ add_foreign_key_statements = foreign_keys.map do |foreign_key|
22
+ statement_parts = [ ('add_foreign_key ' + foreign_key.from_table.inspect) ]
23
+ statement_parts << foreign_key.to_table.inspect
24
+ statement_parts << (':name => ' + foreign_key.options[:name].inspect)
25
+
26
+ if foreign_key.options[:column] != "#{foreign_key.to_table.singularize}_id"
27
+ statement_parts << (':column => ' + foreign_key.options[:column].inspect)
28
+ end
29
+ if foreign_key.options[:primary_key] != 'id'
30
+ statement_parts << (':primary_key => ' + foreign_key.options[:primary_key].inspect)
31
+ end
32
+ if foreign_key.options[:dependent].present?
33
+ statement_parts << (':dependent => ' + foreign_key.options[:dependent].inspect)
34
+ end
35
+
36
+ ' ' + statement_parts.join(', ')
37
+ end
38
+
39
+ stream.puts add_foreign_key_statements.sort.join("\n")
40
+ stream.puts
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require 'active_support'
4
+ require 'active_support/test_case'
5
+ require 'active_record'
6
+ require 'active_record/test_case'
7
+ require 'active_record/connection_adapters/mysql_adapter'
8
+ require 'foreigner'
@@ -0,0 +1,83 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class MysqlAdapterTest < ActiveRecord::TestCase
4
+ include Foreigner::MysqlAdapter
5
+
6
+ def test_add_without_options
7
+ assert_equal(
8
+ "ALTER TABLE `employees` ADD CONSTRAINT `employees_company_id_fk` FOREIGN KEY (`company_id`) REFERENCES `companies`(id)",
9
+ add_foreign_key(:employees, :companies)
10
+ )
11
+ end
12
+
13
+ def test_add_with_name
14
+ assert_equal(
15
+ "ALTER TABLE `employees` ADD CONSTRAINT `favorite_company_fk` FOREIGN KEY (`company_id`) REFERENCES `companies`(id)",
16
+ add_foreign_key(:employees, :companies, :name => 'favorite_company_fk')
17
+ )
18
+ end
19
+
20
+ def test_add_with_column
21
+ assert_equal(
22
+ "ALTER TABLE `employees` ADD CONSTRAINT `employees_last_employer_id_fk` FOREIGN KEY (`last_employer_id`) REFERENCES `companies`(id)",
23
+ add_foreign_key(:employees, :companies, :column => 'last_employer_id')
24
+ )
25
+ end
26
+
27
+ def test_add_with_column_and_name
28
+ assert_equal(
29
+ "ALTER TABLE `employees` ADD CONSTRAINT `favorite_company_fk` FOREIGN KEY (`last_employer_id`) REFERENCES `companies`(id)",
30
+ add_foreign_key(:employees, :companies, :column => 'last_employer_id', :name => 'favorite_company_fk')
31
+ )
32
+ end
33
+
34
+ def test_add_with_delete_dependency
35
+ assert_equal(
36
+ "ALTER TABLE `employees` ADD CONSTRAINT `employees_company_id_fk` FOREIGN KEY (`company_id`) REFERENCES `companies`(id) " +
37
+ "ON DELETE CASCADE",
38
+ add_foreign_key(:employees, :companies, :dependent => :delete)
39
+ )
40
+ end
41
+
42
+ def test_add_with_nullify_dependency
43
+ assert_equal(
44
+ "ALTER TABLE `employees` ADD CONSTRAINT `employees_company_id_fk` FOREIGN KEY (`company_id`) REFERENCES `companies`(id) " +
45
+ "ON DELETE SET NULL",
46
+ add_foreign_key(:employees, :companies, :dependent => :nullify)
47
+ )
48
+ end
49
+
50
+ def test_remove_by_table
51
+ assert_equal(
52
+ "ALTER TABLE `suppliers` DROP FOREIGN KEY `suppliers_company_id_fk`",
53
+ remove_foreign_key(:suppliers, :companies)
54
+ )
55
+ end
56
+
57
+ def test_remove_by_name
58
+ assert_equal(
59
+ "ALTER TABLE `suppliers` DROP FOREIGN KEY `belongs_to_supplier`",
60
+ remove_foreign_key(:suppliers, :name => "belongs_to_supplier")
61
+ )
62
+ end
63
+
64
+ def test_remove_by_column
65
+ assert_equal(
66
+ "ALTER TABLE `suppliers` DROP FOREIGN KEY `suppliers_ship_to_id_fk`",
67
+ remove_foreign_key(:suppliers, :column => "ship_to_id")
68
+ )
69
+ end
70
+
71
+ private
72
+ def execute(sql, name = nil)
73
+ sql
74
+ end
75
+
76
+ def quote_column_name(name)
77
+ "`#{name}`"
78
+ end
79
+
80
+ def quote_table_name(name)
81
+ quote_column_name(name).gsub('.', '`.`')
82
+ end
83
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kvs-foreigner
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.2
5
+ platform: ruby
6
+ authors:
7
+ - Kenneth Vestergaard Schmidt
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-06 00:00:00 +02:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Foreign keys for Rails migrations
17
+ email: kvs@binarysolutions.dk
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ files:
25
+ - MIT-LICENSE
26
+ - Rakefile
27
+ - README
28
+ - lib/foreigner.rb
29
+ - lib/foreigner/schema_dumper.rb
30
+ - lib/foreigner/connection_adapters/sql_2003.rb
31
+ - lib/foreigner/connection_adapters/mysql_adapter.rb
32
+ - lib/foreigner/connection_adapters/postgresql_adapter.rb
33
+ - lib/foreigner/connection_adapters/abstract/schema_definitions.rb
34
+ - lib/foreigner/connection_adapters/abstract/schema_statements.rb
35
+ - test/helper.rb
36
+ - test/mysql_adapter_test.rb
37
+ has_rdoc: true
38
+ homepage: http://github.com/kvs/foreigner/tree/master
39
+ licenses: []
40
+
41
+ post_install_message:
42
+ rdoc_options:
43
+ - --line-numbers
44
+ - --main
45
+ - README
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ requirements: []
61
+
62
+ rubyforge_project:
63
+ rubygems_version: 1.3.5
64
+ signing_key:
65
+ specification_version: 1
66
+ summary: Foreign keys for Rails migrations
67
+ test_files: []
68
+