aspgems-foreign_key_migrations 2.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. data/.gitignore +3 -0
  2. data/CHANGELOG +109 -0
  3. data/Gemfile +3 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +91 -0
  6. data/Rakefile +69 -0
  7. data/foreign_key_migrations.gemspec +28 -0
  8. data/init.rb +1 -0
  9. data/install.rb +1 -0
  10. data/lib/foreign_key_migrations.rb +48 -0
  11. data/lib/foreign_key_migrations/active_record/base.rb +36 -0
  12. data/lib/foreign_key_migrations/active_record/connection_adapters/schema_statements.rb +23 -0
  13. data/lib/foreign_key_migrations/active_record/connection_adapters/table_definition.rb +50 -0
  14. data/lib/foreign_key_migrations/active_record/migration.rb +62 -0
  15. data/lib/foreign_key_migrations/version.rb +3 -0
  16. data/lib/generators/foreign_key_migrations/migration_generator.rb +38 -0
  17. data/lib/generators/foreign_key_migrations/templates/migration.rb +10 -0
  18. data/spec/aaa_create_tables_spec.rb +9 -0
  19. data/spec/connections/mysql/connection.rb +16 -0
  20. data/spec/connections/mysql2/connection.rb +16 -0
  21. data/spec/connections/postgresql/connection.rb +13 -0
  22. data/spec/migration_spec.rb +257 -0
  23. data/spec/models/comment.rb +3 -0
  24. data/spec/models/post.rb +3 -0
  25. data/spec/models/user.rb +2 -0
  26. data/spec/references_spec.rb +48 -0
  27. data/spec/schema/schema.rb +24 -0
  28. data/spec/schema_dumper_spec.rb +32 -0
  29. data/spec/schema_spec.rb +65 -0
  30. data/spec/spec_helper.rb +15 -0
  31. data/spec/support/helpers.rb +8 -0
  32. data/spec/support/matchers/foreign_key_migrations_matchers.rb +2 -0
  33. data/spec/support/matchers/have_index.rb +52 -0
  34. data/spec/support/matchers/reference.rb +66 -0
  35. metadata +144 -0
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ spec/db/*db
2
+ spec/debug.log
3
+
data/CHANGELOG ADDED
@@ -0,0 +1,109 @@
1
+ [REVISION 20080131]
2
+
3
+ [FIXED] Stack-level too deep.
4
+
5
+ [NEW] Generate foreign keys for databases that currently have none. Doesn't check to see if the foreign key already exists, nor does it drop the foreign keys yet.
6
+
7
+ [REVISION 20071128]
8
+
9
+ [FIXED] Workaround to ensure plugin is only ever loaded once.
10
+
11
+ [REVISION 20070905]
12
+
13
+ [FIXED] "some_column_name" referenced in foreign key constraint does not exist.
14
+
15
+ [REVISION 20070904]
16
+
17
+ [NEW] Support :references keyword when calling primary_key().
18
+
19
+ [NEW] [#11995] the parameter :references needs the second argument referencing the field name.
20
+
21
+ [REVISION 20070707]
22
+
23
+ [NEW] Support acts_as_tree convention: if a column is named parent_id it will be treated as a circular reference to the table in which it is defined.
24
+
25
+ [REVISION 20070703]
26
+
27
+ [FIXED] Foreign-keys not created when using add_column.
28
+
29
+ [REVISION 20070628]
30
+
31
+ [FIXED] Stack level too deep in 'add_column_without_foreign_key_migrations' (Ronen Barzel).
32
+
33
+ [REVISION 20070503]
34
+
35
+ [NEW] Support for SQL92 [NOT] DEFERRABLE on foreign keys.
36
+
37
+ [REVISION 20061202]
38
+
39
+ [CHANGED] Use Rails 1.2 alias_method_chain.
40
+
41
+ [CHANGED] Separate modules into individual files.
42
+
43
+ [REVISION 20061013]
44
+
45
+ [NEW] install.rb informs user of missing dependencies.
46
+
47
+ [REVISION 20060909]
48
+
49
+ [CHANGED] Replaced dependence on defunct Foreign Key Support and Schema Defining plugins with a single dependece on RedHill on Rails Core.
50
+
51
+ [REVISION 20060831]
52
+
53
+ [CHANGED] Separated out generic foreign-key functionality into new foreign key support plugin.
54
+
55
+ [REVISION 20060629]
56
+
57
+ [NEW] Added foreign_key method to table to allow t.foreign_key(columns, references_table_name, references_column_names, options).
58
+
59
+ [NEW] Support foreign keys in add_column as we do for initial table columns.
60
+
61
+ [NEW] Support :on_update and :on_delete as options--with values of :set_null, :cascade, or :restrict--for all foreign key creation mechanisms.
62
+
63
+ [REVISION 20060627]
64
+
65
+ [CHANGED] Reverted to overloaded column method with optional :references as the preferred mechanism with belongs_to a "nicety". This is really as a result of using it in a large-scale production application where belongs_to just didn't feel right in many cases and was semantically ambiguous.
66
+
67
+ [REVISION 20060824]
68
+
69
+ [CHANGED] Replaced method and column option :references with :belongs_to in keeping with the rails model keywords. The references variations are still available but have been deprecated and will be removed.
70
+
71
+ [NEW] Added options :dependent => :nullify to SET NULL or :dependent => :delete_all | :destroy to CASCADE DELETE.
72
+
73
+ [REVISION 20060812]
74
+
75
+ [NEW] Added new table method references(table, options) which is essentially an alias for column(:table_id, :integer, options).
76
+
77
+ [REVISION 20060803]
78
+
79
+ [FIXED] The method proper_pluralized_table_name tries to call pluralize_table_name where it should call pluralized_table_name.
80
+
81
+ [REVISION 20060623]
82
+
83
+ [FIXED] Another try at a hack-around for a "feature" of pluralize that when called to pluralize a word that is already in the plural, acts as singularize.
84
+
85
+ [REVISION 20060616]
86
+
87
+ [FIXED] Hack-around for a "feature" of pluralize that when called to pluralize a word that is already in the plural, acts as singularize. Ie. "countries".pluralize becomes "country"!
88
+
89
+ [REVISION 200606004]
90
+
91
+ [CHANGED] This plugin now depends on Schema Defining!
92
+
93
+ [REVISION 20060602]
94
+
95
+ [CHANGED] Simplified static method overriding thanks to Ryan Tomayko.
96
+
97
+ [REVISION 20060525]
98
+
99
+ [CHANGED] Disabled foreign-key generation when executing a schema dump. This is a temporary measure until I get around to batching up the foreign keys at the end of the script.
100
+
101
+ [REVISION 20060523]
102
+
103
+ [NEW] Support :references => nil to prevent unwanted foreign-keys.
104
+
105
+ [FIXED] Pluralization.
106
+
107
+ [REVISION 20060522]
108
+
109
+ [FIXED] Infinite recursion caused by bug in 1.8.4 method_alias on windows.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2006 RedHill Consulting, Pty. Ltd.
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.md ADDED
@@ -0,0 +1,91 @@
1
+ # Foreign Key Migrations
2
+
3
+ Foreign Key Migrations is a plugin that automatically generates foreign-key
4
+ constraints when creating tables. It uses SQL-92 syntax and as such should be
5
+ compatible with most databases that support foreign-key constraints.
6
+
7
+ In the simplest case, the plugin assumes that if you have a column named
8
+ <tt>customer_id</tt> that you want a foreign-key constraint generated that references
9
+ the <tt>id</tt> column in the <tt>customers</tt> table:
10
+
11
+ create_table :orders do |t|
12
+ t.column :customer_id, :integer, :null => false
13
+ ...
14
+ end
15
+
16
+ If you have multiple columns referencing a table or for whatever reason, your
17
+ column name isn't the same as the referenced table name, you can use the
18
+ `:references` option:
19
+
20
+ create_table :orders do |t|
21
+ t.column :ordered_by_id, :integer, :null => false, :references => :customers
22
+ ...
23
+ end
24
+
25
+ If you have a column with a name ending in <tt>_id</tt> for which you do not wish a
26
+ foreign-key to be generated, you can use `:references => nil`:
27
+
28
+ create_table :orders do |t|
29
+ t.column :external_id, :integer, :null => false, :references => nil
30
+ ...
31
+ end
32
+
33
+ Sometimes you may (for legacy reasons) need to reference a primary key column that is
34
+ named something other than <tt>id</tt>. In this case you can specify the name of the column:
35
+
36
+ create_table :orders do |t|
37
+ t.column :ordered_by_pk, :integer, :null => false, :references => [:customers, :pk]
38
+ ...
39
+ end
40
+
41
+ You also have the option of specifying what to do on delete/update using
42
+ `:on_delete`/`:on_update`, respectively to one of:
43
+ `:cascade`; `:restrict`; and `:set_null`:
44
+
45
+ create_table :orders do |t|
46
+ t.column :customer_id, :integer, :on_delete => :set_null, :on_update => :cascade
47
+ ...
48
+ end
49
+
50
+ If your database supports it (for example PostgreSQL) you can also mark the constraint as deferrable:
51
+
52
+ create_table :orders do |t|
53
+ t.column :customer_id, :integer, :deferrable => true
54
+ ...
55
+ end
56
+
57
+ By convention, if a column is named <tt>parent_id</tt> it will be treated as a circular reference to
58
+ the table in which it is defined.
59
+
60
+ Sometimes you may (for legacy reasons) need to name your primary key column such that it
61
+ would be misinterpreted as a foreign-key (say for example if you named the primary key
62
+ <tt>order_id</tt>). In this case you can manually create the primary key as follows:
63
+
64
+ create_table :orders, :id => false do |t|
65
+ ...
66
+ t.primary_key :order_id, :references => nil
67
+ end
68
+
69
+ There is also a generator for creating foreign keys on a database that currently has none:
70
+
71
+ ruby script/generate foreign_key_migration
72
+
73
+ The plugin fully supports and understands the following active-record
74
+ configuration properties:
75
+
76
+ * `config.active_record.pluralize_table_names`
77
+ * `config.active_record.table_name_prefix`
78
+ * `config.active_record.table_name_suffix`
79
+
80
+ ## Dependencies
81
+
82
+ * RedHill on Rails Core (redhillonrails_core) aspgems version.
83
+
84
+ ## NOTE
85
+
86
+ * Code was created by harukizaemon(http://github.com/harukizaemon) but is not supported currently by him.
87
+
88
+ ## License
89
+
90
+ This plugin is copyright 2006 by RedHill Consulting, Pty. Ltd. and is released
91
+ under the MIT license.
data/Rakefile ADDED
@@ -0,0 +1,69 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ %w[postgresql mysql mysql2].each do |adapter|
6
+ namespace adapter do
7
+ RSpec::Core::RakeTask.new(:spec) do |spec|
8
+ spec.rspec_opts = "-Ispec/connections/#{adapter}"
9
+ end
10
+ end
11
+ end
12
+
13
+ desc 'Run postgresql and mysql tests'
14
+ task :spec do
15
+ %w[postgresql mysql mysql2].each do |adapter|
16
+ Rake::Task["#{adapter}:spec"].invoke
17
+ end
18
+ end
19
+
20
+ task :default => :spec
21
+
22
+ require 'rake/rdoctask'
23
+ Rake::RDocTask.new do |rdoc|
24
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
25
+
26
+ rdoc.rdoc_dir = 'rdoc'
27
+ rdoc.title = "foreign key migrations #{version}"
28
+ rdoc.rdoc_files.include('README*')
29
+ rdoc.rdoc_files.include('lib/**/*.rb')
30
+ end
31
+
32
+ namespace :postgresql do
33
+ desc 'Build the PostgreSQL test databases'
34
+ task :build_databases do
35
+ %x( createdb -E UTF8 fkm_unittest )
36
+ end
37
+
38
+ desc 'Drop the PostgreSQL test databases'
39
+ task :drop_databases do
40
+ %x( dropdb fkm_unittest )
41
+ end
42
+
43
+ desc 'Rebuild the PostgreSQL test databases'
44
+ task :rebuild_databases => [:drop_databases, :build_databases]
45
+ end
46
+
47
+ task :build_postgresql_databases => 'postgresql:build_databases'
48
+ task :drop_postgresql_databases => 'postgresql:drop_databases'
49
+ task :rebuild_postgresql_databases => 'postgresql:rebuild_databases'
50
+
51
+ MYSQL_DB_USER = 'fkm'
52
+ namespace :mysql do
53
+ desc 'Build the MySQL test databases'
54
+ task :build_databases do
55
+ %x( echo "create DATABASE fkm_unittest DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci " | mysql --user=#{MYSQL_DB_USER})
56
+ end
57
+
58
+ desc 'Drop the MySQL test databases'
59
+ task :drop_databases do
60
+ %x( mysqladmin --user=#{MYSQL_DB_USER} -f drop fkm_unittest )
61
+ end
62
+
63
+ desc 'Rebuild the MySQL test databases'
64
+ task :rebuild_databases => [:drop_databases, :build_databases]
65
+ end
66
+
67
+ task :build_mysql_databases => 'mysql:build_databases'
68
+ task :drop_mysql_databases => 'mysql:drop_databases'
69
+ task :rebuild_mysql_databases => 'mysql:rebuild_databases'
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "foreign_key_migrations/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "aspgems-foreign_key_migrations"
7
+ s.version = ForeignKeyMigrations::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Michał Łomnicki", "Paco Guzmán"]
10
+ s.email = ["michal.lomnicki@gmail.com", "fjguzman@aspgems.com"]
11
+ s.homepage = "https://github.com/aspgems/foreign_key_migrations"
12
+ s.summary = "Automatically generate foreign-key constraints when creating tables"
13
+ s.description = "Automatic Foreign Key automatically generates foreign-key \
14
+ constraints when creating tables or adding columns. It uses SQL-92 syntax and as such should be compatible with most databases that support foreign-key constraints."
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_dependency("aspgems-redhillonrails_core", "~> 2.0.0.beta2")
22
+
23
+ s.add_development_dependency("rspec", "~> 2.5.0")
24
+ s.add_development_dependency("pg")
25
+ s.add_development_dependency("mysql")
26
+ s.add_development_dependency("mysql2")
27
+ end
28
+
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'foreign_key_migrations' unless defined?(ForeignKeyMigrations)
data/install.rb ADDED
@@ -0,0 +1 @@
1
+ puts "Note redhillonrails_core dependency is needed"
@@ -0,0 +1,48 @@
1
+ require 'redhillonrails_core'
2
+
3
+ module ForeignKeyMigrations
4
+ module ActiveRecord
5
+ extend ActiveSupport::Autoload
6
+
7
+ autoload :Base
8
+ autoload :Migration
9
+
10
+ module ConnectionAdapters
11
+ extend ActiveSupport::Autoload
12
+
13
+ autoload :TableDefinition
14
+ autoload :SchemaStatements
15
+ end
16
+ end
17
+
18
+ # Default FK update action
19
+ mattr_accessor :on_update
20
+ @@on_update = :restrict
21
+
22
+ # Default FK delete action
23
+ mattr_accessor :on_delete
24
+ @@on_delete = :restrict
25
+
26
+ # Create an index after creating FK (default false)
27
+ mattr_accessor :auto_index
28
+ @@auto_index = nil
29
+
30
+ # FIXME Not used by now
31
+ def self.setup(&block)
32
+ yield self
33
+ end
34
+
35
+ def self.options_for_index(index)
36
+ index.is_a?(Hash) ? index : {}
37
+ end
38
+
39
+ def self.set_default_update_and_delete_actions!(options)
40
+ options[:on_update] = options.fetch(:on_update, ForeignKeyMigrations.on_update)
41
+ options[:on_delete] = options.fetch(:on_delete, ForeignKeyMigrations.on_delete)
42
+ end
43
+ end
44
+
45
+ ActiveRecord::Base.send(:include, ForeignKeyMigrations::ActiveRecord::Base)
46
+ ActiveRecord::Migration.send(:include, ForeignKeyMigrations::ActiveRecord::Migration)
47
+ ActiveRecord::ConnectionAdapters::TableDefinition.send(:include, ForeignKeyMigrations::ActiveRecord::ConnectionAdapters::TableDefinition)
48
+ ActiveRecord::ConnectionAdapters::SchemaStatements.send(:include, ForeignKeyMigrations::ActiveRecord::ConnectionAdapters::SchemaStatements)
@@ -0,0 +1,36 @@
1
+ module ForeignKeyMigrations::ActiveRecord
2
+ module Base
3
+ def self.included(base) # :nodoc
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+ # Determines referenced table and column.
9
+ # Used in migrations.
10
+ # references('comments', 'post_id') # => ['posts', 'id']
11
+ #
12
+ # If <tt>column_name</tt> is parent_id it references to the same table
13
+ # references('pages', 'parent_id') # => ['pages', 'id']
14
+ #
15
+ # If referenced table cannot be determined properly it may be overriden
16
+ # references('widgets', 'main_page_id', :references => 'pages'))
17
+ # # => ['pages', 'id']
18
+ #
19
+ # Also whole result may be given by hand
20
+ # references('addresses', 'member_id', :references => ['users', 'uuid'])
21
+ # # => ['users', 'uuid']
22
+ def references(table_name, column_name, options = {})
23
+ column_name = column_name.to_s
24
+ if options.has_key?(:references)
25
+ references = options[:references]
26
+ references = [references, :id] unless references.nil? || references.is_a?(Array)
27
+ references
28
+ elsif column_name == 'parent_id'
29
+ [table_name, :id]
30
+ elsif column_name =~ /^(.*)_id$/
31
+ [pluralized_table_name($1), :id]
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,23 @@
1
+ module ForeignKeyMigrations::ActiveRecord::ConnectionAdapters
2
+ module SchemaStatements
3
+
4
+ def self.included(base)
5
+ base.class_eval do
6
+ alias_method_chain :create_table, :foreign_key_migrations
7
+ end
8
+ end
9
+
10
+ def create_table_with_foreign_key_migrations(table, options = {})
11
+ indices = nil
12
+ create_table_without_foreign_key_migrations(table, options) do |table_definition|
13
+ yield table_definition if block_given?
14
+ indices = table_definition.indices
15
+ end
16
+ indices.each do |column_name, index_options|
17
+ column_names = [column_name] + Array.wrap(index_options.delete(:with))
18
+ add_index(table, column_names, index_options)
19
+ end
20
+ end
21
+
22
+ end
23
+ end