foreigner 1.6.1 → 1.7.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6267757603fa3cc7daf2d7c9fb0cd5c3c0b5de57
4
- data.tar.gz: 59ba0f7366cbfbbc9c315c6a4f3141c7ccefd887
3
+ metadata.gz: dd7dbe28f6138244683eb3608d4bac19560dda16
4
+ data.tar.gz: 584f38f853a0f97d15600e48f7f8b01b4bee182d
5
5
  SHA512:
6
- metadata.gz: 0692abaca90f8bf9afe7a1b034062741d1cb6288816f7491aac15e566392121338dab6814bd94adf3dabb0a1acd0262d1f62af938cc34030947be52ca26f3736
7
- data.tar.gz: 17fd7783a3127006a0a2284f4c82ea4960fd81115c6a56c9fff3a2159952cf18b8aac1f7f8da1842e8f514308f87b38c6b0acc2e3e5b4dac7421e25fab3da8b6
6
+ metadata.gz: 4a61ab89633713aa621dc783ec6a9fa87764e307b2a579f342410a2cadd53013b7dbec3f9034298166cb3d035f866eb58959d312687eb57c1d891f624f306613
7
+ data.tar.gz: df79723061e8ffe3bc5e11f69728874740ccef05f87c55d6e6fbd870851d569c16b035c9a6287d02da6b08d8ebf647ec01c8e2f21cd1fe7932b4ec4afdfa7d78
data/README.md CHANGED
@@ -13,46 +13,46 @@ The following adapters are supported:
13
13
 
14
14
  Add the following to your Gemfile:
15
15
  ```ruby
16
- gem 'foreigner'
16
+ gem 'foreigner'
17
17
  ```
18
18
  ## API Examples
19
19
 
20
20
  Foreigner adds two methods to migrations.
21
21
 
22
22
  * `add_foreign_key(from_table, to_table, options)`
23
- * `remove_foreign_key(from_table, options)`
23
+ * `remove_foreign_key(from_table, to_table, options)`
24
24
 
25
25
  (Options are documented in `connection_adapters/abstract/schema_statements.rb`):
26
26
 
27
27
  For example, given the following model:
28
28
  ```ruby
29
- class Comment < ActiveRecord::Base
30
- belongs_to :post
31
- end
29
+ class Comment < ActiveRecord::Base
30
+ belongs_to :post
31
+ end
32
32
 
33
- class Post < ActiveRecord::Base
34
- has_many :comments, dependent: :delete_all
35
- end
33
+ class Post < ActiveRecord::Base
34
+ has_many :comments, dependent: :delete_all
35
+ end
36
36
  ```
37
37
  You should add a foreign key in your migration:
38
38
  ```ruby
39
- add_foreign_key(:comments, :posts)
39
+ add_foreign_key(:comments, :posts)
40
40
  ```
41
41
  The `:dependent` option can be moved from the `has_many` definition to the foreign key:
42
42
  ```ruby
43
- add_foreign_key(:comments, :posts, dependent: :delete)
43
+ add_foreign_key(:comments, :posts, dependent: :delete)
44
44
  ```
45
45
  If the column is named `article_id` instead of `post_id`, use the `:column` option:
46
46
  ```ruby
47
- add_foreign_key(:comments, :posts, column: 'article_id')
47
+ add_foreign_key(:comments, :posts, column: 'article_id')
48
48
  ```
49
49
  A name can be specified for the foreign key constraint:
50
50
  ```ruby
51
- add_foreign_key(:comments, :posts, name: 'comment_article_foreign_key')
51
+ add_foreign_key(:comments, :posts, name: 'comment_article_foreign_key')
52
52
  ```
53
53
  The `:column` and `:name` options create a foreign key with a custom name. In order to remove it you need to specify `:name`:
54
54
  ```ruby
55
- remove_foreign_key(:comments, name: 'comment_article_foreign_key')
55
+ remove_foreign_key(:comments, name: 'comment_article_foreign_key')
56
56
  ```
57
57
  ## Change Table Methods
58
58
 
@@ -60,29 +60,29 @@ Foreigner adds extra methods to `create_table` and `change_table`.
60
60
 
61
61
  Create a new table with a foreign key:
62
62
  ```ruby
63
- create_table :products do |t|
64
- t.string :name
65
- t.integer :factory_id
66
- t.foreign_key :factories
67
- end
63
+ create_table :products do |t|
64
+ t.string :name
65
+ t.integer :factory_id
66
+ t.foreign_key :factories
67
+ end
68
68
  ```
69
69
  Add a missing foreign key to comments:
70
70
  ```ruby
71
- change_table :comments do |t|
72
- t.foreign_key :posts, dependent: :delete
73
- end
71
+ change_table :comments do |t|
72
+ t.foreign_key :posts, dependent: :delete
73
+ end
74
74
  ```
75
75
  Remove an unwanted foreign key:
76
76
  ```ruby
77
- change_table :comments do |t|
78
- t.remove_foreign_key :users
79
- end
77
+ change_table :comments do |t|
78
+ t.remove_foreign_key :users
79
+ end
80
80
  ```
81
81
  ## Database-specific options
82
82
 
83
83
  Database-specific options will never be supported by foreigner. You can add them using `:options`:
84
84
  ```ruby
85
- add_foreign_key(:comments, :posts, options: 'ON UPDATE DEFERRED')
85
+ add_foreign_key(:comments, :posts, options: 'ON UPDATE DEFERRED')
86
86
  ```
87
87
  ## Foreigner Add-ons
88
88
 
@@ -26,12 +26,13 @@ module Foreigner
26
26
  fk_info.map do |row|
27
27
  options = {column: row['column'], name: row['name'], primary_key: row['primary_key']}
28
28
 
29
- if create_table_info =~ /CONSTRAINT #{quote_column_name(row['name'])} FOREIGN KEY .* REFERENCES .* ON DELETE (CASCADE|SET NULL|RESTRICT)/
29
+ if create_table_info =~ /CONSTRAINT #{quote_column_name(row['name'])} FOREIGN KEY .* REFERENCES .*\)(?: ON DELETE (CASCADE|SET NULL|RESTRICT))?(?: (.+?))?,?$/
30
30
  options[:dependent] = case $1
31
31
  when 'CASCADE' then :delete
32
32
  when 'SET NULL' then :nullify
33
33
  when 'RESTRICT' then :restrict
34
34
  end
35
+ options[:options] = $2 # e.g. ON UPDATE ...
35
36
  end
36
37
  ForeignKeyDefinition.new(table_name, row['to_table'], options)
37
38
  end
@@ -3,9 +3,19 @@ module Foreigner
3
3
  module PostgreSQLAdapter
4
4
  include Foreigner::ConnectionAdapters::Sql2003
5
5
 
6
+ DEPENDENCY_CODE_ACTIONS = {'c' => 'CASCADE', 'n' => 'SET NULL', 'r' => 'RESTRICT', 'd' => 'SET DEFAULT'}
7
+
6
8
  def foreign_keys(table_name)
7
9
  fk_info = select_all %{
8
- SELECT t2.relname AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confdeltype AS dependency
10
+ SELECT t2.relname AS to_table
11
+ , a1.attname AS column
12
+ , a2.attname AS primary_key
13
+ , c.conname AS name
14
+ , c.confdeltype AS dependency
15
+ , c.confupdtype AS update_dependency
16
+ , c.condeferrable AS deferrable
17
+ , c.condeferred AS deferred
18
+ #{", c.convalidated AS valid" if postgresql_version >= 90100}
9
19
  FROM pg_constraint c
10
20
  JOIN pg_class t1 ON c.conrelid = t1.oid
11
21
  JOIN pg_class t2 ON c.confrelid = t2.oid
@@ -22,11 +32,23 @@ module Foreigner
22
32
  options = {column: row['column'], name: row['name'], primary_key: row['primary_key']}
23
33
 
24
34
  options[:dependent] = case row['dependency']
35
+ # NO ACTION is the default
36
+ # SET DEFAULT is handled below, since it is postgres-specific
25
37
  when 'c' then :delete
26
38
  when 'n' then :nullify
27
39
  when 'r' then :restrict
28
40
  end
29
41
 
42
+ extras = []
43
+ extras << "ON DELETE SET DEFAULT" if row['dependency'] == 'd'
44
+ if update_action = DEPENDENCY_CODE_ACTIONS[row['update_dependency']]
45
+ extras << "ON UPDATE #{update_action}"
46
+ end
47
+ extras << 'DEFERRABLE' if row['deferrable'] == 't'
48
+ extras << 'INITIALLY DEFERRED' if row['deferred'] == 't'
49
+ extras << 'NOT VALID' if row['valid'] == 'f'
50
+ options[:options] = extras.join(" ")
51
+
30
52
  ForeignKeyDefinition.new(table_name, row['to_table'], options)
31
53
  end
32
54
  end
@@ -35,4 +57,4 @@ module Foreigner
35
57
  end
36
58
 
37
59
  Foreigner::Adapter.safe_include :JdbcAdapter, Foreigner::ConnectionAdapters::PostgreSQLAdapter
38
- Foreigner::Adapter.safe_include :PostgreSQLAdapter, Foreigner::ConnectionAdapters::PostgreSQLAdapter
60
+ Foreigner::Adapter.safe_include :PostgreSQLAdapter, Foreigner::ConnectionAdapters::PostgreSQLAdapter
@@ -8,20 +8,19 @@ module Foreigner
8
8
  def drop_table(*args)
9
9
  options = args.extract_options!
10
10
  if options[:force]
11
- disable_referential_integrity { super }
11
+ disable_referential_integrity { super(*(args.dup << options)) }
12
12
  else
13
- super
13
+ super(*(args.dup << options))
14
14
  end
15
15
  end
16
16
 
17
17
  def foreign_key_exists?(from_table, options)
18
18
  foreign_key_name = decipher_foreign_key_name(from_table, options)
19
-
20
19
  foreign_keys(from_table).any? { |fk| fk.name == foreign_key_name }
21
20
  end
22
21
 
23
22
  def add_foreign_key(from_table, to_table, options = {})
24
- sql = "ALTER TABLE #{quote_table_name(from_table)} #{add_foreign_key_sql(from_table, to_table, options)}"
23
+ sql = "ALTER TABLE #{quote_proper_table_name(from_table)} #{add_foreign_key_sql(from_table, to_table, options)}"
25
24
  execute(sql)
26
25
  end
27
26
 
@@ -31,28 +30,35 @@ module Foreigner
31
30
  primary_key = options[:primary_key] || "id"
32
31
  dependency = dependency_sql(options[:dependent])
33
32
 
34
- proper_name = proper_table_name(to_table)
35
-
36
33
  sql =
37
34
  "ADD CONSTRAINT #{quote_column_name(foreign_key_name)} " +
38
35
  "FOREIGN KEY (#{quote_column_name(column)}) " +
39
- "REFERENCES #{quote_table_name(proper_name)}(#{primary_key})"
36
+ "REFERENCES #{quote_proper_table_name(to_table)}(#{primary_key})"
40
37
  sql << " #{dependency}" if dependency.present?
41
38
  sql << " #{options[:options]}" if options[:options]
42
39
 
43
40
  sql
44
41
  end
45
42
 
46
- def proper_table_name(to_table)
43
+ def quote_proper_table_name(table)
44
+ quote_table_name(proper_table_name(table))
45
+ end
46
+
47
+ def proper_table_name(table)
48
+ # This will normally be a no-op, but prevents the table from being wrapped twice:
49
+ table = Foreigner::SchemaDumper::ClassMethods.remove_prefix_and_suffix(table)
47
50
  if ActiveRecord::Migration.instance_methods(false).include? :proper_table_name
48
- ActiveRecord::Migration.new.proper_table_name(to_table)
51
+ ActiveRecord::Migration.new.proper_table_name(table, options = {
52
+ table_name_prefix: ActiveRecord::Base.table_name_prefix,
53
+ table_name_suffix: ActiveRecord::Base.table_name_suffix
54
+ })
49
55
  else
50
- ActiveRecord::Migrator.proper_table_name(to_table)
56
+ ActiveRecord::Migrator.proper_table_name(table)
51
57
  end
52
58
  end
53
59
 
54
60
  def remove_foreign_key(table, options)
55
- execute "ALTER TABLE #{quote_table_name(table)} #{remove_foreign_key_sql(table, options)}"
61
+ execute "ALTER TABLE #{quote_proper_table_name(table)} #{remove_foreign_key_sql(table, options)}"
56
62
  end
57
63
 
58
64
  def remove_foreign_key_sql(table, options)
@@ -0,0 +1,13 @@
1
+ module Foreigner
2
+ module Helper
3
+ def self.active_record_version
4
+ if ::ActiveRecord.respond_to? :version
5
+ ActiveRecord.version
6
+ elsif ::ActiveRecord::VERSION::STRING
7
+ Gem::Version.new(::ActiveRecord::VERSION::STRING)
8
+ else
9
+ raise "Unknown ActiveRecord Version API"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -21,17 +21,36 @@ module Foreigner
21
21
  if foreign_key.options[:dependent].present?
22
22
  statement_parts << ('dependent: ' + foreign_key.options[:dependent].inspect)
23
23
  end
24
+ if foreign_key.options[:options].present?
25
+ statement_parts << ('options: ' + foreign_key.options[:options].inspect)
26
+ end
24
27
 
25
28
  statement_parts.join(', ')
26
29
  end
27
30
 
28
- def remove_prefix_and_suffix(table)
29
- table.gsub(/^(#{ActiveRecord::Base.table_name_prefix})(.+)(#{ActiveRecord::Base.table_name_suffix})$/, "\\2")
31
+ def remove_prefix_and_suffix(table_name)
32
+ table_name = table_name.to_s
33
+ pre, suff = ActiveRecord::Base.table_name_prefix, ActiveRecord::Base.table_name_suffix
34
+ if table_name.start_with?(pre) && table_name.end_with?(suff)
35
+ table_name[pre.size..-(suff.size + 1)]
36
+ else
37
+ table_name
38
+ end
30
39
  end
40
+ module_function :remove_prefix_and_suffix
41
+ end
42
+
43
+ def requires_foreigner_load?
44
+ major, minor, patch = Foreigner::Helper.active_record_version.segments
45
+ major == 4 && minor == 1 && patch >= 9
31
46
  end
32
47
 
33
48
  def tables_with_foreign_keys(stream)
34
49
  tables_without_foreign_keys(stream)
50
+ # Ensure Foreigner to be initialized before running foreign_keys.
51
+ # This is required since schema::load is not initializing the environment
52
+ # anymore in Rails 4.1.9 (https://github.com/rails/rails/commit/5d6bb89f)
53
+ stream.puts ' Foreigner.load' if requires_foreigner_load?
35
54
  @connection.tables.sort.each do |table|
36
55
  next if ['schema_migrations', ignore_tables].flatten.any? do |ignored|
37
56
  case ignored
data/lib/foreigner.rb CHANGED
@@ -28,8 +28,10 @@ Foreigner::Adapter.register 'mysql', 'foreigner/connection_adapters/mysql_adapte
28
28
  Foreigner::Adapter.register 'mysql2', 'foreigner/connection_adapters/mysql2_adapter'
29
29
  Foreigner::Adapter.register 'jdbcmysql', 'foreigner/connection_adapters/mysql2_adapter'
30
30
  Foreigner::Adapter.register 'postgresql', 'foreigner/connection_adapters/postgresql_adapter'
31
+ Foreigner::Adapter.register 'postgis', 'foreigner/connection_adapters/postgresql_adapter'
31
32
  Foreigner::Adapter.register 'jdbcpostgresql', 'foreigner/connection_adapters/postgresql_adapter'
32
33
  Foreigner::Adapter.register 'sqlite3', 'foreigner/connection_adapters/noop_adapter'
33
34
 
34
35
  require 'foreigner/loader'
36
+ require 'foreigner/helper'
35
37
  require 'foreigner/railtie' if defined?(Rails)
@@ -7,7 +7,7 @@ class Foreigner::ConnectionAdapters::TableDefinitionsTest < ActiveSupport::TestC
7
7
 
8
8
  test "foreign_key used once" do
9
9
  definition = TestDefinition.new
10
- definition.foreign_key :poops, and: :one;
10
+ definition.foreign_key :poops, and: :one
11
11
  assert_equal [{ and: :one }], definition.foreign_keys[:poops]
12
12
  end
13
13
 
@@ -18,4 +18,4 @@ class Foreigner::ConnectionAdapters::TableDefinitionsTest < ActiveSupport::TestC
18
18
  assert_equal [{ column: :from_id }, { column: :to_id }],
19
19
  definition.foreign_keys[:nodes]
20
20
  end
21
- end
21
+ end
@@ -9,6 +9,45 @@ class Foreigner::Mysql2AdapterTest < Foreigner::UnitTest
9
9
 
10
10
  setup do
11
11
  @adapter = Mysql2Adapter.new
12
+ @adapter.instance_variable_set(:@config, database: 'foo')
13
+ end
14
+
15
+ test 'foreign_keys parsing' do
16
+ @adapter.expects(:select_all).at_least_once.returns([
17
+ {'column' => 'foo_id', 'name' => 'foo_bar_foo_id_fk', 'primary_key' => 'id', 'to_table' => 'foo'}
18
+ ])
19
+
20
+ @adapter.expects(:select_one).returns('Create Table' => "CONSTRAINT `foo_bar_foo_id_fk` FOREIGN KEY (`foo_id`) REFERENCES `foo` (`id`)\n")
21
+ assert_equal Foreigner::ConnectionAdapters::ForeignKeyDefinition.new('bar', 'foo', {column:"foo_id", name:"foo_bar_foo_id_fk", primary_key:"id", dependent:nil, options:nil}),
22
+ @adapter.foreign_keys('bar').first
23
+
24
+ @adapter.expects(:select_one).returns('Create Table' => "CONSTRAINT `foo_bar_foo_id_fk` FOREIGN KEY (`foo_id`) REFERENCES `foo` (`id`),\n")
25
+ assert_equal Foreigner::ConnectionAdapters::ForeignKeyDefinition.new('bar', 'foo', {column:"foo_id", name:"foo_bar_foo_id_fk", primary_key:"id", dependent:nil, options:nil}),
26
+ @adapter.foreign_keys('bar').first
27
+
28
+ @adapter.expects(:select_one).returns('Create Table' => "CONSTRAINT `foo_bar_foo_id_fk` FOREIGN KEY (`foo_id`) REFERENCES `foo` (`id`) ON DELETE CASCADE\n")
29
+ assert_equal Foreigner::ConnectionAdapters::ForeignKeyDefinition.new('bar', 'foo', {column:"foo_id", name:"foo_bar_foo_id_fk", primary_key:"id", dependent: :delete, options:nil}),
30
+ @adapter.foreign_keys('bar').first
31
+
32
+ @adapter.expects(:select_one).returns('Create Table' => "CONSTRAINT `foo_bar_foo_id_fk` FOREIGN KEY (`foo_id`) REFERENCES `foo` (`id`) ON DELETE CASCADE,\n")
33
+ assert_equal Foreigner::ConnectionAdapters::ForeignKeyDefinition.new('bar', 'foo', {column:"foo_id", name:"foo_bar_foo_id_fk", primary_key:"id", dependent: :delete, options:nil}),
34
+ @adapter.foreign_keys('bar').first
35
+
36
+ @adapter.expects(:select_one).returns('Create Table' => "CONSTRAINT `foo_bar_foo_id_fk` FOREIGN KEY (`foo_id`) REFERENCES `foo` (`id`) FOO BAR\n")
37
+ assert_equal Foreigner::ConnectionAdapters::ForeignKeyDefinition.new('bar', 'foo', {column:"foo_id", name:"foo_bar_foo_id_fk", primary_key:"id", dependent:nil, options:'FOO BAR'}),
38
+ @adapter.foreign_keys('bar').first
39
+
40
+ @adapter.expects(:select_one).returns('Create Table' => "CONSTRAINT `foo_bar_foo_id_fk` FOREIGN KEY (`foo_id`) REFERENCES `foo` (`id`) FOO BAR,\n")
41
+ assert_equal Foreigner::ConnectionAdapters::ForeignKeyDefinition.new('bar', 'foo', {column:"foo_id", name:"foo_bar_foo_id_fk", primary_key:"id", dependent:nil, options:'FOO BAR'}),
42
+ @adapter.foreign_keys('bar').first
43
+
44
+ @adapter.expects(:select_one).returns('Create Table' => "CONSTRAINT `foo_bar_foo_id_fk` FOREIGN KEY (`foo_id`) REFERENCES `foo` (`id`) ON DELETE CASCADE FOO BAR,\n")
45
+ assert_equal Foreigner::ConnectionAdapters::ForeignKeyDefinition.new('bar', 'foo', {column:"foo_id", name:"foo_bar_foo_id_fk", primary_key:"id", dependent: :delete, options:'FOO BAR'}),
46
+ @adapter.foreign_keys('bar').first
47
+
48
+ @adapter.expects(:select_one).returns('Create Table' => "CONSTRAINT `foo_bar_foo_id_fk` FOREIGN KEY (`foo_id`) REFERENCES `foo` (`id`) ON DELETE CASCADE FOO BAR,\n")
49
+ assert_equal Foreigner::ConnectionAdapters::ForeignKeyDefinition.new('bar', 'foo', {column:"foo_id", name:"foo_bar_foo_id_fk", primary_key:"id", dependent: :delete, options:'FOO BAR'}),
50
+ @adapter.foreign_keys('bar').first
12
51
  end
13
52
 
14
53
  test 'remove_foreign_key_sql by table' do
@@ -31,4 +70,4 @@ class Foreigner::Mysql2AdapterTest < Foreigner::UnitTest
31
70
  @adapter.remove_foreign_key_sql(:suppliers, column: "ship_to_id")
32
71
  )
33
72
  end
34
- end
73
+ end
@@ -2,9 +2,10 @@ require 'helper'
2
2
 
3
3
  class Foreigner::MysqlAdapterTest < Foreigner::UnitTest
4
4
  test 'warning' do
5
+ skip unless respond_to?(:capture) # < not available until 3.1.x
5
6
  output = capture(:stdout) do
6
7
  require 'foreigner/connection_adapters/mysql_adapter'
7
8
  end
8
9
  assert_match /WARNING: Please upgrade to mysql2. The old mysql adapter is not supported by foreigner./, output
9
10
  end
10
- end
11
+ end
@@ -10,6 +10,16 @@ class Foreigner::Sql2003Test < Foreigner::UnitTest
10
10
  @adapter = TestAdapter.new
11
11
  end
12
12
 
13
+ teardown do
14
+ ActiveRecord::Base.table_name_prefix = ''
15
+ ActiveRecord::Base.table_name_suffix = ''
16
+ end
17
+
18
+ def add_table_prefix_and_suffix
19
+ ActiveRecord::Base.table_name_prefix = 'pre_'
20
+ ActiveRecord::Base.table_name_suffix = '_suff'
21
+ end
22
+
13
23
  test 'drop_table without force' do
14
24
  @adapter.drop_table 'shoes'
15
25
  assert !@adapter.instance_variable_get(:@disable_referential_integrity)
@@ -39,6 +49,14 @@ class Foreigner::Sql2003Test < Foreigner::UnitTest
39
49
  )
40
50
  end
41
51
 
52
+ test 'add_without_options with prefix and suffix' do
53
+ add_table_prefix_and_suffix
54
+ assert_equal(
55
+ "ALTER TABLE `pre_employees_suff` ADD CONSTRAINT `employees_company_id_fk` FOREIGN KEY (`company_id`) REFERENCES `pre_companies_suff`(id)",
56
+ @adapter.add_foreign_key(:employees, :companies)
57
+ )
58
+ end
59
+
42
60
  test 'add_with_name' do
43
61
  assert_equal(
44
62
  "ALTER TABLE `employees` ADD CONSTRAINT `favorite_company_fk` FOREIGN KEY (`company_id`) REFERENCES `companies`(id)",
@@ -60,6 +78,14 @@ class Foreigner::Sql2003Test < Foreigner::UnitTest
60
78
  )
61
79
  end
62
80
 
81
+ test 'add_with_column_and_name with prefix and suffix' do
82
+ add_table_prefix_and_suffix
83
+ assert_equal(
84
+ "ALTER TABLE `pre_employees_suff` ADD CONSTRAINT `favorite_company_fk` FOREIGN KEY (`last_employer_id`) REFERENCES `pre_companies_suff`(id)",
85
+ @adapter.add_foreign_key(:employees, :companies, column: 'last_employer_id', name: 'favorite_company_fk')
86
+ )
87
+ end
88
+
63
89
  test 'add_with_delete_dependency' do
64
90
  assert_equal(
65
91
  "ALTER TABLE `employees` ADD CONSTRAINT `employees_company_id_fk` FOREIGN KEY (`company_id`) REFERENCES `companies`(id) " +
@@ -99,6 +125,14 @@ class Foreigner::Sql2003Test < Foreigner::UnitTest
99
125
  )
100
126
  end
101
127
 
128
+ test 'remove_by_table with prefix and suffix' do
129
+ add_table_prefix_and_suffix
130
+ assert_equal(
131
+ "ALTER TABLE `pre_suppliers_suff` DROP CONSTRAINT `suppliers_company_id_fk`",
132
+ @adapter.remove_foreign_key(:suppliers, :companies)
133
+ )
134
+ end
135
+
102
136
  test 'remove_by_name' do
103
137
  assert_equal(
104
138
  "ALTER TABLE `suppliers` DROP CONSTRAINT `belongs_to_supplier`",
@@ -112,4 +146,4 @@ class Foreigner::Sql2003Test < Foreigner::UnitTest
112
146
  @adapter.remove_foreign_key(:suppliers, column: "ship_to_id")
113
147
  )
114
148
  end
115
- end
149
+ end
@@ -1,11 +1,20 @@
1
1
  require 'helper'
2
2
 
3
- ActiveRecord::Migration::CommandRecorder.class_eval do
4
- include ::Foreigner::Migration::CommandRecorder
3
+ if defined?(ActiveRecord::Migration::CommandRecorder)
4
+ ActiveRecord::Migration::CommandRecorder.class_eval do
5
+ include ::Foreigner::Migration::CommandRecorder
6
+ end
5
7
  end
6
8
 
7
9
  class Foreigner::CommandRecorderTest < Foreigner::UnitTest
10
+
11
+ def revert_exists?
12
+ defined?(ActiveRecord::Migration::CommandRecorder) &&
13
+ ActiveRecord::Migration::CommandRecorder.instance_methods.include?(:revert)
14
+ end
15
+
8
16
  setup do
17
+ skip unless revert_exists?
9
18
  @recorder = ActiveRecord::Migration::CommandRecorder.new
10
19
  end
11
20
 
@@ -48,4 +57,4 @@ class Foreigner::CommandRecorderTest < Foreigner::UnitTest
48
57
  # @recorder.inverse
49
58
  # end
50
59
  end
51
- end
60
+ end
@@ -11,7 +11,7 @@ class Foreigner::SchemaDumperTest < Foreigner::UnitTest
11
11
  class MockSchemaDumper
12
12
  cattr_accessor :ignore_tables
13
13
 
14
- attr_accessor :processed_tables
14
+ attr_accessor :processed_tables, :stream
15
15
  def initialize
16
16
  @connection = MockConnection.new
17
17
  @processed_tables = []
@@ -21,6 +21,7 @@ class Foreigner::SchemaDumperTest < Foreigner::UnitTest
21
21
  end
22
22
 
23
23
  def foreign_keys(table, stream)
24
+ self.stream = stream
24
25
  processed_tables << table
25
26
  end
26
27
 
@@ -32,6 +33,7 @@ class Foreigner::SchemaDumperTest < Foreigner::UnitTest
32
33
  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')
33
34
  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)
34
35
  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')
36
+ assert_dump "add_foreign_key \"foos\", \"bars\", name: \"lulz\", options: \"YOLO MAYBE DB-SPECIFIC!\"", Foreigner::ConnectionAdapters::ForeignKeyDefinition.new('foos', 'bars', column: 'bar_id', primary_key: 'id', name: 'lulz', options: "YOLO MAYBE DB-SPECIFIC!")
35
37
  end
36
38
 
37
39
  test 'all tables' do
@@ -48,6 +50,15 @@ class Foreigner::SchemaDumperTest < Foreigner::UnitTest
48
50
  assert_equal ['bar'].to_set, dumper.processed_tables.to_set
49
51
  end
50
52
 
53
+ test '4.1.9 loading error' do
54
+ Foreigner::Helper.stubs(:active_record_version).returns Gem::Version.new("4.1.9")
55
+ MockSchemaDumper.ignore_tables = []
56
+ dumper = MockSchemaDumper.new
57
+ dumper.tables(StringIO.new)
58
+
59
+ assert_match(/Foreigner\.load/, dumper.stream.string)
60
+ end
61
+
51
62
  test 'removes table name suffix and prefix' do
52
63
  begin
53
64
  ActiveRecord::Base.table_name_prefix = 'pre_'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreigner
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.1
4
+ version: 1.7.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Higgins
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-06 00:00:00.000000000 Z
11
+ date: 2015-03-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -24,6 +24,34 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 3.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: mocha
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
27
55
  description: Adds helpers to migrations and dumps foreign keys to schema.rb
28
56
  email: developer@matthewhiggins.com
29
57
  executables: []
@@ -45,6 +73,7 @@ files:
45
73
  - lib/foreigner/connection_adapters/noop_adapter.rb
46
74
  - lib/foreigner/connection_adapters/postgresql_adapter.rb
47
75
  - lib/foreigner/connection_adapters/sql2003.rb
76
+ - lib/foreigner/helper.rb
48
77
  - lib/foreigner/loader.rb
49
78
  - lib/foreigner/migration/command_recorder.rb
50
79
  - lib/foreigner/railtie.rb
@@ -60,7 +89,8 @@ files:
60
89
  - test/foreigner/schema_dumper_test.rb
61
90
  - test/helper.rb
62
91
  homepage: http://github.com/matthuhiggins/foreigner
63
- licenses: []
92
+ licenses:
93
+ - MIT
64
94
  metadata: {}
65
95
  post_install_message:
66
96
  rdoc_options: []
@@ -78,7 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
78
108
  version: 1.3.5
79
109
  requirements: []
80
110
  rubyforge_project: foreigner
81
- rubygems_version: 2.2.0
111
+ rubygems_version: 2.4.5
82
112
  signing_key:
83
113
  specification_version: 4
84
114
  summary: Foreign Keys for Rails