matthuhiggins-foreigner 0.2.0 → 0.2.1
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.
@@ -1,133 +1,149 @@
|
|
1
1
|
module Foreigner
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
module TableDefinition
|
6
|
-
class ForeignKey < Struct.new(:base, :to_table, :options)
|
7
|
-
def to_sql
|
8
|
-
base.foreign_key_definition(to_table, options)
|
9
|
-
end
|
10
|
-
alias to_s :to_sql
|
2
|
+
module ConnectionAdapters
|
3
|
+
class ForeignKeyDefinition < Struct.new(:from_table, :to_table, :options) #:nodoc:
|
11
4
|
end
|
12
5
|
|
13
|
-
|
14
|
-
base
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
18
15
|
end
|
19
16
|
end
|
20
|
-
|
21
|
-
module
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
#
|
26
|
-
# ===== Examples
|
27
|
-
# ====== Add goat_id column and a foreign key to the goats table.
|
28
|
-
# t.references(:goat, :foreign_key => true)
|
29
|
-
# ====== Add goat_id column and a cascading foreign key to the goats table.
|
30
|
-
# t.references(:goat, :foreign_key => {:dependent => :delete})
|
31
|
-
#
|
32
|
-
# Note: No foreign key is created if :polymorphic => true is used.
|
33
|
-
# Note: If no name is specified, the database driver creates one for you!
|
34
|
-
def references_with_foreign_keys(*args)
|
35
|
-
options = args.extract_options!
|
36
|
-
fk_options = options.delete(:foreign_key)
|
37
|
-
|
38
|
-
if fk_options && !options[:polymorphic]
|
39
|
-
fk_options = {} if options[:foreign_key] == true
|
40
|
-
args.each { |to_table| foreign_key(to_table, fk_options) }
|
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)
|
41
22
|
end
|
23
|
+
alias to_s :to_sql
|
24
|
+
end
|
42
25
|
|
43
|
-
|
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
|
44
32
|
end
|
45
33
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
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
|
+
def foreign_key(to_table, options = {})
|
70
|
+
if @base.supports_foreign_keys?
|
71
|
+
to_table = to_table.to_s.pluralize if ActiveRecord::Base.pluralize_table_names
|
72
|
+
foreign_keys << ForeignKey.new(@base, to_table, options)
|
73
|
+
end
|
74
|
+
end
|
66
75
|
|
67
|
-
|
68
|
-
|
69
|
-
|
76
|
+
def to_sql_with_foreign_keys
|
77
|
+
sql = to_sql_without_foreign_keys
|
78
|
+
sql << ', ' << (foreign_keys * ', ') if foreign_keys.present?
|
79
|
+
sql
|
70
80
|
end
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
base.class_eval do
|
77
|
-
include InstanceMethods
|
78
|
-
alias_method_chain :references, :foreign_keys
|
81
|
+
|
82
|
+
private
|
83
|
+
def foreign_keys
|
84
|
+
@foreign_keys ||= []
|
85
|
+
end
|
79
86
|
end
|
80
87
|
end
|
81
88
|
|
82
|
-
module
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
# t.foreign_key(:people)
|
89
|
-
# ====== Defining the column
|
90
|
-
# t.foreign_key(:people, :column => :sender_id)
|
91
|
-
# ====== Creating a named foreign key
|
92
|
-
# t.foreign_key(:people, :column => :sender_id, :name => 'sender_foreign_key')
|
93
|
-
def foreign_key(to_table, options = {})
|
94
|
-
@base.add_foreign_key(@table_name, to_table, options)
|
89
|
+
module Table
|
90
|
+
def self.included(base)
|
91
|
+
base.class_eval do
|
92
|
+
include InstanceMethods
|
93
|
+
alias_method_chain :references, :foreign_keys
|
94
|
+
end
|
95
95
|
end
|
96
|
+
|
97
|
+
module InstanceMethods
|
98
|
+
# Adds a new foreign key to the table. +to_table+ can be a single Symbol, or
|
99
|
+
# an Array of Symbols. See SchemaStatements#add_foreign_key
|
100
|
+
#
|
101
|
+
# ===== Examples
|
102
|
+
# ====== Creating a simple foreign key
|
103
|
+
# t.foreign_key(:people)
|
104
|
+
# ====== Defining the column
|
105
|
+
# t.foreign_key(:people, :column => :sender_id)
|
106
|
+
# ====== Creating a named foreign key
|
107
|
+
# t.foreign_key(:people, :column => :sender_id, :name => 'sender_foreign_key')
|
108
|
+
def foreign_key(to_table, options = {})
|
109
|
+
@base.add_foreign_key(@table_name, to_table, options)
|
110
|
+
end
|
96
111
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
112
|
+
# Remove the given foreign key from the table.
|
113
|
+
#
|
114
|
+
# ===== Examples
|
115
|
+
# ====== Remove the suppliers_company_id_fk in the suppliers table.
|
116
|
+
# t.remove_foreign_key :companies
|
117
|
+
# ====== Remove the foreign key named accounts_branch_id_fk in the accounts table.
|
118
|
+
# remove_foreign_key :column => :branch_id
|
119
|
+
# ====== Remove the foreign key named party_foreign_key in the accounts table.
|
120
|
+
# remove_index :name => :party_foreign_key
|
121
|
+
def remove_foreign_key(options = {})
|
122
|
+
@base.remove_foreign_key(@table_name, options)
|
123
|
+
end
|
109
124
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
+
# Adds a :foreign_key option to TableDefinition.references.
|
126
|
+
# If :foreign_key is true, a foreign key constraint is added to the table.
|
127
|
+
# You can also specify a hash, which is passed as foreign key options.
|
128
|
+
#
|
129
|
+
# ===== Examples
|
130
|
+
# ====== Add goat_id column and a foreign key to the goats table.
|
131
|
+
# t.references(:goat, :foreign_key => true)
|
132
|
+
# ====== Add goat_id column and a cascading foreign key to the goats table.
|
133
|
+
# t.references(:goat, :foreign_key => {:dependent => :delete})
|
134
|
+
#
|
135
|
+
# Note: No foreign key is created if :polymorphic => true is used.
|
136
|
+
def references_with_foreign_keys(*args)
|
137
|
+
options = args.extract_options!
|
138
|
+
polymorphic = options[:polymorphic]
|
139
|
+
fk_options = options.delete(:foreign_key)
|
125
140
|
|
126
|
-
|
141
|
+
references_without_foreign_keys(*(args << options))
|
127
142
|
|
128
|
-
|
129
|
-
|
130
|
-
|
143
|
+
if fk_options && !polymorphic
|
144
|
+
fk_options = {} if fk_options == true
|
145
|
+
args.each { |to_table| foreign_key(to_table, fk_options) }
|
146
|
+
end
|
131
147
|
end
|
132
148
|
end
|
133
149
|
end
|
@@ -1,62 +1,72 @@
|
|
1
1
|
module Foreigner
|
2
|
-
module
|
3
|
-
|
4
|
-
|
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
|
5
9
|
end
|
6
10
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
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
|
+
# [:name]
|
47
|
+
# Specify the name of the foreign key constraint. This defaults to use from_table and foreign key column.
|
48
|
+
# [:dependent]
|
49
|
+
# If set to <tt>:delete</tt>, the associated records in from_table are deleted when records in to_table table are deleted.
|
50
|
+
# If set to <tt>:nullify</tt>, the foreign key column is set to +NULL+.
|
51
|
+
def add_foreign_key(from_table, to_table, options = {})
|
52
|
+
end
|
53
|
+
|
54
|
+
# Remove the given foreign key from the table.
|
55
|
+
#
|
56
|
+
# ===== Examples
|
57
|
+
# ====== Remove the suppliers_company_id_fk in the suppliers table.
|
58
|
+
# remove_foreign_key :suppliers, :companies
|
59
|
+
# ====== Remove the foreign key named accounts_branch_id_fk in the accounts table.
|
60
|
+
# remove_foreign_key :accounts, :column => :branch_id
|
61
|
+
# ====== Remove the foreign key named party_foreign_key in the accounts table.
|
62
|
+
# remove_foreign_key :accounts, :name => :party_foreign_key
|
63
|
+
def remove_foreign_key(from_table, options)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Return the foreign keys for the schema_dumper
|
67
|
+
def foreign_keys(table_name)
|
68
|
+
[]
|
69
|
+
end
|
60
70
|
end
|
61
71
|
end
|
62
72
|
end
|
@@ -6,8 +6,6 @@ module Foreigner
|
|
6
6
|
include Foreigner::ConnectionAdapters::Sql2003
|
7
7
|
|
8
8
|
def foreign_keys(table_name)
|
9
|
-
foreign_keys = []
|
10
|
-
|
11
9
|
fk_info = select_all %{
|
12
10
|
select tc.constraint_name as name
|
13
11
|
,ccu.table_name as to_table
|
@@ -15,17 +13,11 @@ module Foreigner
|
|
15
13
|
,rc.delete_rule as dependency
|
16
14
|
from information_schema.table_constraints tc
|
17
15
|
join information_schema.key_column_usage kcu
|
18
|
-
|
19
|
-
and tc.constraint_schema = kcu.constraint_schema
|
20
|
-
and tc.constraint_name = kcu.constraint_name
|
16
|
+
using (constraint_catalog, constraint_schema, constraint_name)
|
21
17
|
join information_schema.referential_constraints rc
|
22
|
-
|
23
|
-
and tc.constraint_schema = rc.constraint_schema
|
24
|
-
and tc.constraint_name = rc.constraint_name
|
18
|
+
using (constraint_catalog, constraint_schema, constraint_name)
|
25
19
|
join information_schema.constraint_column_usage ccu
|
26
|
-
|
27
|
-
and tc.constraint_schema = ccu.constraint_schema
|
28
|
-
and tc.constraint_name = ccu.constraint_name
|
20
|
+
using (constraint_catalog, constraint_schema, constraint_name)
|
29
21
|
where tc.constraint_type = 'FOREIGN KEY'
|
30
22
|
and tc.constraint_catalog = '#{@config[:database]}'
|
31
23
|
and tc.table_name = '#{table_name}'
|
data/lib/foreigner.rb
CHANGED
@@ -4,17 +4,8 @@ require 'foreigner/schema_dumper'
|
|
4
4
|
|
5
5
|
module ActiveRecord
|
6
6
|
module ConnectionAdapters
|
7
|
-
|
8
|
-
|
9
|
-
end
|
10
|
-
|
11
|
-
TableDefinition.class_eval do
|
12
|
-
include Foreigner::TableDefinition
|
13
|
-
end
|
14
|
-
|
15
|
-
Table.class_eval do
|
16
|
-
include Foreigner::Table
|
17
|
-
end
|
7
|
+
include Foreigner::ConnectionAdapters::SchemaStatements
|
8
|
+
include Foreigner::ConnectionAdapters::SchemaDefinitions
|
18
9
|
end
|
19
10
|
|
20
11
|
SchemaDumper.class_eval do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: matthuhiggins-foreigner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthew Higgins
|
@@ -38,6 +38,7 @@ files:
|
|
38
38
|
- test/mysql_adapter_test.rb
|
39
39
|
has_rdoc: false
|
40
40
|
homepage: http://github.com/matthuhiggins/foreigner/tree/master
|
41
|
+
licenses:
|
41
42
|
post_install_message:
|
42
43
|
rdoc_options:
|
43
44
|
- --line-numbers
|
@@ -60,7 +61,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
60
61
|
requirements: []
|
61
62
|
|
62
63
|
rubyforge_project: foreigner
|
63
|
-
rubygems_version: 1.
|
64
|
+
rubygems_version: 1.3.5
|
64
65
|
signing_key:
|
65
66
|
specification_version: 1
|
66
67
|
summary: Foreign keys for Rails migrations
|