automatic_foreign_key 1.0.2 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -12,7 +12,7 @@ constraints when creating tables. It uses SQL-92 syntax and as such should be co
12
12
  gem.email = "michal.lomnicki@gmail.com"
13
13
  gem.homepage = "http://github.com/mlomnicki/automatic_foreign_key"
14
14
  gem.authors = ["Michał Łomnicki"]
15
- gem.add_dependency "redhillonrails_core", ">= 1.0.2"
15
+ gem.add_dependency "redhillonrails_core", ">= 1.0.4.1"
16
16
  gem.add_dependency "activerecord", ">= 2.2"
17
17
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
18
18
  end
@@ -41,9 +41,32 @@ rescue LoadError
41
41
  end
42
42
  end
43
43
 
44
- task :test => :check_dependencies
44
+ require 'spec/rake/spectask'
45
+ %w[postgresql mysql].each do |adapter|
46
+ namespace adapter do
47
+ Spec::Rake::SpecTask.new(:spec) do |spec|
48
+ spec.libs << 'lib' << 'spec' << "spec/connections/#{adapter}"
49
+ spec.spec_files = FileList['spec/**/*_spec.rb']
50
+ end
51
+ end
52
+ end
53
+
54
+ desc 'Run postgresql and mysql tests'
55
+ task :spec do
56
+ %w[postgresql mysql].each do |adapter|
57
+ Rake::Task["#{adapter}:spec"].invoke
58
+ end
59
+ end
60
+
61
+ task :spec => :check_dependencies
45
62
 
46
- task :default => :test
63
+ task :default => :spec
64
+
65
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
66
+ spec.libs << 'lib' << 'spec'
67
+ spec.pattern = 'spec/**/*_spec.rb'
68
+ spec.rcov = true
69
+ end
47
70
 
48
71
  require 'rake/rdoctask'
49
72
  Rake::RDocTask.new do |rdoc|
@@ -54,3 +77,44 @@ Rake::RDocTask.new do |rdoc|
54
77
  rdoc.rdoc_files.include('README*')
55
78
  rdoc.rdoc_files.include('lib/**/*.rb')
56
79
  end
80
+
81
+ namespace :postgresql do
82
+ desc 'Build the PostgreSQL test databases'
83
+ task :build_databases do
84
+ %x( createdb -E UTF8 afk_unittest )
85
+ %x( createdb -E UTF8 afk_unittest2 )
86
+ end
87
+
88
+ desc 'Drop the PostgreSQL test databases'
89
+ task :drop_databases do
90
+ %x( dropdb afk_unittest )
91
+ %x( dropdb afk_unittest2 )
92
+ end
93
+
94
+ desc 'Rebuild the PostgreSQL test databases'
95
+ task :rebuild_databases => [:drop_databases, :build_databases]
96
+ end
97
+
98
+ task :build_postgresql_databases => 'postgresql:build_databases'
99
+ task :drop_postgresql_databases => 'postgresql:drop_databases'
100
+ task :rebuild_postgresql_databases => 'postgresql:rebuild_databases'
101
+
102
+ MYSQL_DB_USER = 'afk'
103
+ namespace :mysql do
104
+ desc 'Build the MySQL test databases'
105
+ task :build_databases do
106
+ %x( echo "create DATABASE afk_unittest DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci " | mysql --user=#{MYSQL_DB_USER})
107
+ end
108
+
109
+ desc 'Drop the MySQL test databases'
110
+ task :drop_databases do
111
+ %x( mysqladmin --user=#{MYSQL_DB_USER} -f drop afk_unittest )
112
+ end
113
+
114
+ desc 'Rebuild the MySQL test databases'
115
+ task :rebuild_databases => [:drop_databases, :build_databases]
116
+ end
117
+
118
+ task :build_mysql_databases => 'mysql:build_databases'
119
+ task :drop_mysql_databases => 'mysql:drop_databases'
120
+ task :rebuild_mysql_databases => 'mysql:rebuild_databases'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.2
1
+ 1.0.5
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{automatic_foreign_key}
8
- s.version = "1.0.2"
8
+ s.version = "1.0.5"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Michał Łomnicki"]
12
- s.date = %q{2010-03-30}
12
+ s.date = %q{2010-04-06}
13
13
  s.description = %q{Automatic Key Migrations is a gem that automatically generates foreign-key
14
14
  constraints when creating tables. It uses SQL-92 syntax and as such should be compatible with most databases that support foreign-key constraints.}
15
15
  s.email = %q{michal.lomnicki@gmail.com}
@@ -32,27 +32,51 @@ constraints when creating tables. It uses SQL-92 syntax and as such should be co
32
32
  "lib/automatic_foreign_key/active_record/connection_adapters/table_definition.rb",
33
33
  "lib/automatic_foreign_key/active_record/migration.rb",
34
34
  "lib/generators/automatic_foreign_key/migration_generator.rb",
35
- "lib/generators/automatic_foreign_key/templates/migration.rb"
35
+ "lib/generators/automatic_foreign_key/templates/migration.rb",
36
+ "spec/aaa_create_tables_spec.rb",
37
+ "spec/connections/mysql/connection.rb",
38
+ "spec/connections/postgresql/connection.rb",
39
+ "spec/migration_spec.rb",
40
+ "spec/models/comment.rb",
41
+ "spec/models/post.rb",
42
+ "spec/models/user.rb",
43
+ "spec/references_spec.rb",
44
+ "spec/schema/schema.rb",
45
+ "spec/spec_helper.rb",
46
+ "spec/support/matchers/automatic_foreign_key_matchers.rb"
36
47
  ]
37
48
  s.homepage = %q{http://github.com/mlomnicki/automatic_foreign_key}
38
49
  s.rdoc_options = ["--charset=UTF-8"]
39
50
  s.require_paths = ["lib"]
40
51
  s.rubygems_version = %q{1.3.6}
41
52
  s.summary = %q{Automatically generate foreign-key constraints when creating tables}
53
+ s.test_files = [
54
+ "spec/schema/schema.rb",
55
+ "spec/connections/postgresql/connection.rb",
56
+ "spec/connections/mysql/connection.rb",
57
+ "spec/aaa_create_tables_spec.rb",
58
+ "spec/support/matchers/automatic_foreign_key_matchers.rb",
59
+ "spec/spec_helper.rb",
60
+ "spec/references_spec.rb",
61
+ "spec/migration_spec.rb",
62
+ "spec/models/user.rb",
63
+ "spec/models/post.rb",
64
+ "spec/models/comment.rb"
65
+ ]
42
66
 
43
67
  if s.respond_to? :specification_version then
44
68
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
45
69
  s.specification_version = 3
46
70
 
47
71
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
48
- s.add_runtime_dependency(%q<redhillonrails_core>, [">= 1.0.2"])
72
+ s.add_runtime_dependency(%q<redhillonrails_core>, [">= 1.0.4.1"])
49
73
  s.add_runtime_dependency(%q<activerecord>, [">= 2.2"])
50
74
  else
51
- s.add_dependency(%q<redhillonrails_core>, [">= 1.0.2"])
75
+ s.add_dependency(%q<redhillonrails_core>, [">= 1.0.4.1"])
52
76
  s.add_dependency(%q<activerecord>, [">= 2.2"])
53
77
  end
54
78
  else
55
- s.add_dependency(%q<redhillonrails_core>, [">= 1.0.2"])
79
+ s.add_dependency(%q<redhillonrails_core>, [">= 1.0.4.1"])
56
80
  s.add_dependency(%q<activerecord>, [">= 2.2"])
57
81
  end
58
82
  end
@@ -1,10 +1,24 @@
1
1
  module AutomaticForeignKey::ActiveRecord
2
2
  module Base
3
- def self.included(base)
3
+ def self.included(base) # :nodoc
4
4
  base.extend(ClassMethods)
5
5
  end
6
6
 
7
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']
8
22
  def references(table_name, column_name, options = {})
9
23
  column_name = column_name.to_s
10
24
  if options.has_key?(:references)
@@ -5,6 +5,20 @@ module AutomaticForeignKey::ActiveRecord
5
5
  end
6
6
 
7
7
  module ClassMethods
8
+ # Overrides standard ActiveRecord add column and adds
9
+ # foreign key if column references other column
10
+ #
11
+ # add_column('comments', 'post_id', :integer)
12
+ # # creates a column and adds foreign key on posts(id)
13
+ #
14
+ # add_column('addresses', 'citizen_id', :integer, :references => :users
15
+ # # creates a column and adds foreign key on users(id)
16
+ #
17
+ # add_column('addresses', 'citizen_id', :integer, :references => [:users, :uuid]
18
+ # # creates a column and adds foreign key on users(uuid)
19
+ #
20
+ # add_column('users', 'verified')
21
+ # # just creates a column as usually
8
22
  def add_column(table_name, column_name, type, options = {})
9
23
  super
10
24
  references = ActiveRecord::Base.references(table_name, column_name, options)
@@ -1,4 +1,5 @@
1
1
  begin
2
+ require 'active_support'
2
3
  require 'redhillonrails_core'
3
4
  rescue
4
5
  gem 'redhillonrails_core'
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
+
4
+ # This is not a test really. It just here to create schema
5
+ # The filename begins with "aaa" to ensure this is executed initially
6
+
7
+ ActiveRecord::Migration.suppress_messages do
8
+ load_schema
9
+ end
@@ -0,0 +1,18 @@
1
+ print "Using MySQL\n"
2
+ require 'logger'
3
+
4
+ ActiveRecord::Base.logger = Logger.new("debug.log")
5
+
6
+ ActiveRecord::Base.configurations = {
7
+ 'afk' => {
8
+ :adapter => 'mysql',
9
+ :database => 'afk_unittest',
10
+ :username => 'afk',
11
+ :encoding => 'utf8',
12
+ :socket => '/var/run/mysqld/mysqld.sock',
13
+ :min_messages => 'warning'
14
+ }
15
+
16
+ }
17
+
18
+ ActiveRecord::Base.establish_connection 'afk'
@@ -0,0 +1,15 @@
1
+ print "Using PostgreSQL\n"
2
+ require 'logger'
3
+
4
+ ActiveRecord::Base.logger = Logger.new("debug.log")
5
+
6
+ ActiveRecord::Base.configurations = {
7
+ 'afk' => {
8
+ :adapter => 'postgresql',
9
+ :database => 'afk_unittest',
10
+ :min_messages => 'warning'
11
+ }
12
+
13
+ }
14
+
15
+ ActiveRecord::Base.establish_connection 'afk'
@@ -0,0 +1,100 @@
1
+ # encoding: utf-8
2
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
+
4
+ require 'models/post'
5
+ require 'models/comment'
6
+
7
+ describe ActiveRecord::Base do
8
+
9
+ it "should respond to references" do
10
+ ActiveRecord::Base.should respond_to :references
11
+ end
12
+
13
+ end
14
+
15
+ describe ActiveRecord::Migration do
16
+
17
+ context "when table is created" do
18
+ it "should create foreign keys" do
19
+ create_table(Post, :user_id => {},
20
+ :author_id => { :references => :users },
21
+ :member_id => { :references => nil } )
22
+ Post.should reference(:users, :id).on(:user_id)
23
+ Post.should reference(:users, :id).on(:author_id)
24
+ Post.should_not reference.on(:member_id)
25
+ end
26
+
27
+ end
28
+
29
+ context "when column is added" do
30
+
31
+ before(:all) do
32
+ @model = Comment
33
+ end
34
+
35
+ it "should create foreign key" do
36
+ add_column(:post_id, :integer) do
37
+ @model.should reference(:posts, :id).on(:post_id)
38
+ end
39
+ end
40
+
41
+ it "should create foreign key to explicity given table" do
42
+ add_column(:author_id, :integer, :references => :users) do
43
+ @model.should reference(:users, :id).on(:author_id)
44
+ end
45
+ end
46
+
47
+ it "should create foreign key to explicity given table and column name" do
48
+ add_column(:author_login, :string, :references => [:users, :login]) do
49
+ @model.should reference(:users, :login).on(:author_login)
50
+ end
51
+ end
52
+
53
+ it "should create foreign key to the same table on parent_id" do
54
+ add_column(:parent_id, :integer) do
55
+ @model.should reference(@model.table_name, :id).on(:parent_id)
56
+ end
57
+ end
58
+
59
+ it "shouldn't create foreign key if column doesn't look like foreign key" do
60
+ add_column(:views_count, :integer) do
61
+ @model.should_not reference.on(:views_count)
62
+ end
63
+ end
64
+
65
+ it "shouldnt't create foreign key if specified explicity" do
66
+ add_column(:post_id, :integer, :references => nil) do
67
+ @model.should_not reference.on(:post_id)
68
+ end
69
+ end
70
+
71
+ def add_column(column_name, *args)
72
+ table = @model.table_name
73
+ ActiveRecord::Migration.suppress_messages do
74
+ ActiveRecord::Migration.add_column(table, column_name, *args)
75
+ @model.reset_column_information
76
+ yield if block_given?
77
+ ActiveRecord::Migration.remove_column(table, column_name)
78
+ end
79
+ end
80
+
81
+ end
82
+
83
+ def foreign_key(model, column)
84
+ columns = Array(column)
85
+ model.foreign_keys.detect { |fk| fk.table_name == model.table_name && fk.column_names == columns }
86
+ end
87
+
88
+ def create_table(model, columns_with_options)
89
+ ActiveRecord::Migration.suppress_messages do
90
+ ActiveRecord::Migration.create_table model.table_name, :force => true do |t|
91
+ columns_with_options.each_pair do |column, options|
92
+ t.integer column, options
93
+ end
94
+ end
95
+ model.reset_column_information
96
+ end
97
+ end
98
+
99
+ end
100
+
@@ -0,0 +1,3 @@
1
+ class Comment < ActiveRecord::Base
2
+ belongs_to :post
3
+ end
@@ -0,0 +1,3 @@
1
+ class Post < ActiveRecord::Base
2
+ has_many :comments
3
+ end
@@ -0,0 +1,2 @@
1
+ class User < ActiveRecord::Base
2
+ end
@@ -0,0 +1,48 @@
1
+ # encoding: utf-8
2
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
+
4
+ describe 'references method' do
5
+
6
+ before(:all) do
7
+ @target = ActiveRecord::Base
8
+ @table_name = 'comments'
9
+ @column_name = 'post_id'
10
+ @destination_table = 'posts'
11
+ @destinantion_column = :id
12
+ end
13
+
14
+ it "should accept table name and column name to references" do
15
+ lambda { @target.references(@table_name, @column_name) }.should_not raise_error
16
+ end
17
+
18
+ it "should return an array" do
19
+ @target.references(@table_name, @column_name).should be_an(Array)
20
+ end
21
+
22
+ it "should split column name to table name and primary key" do
23
+ result = @target.references(@table_name, @column_name)
24
+ result[0].should eql @destination_table
25
+ result[1].should eql @destinantion_column
26
+ end
27
+
28
+ it "should handle parent_id as belonging to the same table" do
29
+ column_name = 'parent_id'
30
+ result = @target.references(@table_name, column_name)
31
+ result[0].should eql @table_name
32
+ result[1].should eql :id
33
+ end
34
+
35
+ it "should accept :references option which overrides default table name" do
36
+ result = @target.references(@table_name, @column_name, :references => 'users')
37
+ result[0].should eql 'users'
38
+ result[1].should eql :id
39
+ end
40
+
41
+ it "should accept :references option which overrides default table name and default column name" do
42
+ result = @target.references(@table_name, @column_name, :references => ['users', 'uuid'])
43
+ result[0].should eql 'users'
44
+ result[1].should eql 'uuid'
45
+ end
46
+
47
+ end
48
+
@@ -0,0 +1,16 @@
1
+ ActiveRecord::Schema.define do
2
+
3
+ create_table :users, :force => true do |t|
4
+ t.string :login
5
+ end
6
+ add_index :users, :login, :unique => true
7
+
8
+ create_table :comments, :force => true do |t|
9
+ t.string :content
10
+ end
11
+
12
+ create_table :posts, :force => true do |t|
13
+ t.string :content
14
+ end
15
+
16
+ end
@@ -0,0 +1,16 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'rubygems'
4
+ require 'automatic_foreign_key'
5
+ require 'spec'
6
+ require 'spec/autorun'
7
+ require 'connection'
8
+ Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
9
+
10
+ Spec::Runner.configure do |config|
11
+ config.include(AutomaticForeignKeyMatchers)
12
+ end
13
+
14
+ def load_schema
15
+ eval(File.read(File.join(File.dirname(__FILE__), 'schema', 'schema.rb')))
16
+ end
@@ -0,0 +1,52 @@
1
+ module AutomaticForeignKeyMatchers
2
+
3
+ class Reference
4
+ def initialize(expected)
5
+ @column_names = nil
6
+ unless expected.empty?
7
+ @references_column_names = Array(expected).collect(&:to_s)
8
+ @references_table_name = @references_column_names.shift
9
+ end
10
+ end
11
+
12
+ def matches?(model)
13
+ @model = model
14
+ if @references_table_name
15
+ @result = @model.foreign_keys.select do |fk|
16
+ fk.references_table_name == @references_table_name &&
17
+ fk.references_column_names == @references_column_names
18
+ end
19
+ else
20
+ @result = @model.foreign_keys
21
+ end
22
+ if @column_names
23
+ @result.any? { |fk| fk.column_names == @column_names }
24
+ else
25
+ !!@result
26
+ end
27
+ end
28
+
29
+ def failure_message_for_should(should_not = false)
30
+ target_column_names = @column_names.present? ? "(#{@column_names.join(', ')})" : ""
31
+ destinantion_column_names = @references_table_name ? "#{@references_table_name}(#{@references_column_names.join(', ')})" : "anything"
32
+ invert = should_not ? 'not' : ''
33
+ "Expected #{@model.table_name}#{target_column_names} #{invert} to reference #{destinantion_column_names}"
34
+ end
35
+
36
+ def failure_message_for_should_not
37
+ failure_message_for_should(true)
38
+ end
39
+
40
+ def on(*column_names)
41
+ @column_names = column_names.collect(&:to_s)
42
+ self
43
+ end
44
+
45
+ end
46
+
47
+ def reference(*expect)
48
+ Reference.new(expect)
49
+ end
50
+
51
+ end
52
+
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 1
7
7
  - 0
8
- - 2
9
- version: 1.0.2
8
+ - 5
9
+ version: 1.0.5
10
10
  platform: ruby
11
11
  authors:
12
12
  - "Micha\xC5\x82 \xC5\x81omnicki"
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-03-30 00:00:00 +02:00
17
+ date: 2010-04-06 00:00:00 +02:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -27,8 +27,9 @@ dependencies:
27
27
  segments:
28
28
  - 1
29
29
  - 0
30
- - 2
31
- version: 1.0.2
30
+ - 4
31
+ - 1
32
+ version: 1.0.4.1
32
33
  type: :runtime
33
34
  version_requirements: *id001
34
35
  - !ruby/object:Gem::Dependency
@@ -71,6 +72,17 @@ files:
71
72
  - lib/automatic_foreign_key/active_record/migration.rb
72
73
  - lib/generators/automatic_foreign_key/migration_generator.rb
73
74
  - lib/generators/automatic_foreign_key/templates/migration.rb
75
+ - spec/aaa_create_tables_spec.rb
76
+ - spec/connections/mysql/connection.rb
77
+ - spec/connections/postgresql/connection.rb
78
+ - spec/migration_spec.rb
79
+ - spec/models/comment.rb
80
+ - spec/models/post.rb
81
+ - spec/models/user.rb
82
+ - spec/references_spec.rb
83
+ - spec/schema/schema.rb
84
+ - spec/spec_helper.rb
85
+ - spec/support/matchers/automatic_foreign_key_matchers.rb
74
86
  has_rdoc: true
75
87
  homepage: http://github.com/mlomnicki/automatic_foreign_key
76
88
  licenses: []
@@ -101,5 +113,15 @@ rubygems_version: 1.3.6
101
113
  signing_key:
102
114
  specification_version: 3
103
115
  summary: Automatically generate foreign-key constraints when creating tables
104
- test_files: []
105
-
116
+ test_files:
117
+ - spec/schema/schema.rb
118
+ - spec/connections/postgresql/connection.rb
119
+ - spec/connections/mysql/connection.rb
120
+ - spec/aaa_create_tables_spec.rb
121
+ - spec/support/matchers/automatic_foreign_key_matchers.rb
122
+ - spec/spec_helper.rb
123
+ - spec/references_spec.rb
124
+ - spec/migration_spec.rb
125
+ - spec/models/user.rb
126
+ - spec/models/post.rb
127
+ - spec/models/comment.rb