dwilkie-foreigner 0.4.1 → 0.5.0
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 +2 -1
- data/README.textile +119 -0
- data/lib/foreigner.rb +1 -1
- data/lib/foreigner/connection_adapters/abstract/schema_definitions.rb +22 -9
- data/lib/foreigner/connection_adapters/sql_2003.rb +13 -3
- data/lib/foreigner/connection_adapters/sqlite3_adapter.rb +104 -0
- data/lib/foreigner/schema_dumper.rb +8 -5
- metadata +5 -5
- data/README +0 -76
- data/lib/foreigner/connection_adapters/sqlite_adapter.rb +0 -38
data/MIT-LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c)
|
1
|
+
Copyright (c) 2010 David Wilkie
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining
|
4
4
|
a copy of this software and associated documentation files (the
|
@@ -18,3 +18,4 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
18
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
19
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
20
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
data/README.textile
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
h1. dwilkie Foreigner
|
2
|
+
|
3
|
+
dwilkie-foreigner is a fork of "Matt Higgins Foreigner":http://github.com/matthuhiggins/foreigner/
|
4
|
+
which supports adding AND enforcing foreign key constraints on Sqlite3 databases.
|
5
|
+
|
6
|
+
h2. Some Examples
|
7
|
+
|
8
|
+
dwilkie-foreigner allows you to do the following in your migration files
|
9
|
+
<pre>
|
10
|
+
create_table :comments do |t|
|
11
|
+
t.references :posts, :foreign_key => true, :null => false
|
12
|
+
end
|
13
|
+
</pre>
|
14
|
+
Which will generate the following SQL:
|
15
|
+
<pre>
|
16
|
+
CREATE TABLE "comments" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
17
|
+
"post_id" integer NOT NULL,
|
18
|
+
FOREIGN KEY ("post_id") REFERENCES "posts"(id));
|
19
|
+
</pre>
|
20
|
+
|
21
|
+
Go a different column name?
|
22
|
+
<pre>
|
23
|
+
create_table :comments do |t|
|
24
|
+
t.references :article, :null => false
|
25
|
+
t.foreign_key :posts, :column => :article_id
|
26
|
+
end
|
27
|
+
</pre>
|
28
|
+
Which generates:
|
29
|
+
<pre>
|
30
|
+
CREATE TABLE "comments" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
31
|
+
"article_id" integer NOT NULL,
|
32
|
+
FOREIGN KEY ("article_id") REFERENCES "posts"(id));
|
33
|
+
</pre>
|
34
|
+
|
35
|
+
Want to specify a dependency (nullify or delete)?
|
36
|
+
<pre>
|
37
|
+
create_table :comments do |t|
|
38
|
+
t.references :posts, :foreign_key => {:dependent => :delete}, :null => false
|
39
|
+
end
|
40
|
+
</pre>
|
41
|
+
Generates:
|
42
|
+
<pre>
|
43
|
+
CREATE TABLE "comments" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
44
|
+
"post_id" integer NOT NULL,
|
45
|
+
FOREIGN KEY ("post_id") REFERENCES "posts"(id) ON DELETE CASCADE);
|
46
|
+
</pre>
|
47
|
+
Or:
|
48
|
+
<pre>
|
49
|
+
create_table :comments do |t|
|
50
|
+
t.references :article, :null => false
|
51
|
+
t.foreign_key :posts, :column => :article_id, :dependent => :nullify
|
52
|
+
end
|
53
|
+
</pre>
|
54
|
+
Which generates:
|
55
|
+
<pre>
|
56
|
+
CREATE TABLE "comments" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
57
|
+
"article_id" integer NOT NULL,
|
58
|
+
FOREIGN KEY ("article_id") REFERENCES "posts"(id) ON DELETE SET NULL);
|
59
|
+
</pre>
|
60
|
+
|
61
|
+
h2. Enforcing constraints
|
62
|
+
|
63
|
+
SQLite does not enforce database constraints out of the box
|
64
|
+
This provides you with the flexibility in choosing whether or not to enforce
|
65
|
+
constraints at the DB level or not.
|
66
|
+
|
67
|
+
In order to enforce your constraints:
|
68
|
+
<pre>
|
69
|
+
script/dbconsole
|
70
|
+
.genfkey --exec
|
71
|
+
</pre>
|
72
|
+
|
73
|
+
While your in the console run:
|
74
|
+
<pre>
|
75
|
+
.schema
|
76
|
+
</pre>
|
77
|
+
to see your constraints implemented as triggers
|
78
|
+
|
79
|
+
h2. schema.rb
|
80
|
+
|
81
|
+
All of the constrants are updated in schema.rb
|
82
|
+
when you run:
|
83
|
+
<pre>
|
84
|
+
rake db:migrate
|
85
|
+
rake db:schema:dump
|
86
|
+
</pre>
|
87
|
+
This allows you to see the state of your migratons and
|
88
|
+
take advantage of using <pre>rake db:schema:load</pre>
|
89
|
+
|
90
|
+
h2. Limitations
|
91
|
+
|
92
|
+
Since SQLite does not have complete ALTER TABLE support
|
93
|
+
you cannot use the following syntax:
|
94
|
+
<pre>
|
95
|
+
add_foreign_key
|
96
|
+
remove_foreign_key
|
97
|
+
</pre>
|
98
|
+
|
99
|
+
Therefore you must add your foreign keys when you define your table,
|
100
|
+
which may involve editing existing migration files instead of generating new ones
|
101
|
+
|
102
|
+
h2. Installation
|
103
|
+
|
104
|
+
Add the following to environment.rb:
|
105
|
+
<pre>
|
106
|
+
config.gem "dwilkie-foreigner", :lib => "foreigner", :source => "http://gemcutter.org"
|
107
|
+
</pre>
|
108
|
+
Then run
|
109
|
+
<pre>
|
110
|
+
sudo rake gems:install
|
111
|
+
</pre>
|
112
|
+
|
113
|
+
h2. See also
|
114
|
+
|
115
|
+
Don't need support for other databases?
|
116
|
+
Check out "sqlite-foreigner":http://github.com/dwilkie/sqlite-foreigner/tree/master
|
117
|
+
|
118
|
+
Copyright (c) 2009 David Wilkie, released under the MIT license
|
119
|
+
|
data/lib/foreigner.rb
CHANGED
@@ -14,7 +14,7 @@ module ActiveRecord
|
|
14
14
|
end
|
15
15
|
|
16
16
|
Base.class_eval do
|
17
|
-
if %w(
|
17
|
+
if %w(sqlite3).include? connection_pool.spec.config[:adapter].downcase
|
18
18
|
require "foreigner/connection_adapters/#{connection_pool.spec.config[:adapter].downcase}_adapter"
|
19
19
|
end
|
20
20
|
if %w(mysql postgresql).include? connection_pool.spec.config[:adapter].downcase
|
@@ -2,27 +2,28 @@ module Foreigner
|
|
2
2
|
module ConnectionAdapters
|
3
3
|
class ForeignKeyDefinition < Struct.new(:from_table, :to_table, :options) #:nodoc:
|
4
4
|
end
|
5
|
-
|
5
|
+
|
6
6
|
module SchemaDefinitions
|
7
7
|
def self.included(base)
|
8
8
|
base::TableDefinition.class_eval do
|
9
9
|
include Foreigner::ConnectionAdapters::TableDefinition
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
base::Table.class_eval do
|
13
13
|
include Foreigner::ConnectionAdapters::Table
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
module TableDefinition
|
19
19
|
def self.included(base)
|
20
20
|
base.class_eval do
|
21
21
|
include InstanceMethods
|
22
22
|
alias_method_chain :references, :foreign_keys
|
23
|
+
alias_method_chain :to_sql, :foreign_keys
|
23
24
|
end
|
24
25
|
end
|
25
|
-
|
26
|
+
|
26
27
|
module InstanceMethods
|
27
28
|
def references_with_foreign_keys(*args)
|
28
29
|
options = args.extract_options!
|
@@ -35,13 +36,24 @@ module Foreigner
|
|
35
36
|
|
36
37
|
references_without_foreign_keys(*(args << options))
|
37
38
|
end
|
38
|
-
|
39
|
+
|
39
40
|
def foreign_key(to_table, options = {})
|
40
41
|
ActiveSupport::Deprecation.warn(
|
41
42
|
'adding a foreign key inside create_table is deprecated. ' +
|
42
43
|
'to add a foreign key, use add_foreign_key', caller[0,10]
|
43
44
|
)
|
44
45
|
end
|
46
|
+
|
47
|
+
def to_sql_with_foreign_keys
|
48
|
+
sql = to_sql_without_foreign_keys
|
49
|
+
sql << ', ' << (foreign_keys * ', ') if foreign_keys.present?
|
50
|
+
sql
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
def foreign_keys
|
55
|
+
@foreign_keys ||= []
|
56
|
+
end
|
45
57
|
end
|
46
58
|
end
|
47
59
|
|
@@ -69,7 +81,7 @@ module Foreigner
|
|
69
81
|
def foreign_key(to_table, options = {})
|
70
82
|
@base.add_foreign_key(@table_name, to_table, options)
|
71
83
|
end
|
72
|
-
|
84
|
+
|
73
85
|
# Remove the given foreign key from the table.
|
74
86
|
#
|
75
87
|
# ===== Examples
|
@@ -82,17 +94,17 @@ module Foreigner
|
|
82
94
|
def remove_foreign_key(options = {})
|
83
95
|
@base.remove_foreign_key(@table_name, options)
|
84
96
|
end
|
85
|
-
|
97
|
+
|
86
98
|
# Adds a :foreign_key option to TableDefinition.references.
|
87
99
|
# If :foreign_key is true, a foreign key constraint is added to the table.
|
88
100
|
# You can also specify a hash, which is passed as foreign key options.
|
89
|
-
#
|
101
|
+
#
|
90
102
|
# ===== Examples
|
91
103
|
# ====== Add goat_id column and a foreign key to the goats table.
|
92
104
|
# t.references(:goat, :foreign_key => true)
|
93
105
|
# ====== Add goat_id column and a cascading foreign key to the goats table.
|
94
106
|
# t.references(:goat, :foreign_key => {:dependent => :delete})
|
95
|
-
#
|
107
|
+
#
|
96
108
|
# Note: No foreign key is created if :polymorphic => true is used.
|
97
109
|
def references_with_foreign_keys(*args)
|
98
110
|
options = args.extract_options!
|
@@ -110,3 +122,4 @@ module Foreigner
|
|
110
122
|
end
|
111
123
|
end
|
112
124
|
end
|
125
|
+
|
@@ -4,7 +4,16 @@ module Foreigner
|
|
4
4
|
def supports_foreign_keys?
|
5
5
|
true
|
6
6
|
end
|
7
|
-
|
7
|
+
|
8
|
+
def foreign_key_definition(to_table, options = {})
|
9
|
+
column = options[:column] || "#{to_table.to_s.singularize}_id"
|
10
|
+
dependency = dependency_sql(options[:dependent])
|
11
|
+
|
12
|
+
sql = "FOREIGN KEY (#{quote_column_name(column)}) REFERENCES #{quote_table_name(to_table)}(id)"
|
13
|
+
sql << " #{dependency}" unless dependency.blank?
|
14
|
+
sql
|
15
|
+
end
|
16
|
+
|
8
17
|
def add_foreign_key(from_table, to_table, options = {})
|
9
18
|
column = options[:column] || "#{to_table.to_s.singularize}_id"
|
10
19
|
foreign_key_name = foreign_key_name(from_table, column, options)
|
@@ -18,7 +27,7 @@ module Foreigner
|
|
18
27
|
"REFERENCES #{quote_table_name(ActiveRecord::Migrator.proper_table_name(to_table))}(#{primary_key})"
|
19
28
|
|
20
29
|
sql << " #{dependency}" unless dependency.blank?
|
21
|
-
|
30
|
+
|
22
31
|
execute(sql)
|
23
32
|
end
|
24
33
|
|
@@ -40,4 +49,5 @@ module Foreigner
|
|
40
49
|
end
|
41
50
|
end
|
42
51
|
end
|
43
|
-
end
|
52
|
+
end
|
53
|
+
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'foreigner/connection_adapters/sql_2003'
|
2
|
+
|
3
|
+
module Foreigner
|
4
|
+
module ConnectionAdapters
|
5
|
+
module TableDefinition
|
6
|
+
class ForeignKey < Struct.new(:base, :to_table, :options)
|
7
|
+
|
8
|
+
def to_sql
|
9
|
+
base.foreign_key_definition(to_table, options)
|
10
|
+
end
|
11
|
+
alias to_s :to_sql
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.included(base)
|
15
|
+
base.class_eval do
|
16
|
+
include InstanceMethods
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module InstanceMethods
|
21
|
+
# Adds a :foreign_key option to TableDefinition.references.
|
22
|
+
# If :foreign_key is true, a foreign key constraint is added to the table.
|
23
|
+
# You can also specify a hash, which is passed as foreign key options.
|
24
|
+
#
|
25
|
+
# ===== Examples
|
26
|
+
# ====== Add goat_id column and a foreign key to the goats table.
|
27
|
+
# t.references(:goat, :foreign_key => true)
|
28
|
+
# ====== Add goat_id column and a cascading foreign key to the goats table.
|
29
|
+
# t.references(:goat, :foreign_key => {:dependent => :delete})
|
30
|
+
#
|
31
|
+
# Note: No foreign key is created if :polymorphic => true is used.
|
32
|
+
def references_with_foreign_keys(*args)
|
33
|
+
options = args.extract_options!
|
34
|
+
fk_options = options.delete(:foreign_key)
|
35
|
+
|
36
|
+
if fk_options && !options[:polymorphic]
|
37
|
+
fk_options = {} if fk_options == true
|
38
|
+
args.each { |to_table| foreign_key(to_table, fk_options) }
|
39
|
+
end
|
40
|
+
|
41
|
+
references_without_foreign_keys(*(args << options))
|
42
|
+
end
|
43
|
+
|
44
|
+
# Defines a foreign key for the table. +to_table+ can be a single Symbol, or
|
45
|
+
# an Array of Symbols.
|
46
|
+
#
|
47
|
+
# ===== Examples
|
48
|
+
# ====== Creating a simple foreign key
|
49
|
+
# t.foreign_key(:people)
|
50
|
+
# ====== Defining the column
|
51
|
+
# t.foreign_key(:people, :column => :sender_id)
|
52
|
+
# ====== Specify cascading foreign key
|
53
|
+
# t.foreign_key(:people, :dependent => :delete)
|
54
|
+
def foreign_key(to_table, options = {})
|
55
|
+
if @base.supports_foreign_keys?
|
56
|
+
to_table = to_table.to_s.pluralize if ActiveRecord::Base.pluralize_table_names
|
57
|
+
foreign_keys << ForeignKey.new(@base, to_table, options)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
module SQLite3Adapter
|
64
|
+
include Foreigner::ConnectionAdapters::Sql2003
|
65
|
+
|
66
|
+
def foreign_keys(table_name)
|
67
|
+
foreign_keys = []
|
68
|
+
create_table_info = select_value %{
|
69
|
+
SELECT sql
|
70
|
+
FROM sqlite_master
|
71
|
+
WHERE sql LIKE '%FOREIGN KEY%'
|
72
|
+
AND name = '#{table_name}'
|
73
|
+
}
|
74
|
+
unless create_table_info.nil?
|
75
|
+
fk_columns = create_table_info.scan(/FOREIGN KEY\s*\(\"([^\"]+)\"\)/)
|
76
|
+
fk_tables = create_table_info.scan(/REFERENCES\s*\"([^\"]+)\"/)
|
77
|
+
fk_references = create_table_info.scan(/REFERENCES[^\,]+/)
|
78
|
+
if fk_columns.size == fk_tables.size && fk_references.size == fk_columns.size
|
79
|
+
fk_columns.each_with_index do |fk_column, index|
|
80
|
+
if fk_references[index] =~ /ON DELETE CASCADE/
|
81
|
+
fk_references[index] = :delete
|
82
|
+
elsif fk_references[index] =~ /ON DELETE SET NULL/
|
83
|
+
fk_references[index] = :nullify
|
84
|
+
else
|
85
|
+
fk_references[index] = nil
|
86
|
+
end
|
87
|
+
foreign_keys << ForeignKeyDefinition.new(table_name, fk_tables[index][0], :column => fk_column[0], :dependent => fk_references[index])
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
foreign_keys
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
module ActiveRecord
|
98
|
+
module ConnectionAdapters
|
99
|
+
SQLite3Adapter.class_eval do
|
100
|
+
include Foreigner::ConnectionAdapters::SQLite3Adapter
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
@@ -28,13 +28,12 @@ module Foreigner
|
|
28
28
|
|
29
29
|
private
|
30
30
|
def foreign_keys(table_name, stream)
|
31
|
-
debugger
|
32
31
|
if (foreign_keys = @connection.foreign_keys(table_name)).any?
|
33
32
|
add_foreign_key_statements = foreign_keys.map do |foreign_key|
|
34
33
|
statement_parts = [ ('add_foreign_key ' + foreign_key.from_table.inspect) ]
|
35
34
|
statement_parts << foreign_key.to_table.inspect
|
36
35
|
statement_parts << (':name => ' + foreign_key.options[:name].inspect)
|
37
|
-
|
36
|
+
|
38
37
|
if foreign_key.options[:column] != "#{foreign_key.to_table.singularize}_id"
|
39
38
|
statement_parts << (':column => ' + foreign_key.options[:column].inspect)
|
40
39
|
end
|
@@ -53,8 +52,9 @@ module Foreigner
|
|
53
52
|
end
|
54
53
|
end
|
55
54
|
|
56
|
-
# This is
|
57
|
-
# active_record/schema.dumper
|
55
|
+
# This is almost direct copy from
|
56
|
+
# active_record/schema.dumper with the add_foreign_keys method
|
57
|
+
# inserted into the middle
|
58
58
|
def foreign_key_table(table, stream)
|
59
59
|
columns = @connection.columns(table)
|
60
60
|
begin
|
@@ -119,6 +119,7 @@ module Foreigner
|
|
119
119
|
tbl.puts
|
120
120
|
end
|
121
121
|
|
122
|
+
# add the foreign keys
|
122
123
|
add_foreign_keys(table, tbl)
|
123
124
|
|
124
125
|
tbl.puts " end"
|
@@ -142,6 +143,7 @@ module Foreigner
|
|
142
143
|
add_foreign_key_statements = foreign_keys.map do |foreign_key|
|
143
144
|
statement_parts = [" t.foreign_key " + foreign_key.to_table.inspect]
|
144
145
|
statement_parts << (':column => ' + foreign_key.options[:column].inspect)
|
146
|
+
statement_parts << (':dependent => ' + foreign_key.options[:dependent].inspect)
|
145
147
|
' ' + statement_parts.join(', ')
|
146
148
|
end
|
147
149
|
|
@@ -150,4 +152,5 @@ module Foreigner
|
|
150
152
|
end
|
151
153
|
end
|
152
154
|
end
|
153
|
-
end
|
155
|
+
end
|
156
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dwilkie-foreigner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Wilkie
|
@@ -20,17 +20,17 @@ executables: []
|
|
20
20
|
extensions: []
|
21
21
|
|
22
22
|
extra_rdoc_files:
|
23
|
-
- README
|
23
|
+
- README.textile
|
24
24
|
files:
|
25
25
|
- MIT-LICENSE
|
26
26
|
- Rakefile
|
27
|
-
- README
|
27
|
+
- README.textile
|
28
28
|
- lib/foreigner.rb
|
29
29
|
- lib/foreigner/schema_dumper.rb
|
30
30
|
- lib/foreigner/connection_adapters/sql_2003.rb
|
31
31
|
- lib/foreigner/connection_adapters/mysql_adapter.rb
|
32
32
|
- lib/foreigner/connection_adapters/postgresql_adapter.rb
|
33
|
-
- lib/foreigner/connection_adapters/
|
33
|
+
- lib/foreigner/connection_adapters/sqlite3_adapter.rb
|
34
34
|
- lib/foreigner/connection_adapters/abstract/schema_definitions.rb
|
35
35
|
- lib/foreigner/connection_adapters/abstract/schema_statements.rb
|
36
36
|
- test/helper.rb
|
@@ -43,7 +43,7 @@ post_install_message:
|
|
43
43
|
rdoc_options:
|
44
44
|
- --line-numbers
|
45
45
|
- --main
|
46
|
-
- README
|
46
|
+
- README.textile
|
47
47
|
require_paths:
|
48
48
|
- lib
|
49
49
|
required_ruby_version: !ruby/object:Gem::Requirement
|
data/README
DELETED
@@ -1,76 +0,0 @@
|
|
1
|
-
Foreigner
|
2
|
-
=========
|
3
|
-
|
4
|
-
Adds limited SQLite support for Matt Higgins Foreigner.
|
5
|
-
|
6
|
-
Allows you to do the following in your migration files
|
7
|
-
t.foreign_key :posts
|
8
|
-
|
9
|
-
Which will generate the following SQL:
|
10
|
-
FOREIGN KEY ("post_id") REFERENCES "posts"(id)
|
11
|
-
|
12
|
-
To enforce the constraint use the genfkey tool included with SQLite:
|
13
|
-
rake db:migrate
|
14
|
-
sqlite3 db/development.sqlite3
|
15
|
-
.genfkey --exec
|
16
|
-
|
17
|
-
For more info see
|
18
|
-
http://www.sqlite.org/cvstrac/fileview?f=sqlite/tool/genfkey.README
|
19
|
-
|
20
|
-
|
21
|
-
Installation
|
22
|
-
------------
|
23
|
-
|
24
|
-
Install as a plugin:
|
25
|
-
|
26
|
-
ruby script/plugin install git://github.com/dwilkie/foreigner.git
|
27
|
-
|
28
|
-
Install as a gem by adding the following to environment.rb:
|
29
|
-
|
30
|
-
config.gem "dwilkie-foreigner", :lib => "foreigner", :source => "http://gemcutter.org"
|
31
|
-
|
32
|
-
|
33
|
-
sudo rake gems:install
|
34
|
-
|
35
|
-
API
|
36
|
-
---
|
37
|
-
t.foreign_key(options)
|
38
|
-
foreign_keys(table_name)
|
39
|
-
|
40
|
-
Since SQLite does not have complete ALTER TABLE support
|
41
|
-
you cannot use the following for an SQLite database
|
42
|
-
|
43
|
-
add_foreign_key(from_table, to_table, options)
|
44
|
-
remove_foreign_key(from_table, options)
|
45
|
-
|
46
|
-
|
47
|
-
Example
|
48
|
-
-------
|
49
|
-
|
50
|
-
The most common use of foreign keys is to reference a table that a model belongs to.
|
51
|
-
For example, given the following model:
|
52
|
-
|
53
|
-
class Comment < ActiveRecord::Base
|
54
|
-
belongs_to :post
|
55
|
-
end
|
56
|
-
|
57
|
-
class Post < ActiveRecord::Base
|
58
|
-
has_many :comments, :dependent => :delete_all
|
59
|
-
end
|
60
|
-
|
61
|
-
You should add a foreign key in your migration:
|
62
|
-
|
63
|
-
t.foreign_key :posts
|
64
|
-
|
65
|
-
If the column is named article_id instead of post_id, use the :column option:
|
66
|
-
|
67
|
-
t.foreign_key(:posts, :column => 'article_id')
|
68
|
-
|
69
|
-
schema.rb
|
70
|
-
---------
|
71
|
-
|
72
|
-
Similar to indexes, the foreign keys in your database are automatically dumped to schema.rb.
|
73
|
-
This allows you to use foreign keys without fighting Rails!
|
74
|
-
|
75
|
-
Copyright (c) 2009 David Wilkie, released under the MIT license
|
76
|
-
|
@@ -1,38 +0,0 @@
|
|
1
|
-
require 'foreigner/connection_adapters/sql_2003'
|
2
|
-
|
3
|
-
module Foreigner
|
4
|
-
module ConnectionAdapters
|
5
|
-
module SQLiteAdapter
|
6
|
-
include Foreigner::ConnectionAdapters::Sql2003
|
7
|
-
|
8
|
-
def foreign_keys(table_name)
|
9
|
-
foreign_keys = []
|
10
|
-
create_table_info = select_value %{
|
11
|
-
SELECT sql
|
12
|
-
FROM sqlite_master
|
13
|
-
WHERE sql LIKE '%FOREIGN KEY%'
|
14
|
-
AND name = '#{table_name}'
|
15
|
-
}
|
16
|
-
if !create_table_info.nil?
|
17
|
-
fk_columns = create_table_info.scan(/FOREIGN KEY\s*\(\"([^\"]+)\"\)/)
|
18
|
-
fk_tables = create_table_info.scan(/REFERENCES\s*\"([^\"]+)\"/)
|
19
|
-
if fk_columns.size == fk_tables.size
|
20
|
-
fk_columns.each_with_index do |fk_column, index|
|
21
|
-
foreign_keys << ForeignKeyDefinition.new(table_name, fk_tables[index][0], :column => fk_column[0])
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
foreign_keys
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
module ActiveRecord
|
32
|
-
module ConnectionAdapters
|
33
|
-
SQLiteAdapter.class_eval do
|
34
|
-
include Foreigner::ConnectionAdapters::SQLiteAdapter
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|