matthuhiggins-foreigner 0.2.1 → 0.3.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/README CHANGED
@@ -16,7 +16,7 @@ Install as a plugin:
16
16
 
17
17
  Install as a gem by adding the following to environment.rb:
18
18
 
19
- config.gem "matthuhiggins-foreigner", :lib => "foreigner"
19
+ config.gem "matthuhiggins-foreigner", :lib => "foreigner", :source => http://gemcutter.org
20
20
 
21
21
  API
22
22
  ---
@@ -66,6 +66,8 @@ module Foreigner
66
66
  # t.foreign_key(:people, :column => :sender_id)
67
67
  # ====== Creating a named foreign key
68
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)
69
71
  def foreign_key(to_table, options = {})
70
72
  if @base.supports_foreign_keys?
71
73
  to_table = to_table.to_s.pluralize if ActiveRecord::Base.pluralize_table_names
@@ -105,6 +107,8 @@ module Foreigner
105
107
  # t.foreign_key(:people, :column => :sender_id)
106
108
  # ====== Creating a named foreign key
107
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)
108
112
  def foreign_key(to_table, options = {})
109
113
  @base.add_foreign_key(@table_name, to_table, options)
110
114
  end
@@ -43,6 +43,9 @@ module Foreigner
43
43
  # Specify the column name on the from_table that references the to_table. By default this is guessed
44
44
  # to be the singular name of the to_table with "_id" suffixed. So a to_table of :posts will use "post_id"
45
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".
46
49
  # [:name]
47
50
  # Specify the name of the foreign key constraint. This defaults to use from_table and foreign key column.
48
51
  # [:dependent]
@@ -1,14 +1,22 @@
1
- require 'foreigner/connection_adapters/sql_2003'
2
-
3
1
  module Foreigner
4
2
  module ConnectionAdapters
5
3
  module MysqlAdapter
6
4
  include Foreigner::ConnectionAdapters::Sql2003
7
5
 
6
+ def remove_foreign_key(table, options)
7
+ if Hash === options
8
+ foreign_key_name = foreign_key_name(table, options[:column], options)
9
+ else
10
+ foreign_key_name = foreign_key_name(table, "#{options.to_s.singularize}_id")
11
+ end
12
+
13
+ execute "ALTER TABLE #{quote_table_name(table)} DROP FOREIGN KEY #{quote_column_name(foreign_key_name)}"
14
+ end
15
+
8
16
  def foreign_keys(table_name)
9
- foreign_keys = []
10
17
  fk_info = select_all %{
11
18
  SELECT fk.referenced_table_name as 'to_table'
19
+ ,fk.referenced_column_name as 'primary_key'
12
20
  ,fk.column_name as 'column'
13
21
  ,fk.constraint_name as 'name'
14
22
  FROM information_schema.key_column_usage fk
@@ -19,8 +27,9 @@ module Foreigner
19
27
 
20
28
  create_table_info = select_one("SHOW CREATE TABLE #{quote_table_name(table_name)}")["Create Table"]
21
29
 
22
- fk_info.each do |row|
23
- options = {:column => row['column'], :name => row['name']}
30
+ fk_info.map do |row|
31
+ options = {:column => row['column'], :name => row['name'], :primary_key => row['primary_key']}
32
+
24
33
  if create_table_info =~ /CONSTRAINT #{quote_column_name(row['name'])} FOREIGN KEY .* REFERENCES .* ON DELETE (CASCADE|SET NULL)/
25
34
  if $1 == 'CASCADE'
26
35
  options[:dependent] = :delete
@@ -28,10 +37,8 @@ module Foreigner
28
37
  options[:dependent] = :nullify
29
38
  end
30
39
  end
31
- foreign_keys << ForeignKeyDefinition.new(table_name, row['to_table'], options)
40
+ ForeignKeyDefinition.new(table_name, row['to_table'], options)
32
41
  end
33
-
34
- foreign_keys
35
42
  end
36
43
  end
37
44
  end
@@ -1,36 +1,46 @@
1
- require 'foreigner/connection_adapters/sql_2003'
2
-
3
1
  module Foreigner
4
2
  module ConnectionAdapters
5
3
  module PostgreSQLAdapter
6
4
  include Foreigner::ConnectionAdapters::Sql2003
5
+
6
+ def remove_foreign_key(table, options)
7
+ if Hash === options
8
+ foreign_key_name = foreign_key_name(table, options[:column], options)
9
+ else
10
+ foreign_key_name = foreign_key_name(table, "#{options.to_s.singularize}_id")
11
+ end
12
+
13
+ execute "ALTER TABLE #{quote_table_name(table)} DROP CONSTRAINT #{quote_column_name(foreign_key_name)}"
14
+ end
7
15
 
8
16
  def foreign_keys(table_name)
9
17
  fk_info = select_all %{
10
- select tc.constraint_name as name
18
+ SELECT tc.constraint_name as name
11
19
  ,ccu.table_name as to_table
20
+ ,ccu.column_name as primary_key
12
21
  ,kcu.column_name as column
13
22
  ,rc.delete_rule as dependency
14
- from information_schema.table_constraints tc
15
- join information_schema.key_column_usage kcu
16
- using (constraint_catalog, constraint_schema, constraint_name)
17
- join information_schema.referential_constraints rc
18
- using (constraint_catalog, constraint_schema, constraint_name)
19
- join information_schema.constraint_column_usage ccu
20
- using (constraint_catalog, constraint_schema, constraint_name)
21
- where tc.constraint_type = 'FOREIGN KEY'
22
- and tc.constraint_catalog = '#{@config[:database]}'
23
- and tc.table_name = '#{table_name}'
23
+ FROM information_schema.table_constraints tc
24
+ JOIN information_schema.key_column_usage kcu
25
+ USING (constraint_catalog, constraint_schema, constraint_name)
26
+ JOIN information_schema.referential_constraints rc
27
+ USING (constraint_catalog, constraint_schema, constraint_name)
28
+ JOIN information_schema.constraint_column_usage ccu
29
+ USING (constraint_catalog, constraint_schema, constraint_name)
30
+ WHERE tc.constraint_type = 'FOREIGN KEY'
31
+ AND tc.constraint_catalog = '#{@config[:database]}'
32
+ AND tc.table_name = '#{table_name}'
24
33
  }
25
34
 
26
- fk_info.inject([]) do |foreign_keys, row|
27
- options = {:column => row['column'], :name => row['name']}
35
+ fk_info.map do |row|
36
+ options = {:column => row['column'], :name => row['name'], :primary_key => row['primary_key']}
37
+
28
38
  if row['dependency'] == 'CASCADE'
29
39
  options[:dependent] = :delete
30
40
  elsif row['dependency'] == 'SET NULL'
31
41
  options[:dependent] = :nullify
32
42
  end
33
- foreign_keys << ForeignKeyDefinition.new(table_name, row['to_table'], options)
43
+ ForeignKeyDefinition.new(table_name, row['to_table'], options)
34
44
  end
35
45
  end
36
46
  end
@@ -19,23 +19,14 @@ module Foreigner
19
19
 
20
20
  def foreign_key_definition(to_table, options = {})
21
21
  column = options[:column] || "#{to_table.to_s.singularize}_id"
22
+ primary_key = options[:primary_key] || "id"
22
23
  dependency = dependency_sql(options[:dependent])
23
24
 
24
- sql = "FOREIGN KEY (#{quote_column_name(column)}) REFERENCES #{quote_table_name(to_table)}(id)"
25
+ sql = "FOREIGN KEY (#{quote_column_name(column)}) REFERENCES #{quote_table_name(to_table)}(#{primary_key})"
25
26
  sql << " #{dependency}" unless dependency.blank?
26
27
  sql
27
28
  end
28
29
 
29
- def remove_foreign_key(table, options)
30
- if Hash === options
31
- foreign_key_name = foreign_key_name(table, options[:column], options)
32
- else
33
- foreign_key_name = foreign_key_name(table, "#{options.to_s.singularize}_id")
34
- end
35
-
36
- execute "ALTER TABLE #{quote_table_name(table)} DROP FOREIGN KEY #{quote_column_name(foreign_key_name)}"
37
- end
38
-
39
30
  private
40
31
  def foreign_key_name(table, column, options = {})
41
32
  if options[:name]
@@ -21,8 +21,14 @@ module Foreigner
21
21
  add_foreign_key_statements = foreign_keys.map do |foreign_key|
22
22
  statement_parts = [ ('add_foreign_key ' + foreign_key.from_table.inspect) ]
23
23
  statement_parts << foreign_key.to_table.inspect
24
- statement_parts << (':column => ' + foreign_key.options[:column].inspect)
25
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
26
32
  if foreign_key.options[:dependent].present?
27
33
  statement_parts << (':dependent => ' + foreign_key.options[:dependent].inspect)
28
34
  end
data/lib/foreigner.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'foreigner/connection_adapters/abstract/schema_statements'
2
2
  require 'foreigner/connection_adapters/abstract/schema_definitions'
3
+ require 'foreigner/connection_adapters/sql_2003'
3
4
  require 'foreigner/schema_dumper'
4
5
 
5
6
  module ActiveRecord
@@ -13,7 +14,7 @@ module ActiveRecord
13
14
  end
14
15
 
15
16
  Base.class_eval do
16
- if ['MySQL', 'PostgreSQL'].include? connection.adapter_name
17
+ if %w(MySQL PostgreSQL).include? connection.adapter_name
17
18
  require "foreigner/connection_adapters/#{connection.adapter_name.downcase}_adapter"
18
19
  end
19
20
  end
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.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Higgins
@@ -26,9 +26,7 @@ files:
26
26
  - Rakefile
27
27
  - README
28
28
  - lib/foreigner.rb
29
- - lib/foreigner
30
29
  - lib/foreigner/schema_dumper.rb
31
- - lib/foreigner/connection_adapters
32
30
  - lib/foreigner/connection_adapters/sql_2003.rb
33
31
  - lib/foreigner/connection_adapters/mysql_adapter.rb
34
32
  - lib/foreigner/connection_adapters/postgresql_adapter.rb
@@ -36,9 +34,10 @@ files:
36
34
  - lib/foreigner/connection_adapters/abstract/schema_statements.rb
37
35
  - test/helper.rb
38
36
  - test/mysql_adapter_test.rb
39
- has_rdoc: false
37
+ has_rdoc: true
40
38
  homepage: http://github.com/matthuhiggins/foreigner/tree/master
41
- licenses:
39
+ licenses: []
40
+
42
41
  post_install_message:
43
42
  rdoc_options:
44
43
  - --line-numbers
@@ -60,7 +59,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
60
59
  version:
61
60
  requirements: []
62
61
 
63
- rubyforge_project: foreigner
62
+ rubyforge_project:
64
63
  rubygems_version: 1.3.5
65
64
  signing_key:
66
65
  specification_version: 1