ensured_schema 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. data/.gitignore +2 -0
  2. data/Gemfile.lock +23 -0
  3. data/Rakefile +19 -0
  4. data/ensured_schema.gemspec +4 -0
  5. data/lib/ensured_schema/column.rb +9 -0
  6. data/lib/ensured_schema/ensured_table.rb +53 -0
  7. data/lib/ensured_schema/mysql_column.rb +17 -0
  8. data/lib/ensured_schema/schema.rb +7 -0
  9. data/lib/ensured_schema/schema_statements.rb +69 -0
  10. data/lib/ensured_schema/version.rb +1 -1
  11. data/lib/ensured_schema.rb +5 -155
  12. data/test/cases/ensured_schema_test.rb +206 -0
  13. data/test/cases/helper.rb +70 -0
  14. data/test/cases/migration_test.rb +1523 -0
  15. data/test/cases/repair_helper.rb +50 -0
  16. data/test/config.rb +5 -0
  17. data/test/connections/native_mysql/connection.rb +25 -0
  18. data/test/migrations/broken/100_migration_that_raises_exception.rb +10 -0
  19. data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -0
  20. data/test/migrations/duplicate/1_people_have_last_names.rb +9 -0
  21. data/test/migrations/duplicate/2_we_need_reminders.rb +12 -0
  22. data/test/migrations/duplicate/3_foo.rb +7 -0
  23. data/test/migrations/duplicate/3_innocent_jointable.rb +12 -0
  24. data/test/migrations/duplicate_names/20080507052938_chunky.rb +7 -0
  25. data/test/migrations/duplicate_names/20080507053028_chunky.rb +7 -0
  26. data/test/migrations/interleaved/pass_1/3_innocent_jointable.rb +12 -0
  27. data/test/migrations/interleaved/pass_2/1_people_have_last_names.rb +9 -0
  28. data/test/migrations/interleaved/pass_2/3_innocent_jointable.rb +12 -0
  29. data/test/migrations/interleaved/pass_3/1_people_have_last_names.rb +9 -0
  30. data/test/migrations/interleaved/pass_3/2_i_raise_on_down.rb +8 -0
  31. data/test/migrations/interleaved/pass_3/3_innocent_jointable.rb +12 -0
  32. data/test/migrations/missing/1000_people_have_middle_names.rb +9 -0
  33. data/test/migrations/missing/1_people_have_last_names.rb +9 -0
  34. data/test/migrations/missing/3_we_need_reminders.rb +12 -0
  35. data/test/migrations/missing/4_innocent_jointable.rb +12 -0
  36. data/test/migrations/valid/1_people_have_last_names.rb +9 -0
  37. data/test/migrations/valid/2_we_need_reminders.rb +12 -0
  38. data/test/migrations/valid/3_innocent_jointable.rb +12 -0
  39. data/test/models/author.rb +146 -0
  40. data/test/models/auto_id.rb +4 -0
  41. data/test/models/binary.rb +2 -0
  42. data/test/models/bird.rb +3 -0
  43. data/test/models/book.rb +4 -0
  44. data/test/models/categorization.rb +5 -0
  45. data/test/models/category.rb +34 -0
  46. data/test/models/citation.rb +6 -0
  47. data/test/models/club.rb +13 -0
  48. data/test/models/column_name.rb +3 -0
  49. data/test/models/comment.rb +29 -0
  50. data/test/models/company.rb +171 -0
  51. data/test/models/company_in_module.rb +61 -0
  52. data/test/models/computer.rb +3 -0
  53. data/test/models/contact.rb +16 -0
  54. data/test/models/contract.rb +5 -0
  55. data/test/models/course.rb +3 -0
  56. data/test/models/customer.rb +73 -0
  57. data/test/models/default.rb +2 -0
  58. data/test/models/developer.rb +101 -0
  59. data/test/models/edge.rb +5 -0
  60. data/test/models/entrant.rb +3 -0
  61. data/test/models/essay.rb +3 -0
  62. data/test/models/event.rb +3 -0
  63. data/test/models/guid.rb +2 -0
  64. data/test/models/item.rb +7 -0
  65. data/test/models/job.rb +5 -0
  66. data/test/models/joke.rb +3 -0
  67. data/test/models/keyboard.rb +3 -0
  68. data/test/models/legacy_thing.rb +3 -0
  69. data/test/models/matey.rb +4 -0
  70. data/test/models/member.rb +12 -0
  71. data/test/models/member_detail.rb +5 -0
  72. data/test/models/member_type.rb +3 -0
  73. data/test/models/membership.rb +9 -0
  74. data/test/models/minimalistic.rb +2 -0
  75. data/test/models/mixed_case_monkey.rb +3 -0
  76. data/test/models/movie.rb +5 -0
  77. data/test/models/order.rb +4 -0
  78. data/test/models/organization.rb +6 -0
  79. data/test/models/owner.rb +5 -0
  80. data/test/models/parrot.rb +16 -0
  81. data/test/models/person.rb +16 -0
  82. data/test/models/pet.rb +5 -0
  83. data/test/models/pirate.rb +70 -0
  84. data/test/models/post.rb +100 -0
  85. data/test/models/price_estimate.rb +3 -0
  86. data/test/models/project.rb +30 -0
  87. data/test/models/reader.rb +4 -0
  88. data/test/models/reference.rb +4 -0
  89. data/test/models/reply.rb +46 -0
  90. data/test/models/ship.rb +10 -0
  91. data/test/models/ship_part.rb +5 -0
  92. data/test/models/sponsor.rb +4 -0
  93. data/test/models/subject.rb +4 -0
  94. data/test/models/subscriber.rb +8 -0
  95. data/test/models/subscription.rb +4 -0
  96. data/test/models/tag.rb +7 -0
  97. data/test/models/tagging.rb +10 -0
  98. data/test/models/task.rb +3 -0
  99. data/test/models/topic.rb +80 -0
  100. data/test/models/toy.rb +6 -0
  101. data/test/models/treasure.rb +8 -0
  102. data/test/models/vertex.rb +9 -0
  103. data/test/models/warehouse_thing.rb +5 -0
  104. data/test/schema/mysql_specific_schema.rb +24 -0
  105. data/test/schema/postgresql_specific_schema.rb +114 -0
  106. data/test/schema/schema.rb +493 -0
  107. data/test/schema/schema2.rb +6 -0
  108. data/test/schema/sqlite_specific_schema.rb +25 -0
  109. metadata +237 -7
data/.gitignore CHANGED
@@ -1,3 +1,5 @@
1
1
  pkg/*
2
2
  *.gem
3
3
  .bundle
4
+ debug.log
5
+ .rvmrc
data/Gemfile.lock ADDED
@@ -0,0 +1,23 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ ensured_schema (0.0.1)
5
+ activerecord (~> 2.3.5)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ activerecord (2.3.10)
11
+ activesupport (= 2.3.10)
12
+ activesupport (2.3.10)
13
+ mocha (0.9.10)
14
+ rake
15
+ rake (0.8.7)
16
+
17
+ PLATFORMS
18
+ ruby
19
+
20
+ DEPENDENCIES
21
+ activerecord (~> 2.3.5)
22
+ ensured_schema!
23
+ mocha (~> 0.9.8)
data/Rakefile CHANGED
@@ -1,2 +1,21 @@
1
1
  require 'bundler'
2
2
  Bundler::GemHelper.install_tasks
3
+
4
+ require 'rake/testtask'
5
+ # for adapter in %w( mysql postgresql sqlite sqlite3 firebird db2 oracle sybase openbase frontbase jdbcmysql jdbcpostgresql jdbcsqlite3 jdbcderby jdbch2 jdbchsqldb )
6
+ for adapter in %w( mysql )
7
+ Rake::TestTask.new("test_#{adapter}") { |t|
8
+ if adapter =~ /jdbc/
9
+ t.libs << "test" << "test/connections/jdbc_#{adapter}"
10
+ else
11
+ t.libs << "test" << "test/connections/native_#{adapter}"
12
+ end
13
+ adapter_short = adapter == 'db2' ? adapter : adapter[/^[a-z]+/]
14
+ t.test_files=Dir.glob( "test/cases/**/*_test{,_#{adapter_short}}.rb" ).sort
15
+ t.verbose = true
16
+ }
17
+
18
+ namespace adapter do
19
+ task :test => "test_#{adapter}"
20
+ end
21
+ end
@@ -12,6 +12,10 @@ Gem::Specification.new do |s|
12
12
  s.summary = %q{Ensures database schema always matches your schema.rb file}
13
13
  s.description = %q{Smarter migrations}
14
14
 
15
+ s.add_dependency('activerecord', '~> 2.3.5')
16
+
17
+ s.add_development_dependency('mocha', '~> 0.9.8')
18
+
15
19
  s.rubyforge_project = "ensured_schema"
16
20
 
17
21
  s.files = `git ls-files`.split("\n")
@@ -0,0 +1,9 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ class Column
4
+ def limit_exists?(new_limit)
5
+ self.limit == new_limit
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,53 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ class EnsuredTable < Table
4
+
5
+ def column_exists?(column_name, type = nil, options = {})
6
+ #debugger
7
+ @base.column_exists?(@table_name, column_name, type, options)
8
+ end
9
+
10
+ %w( string text integer float decimal datetime timestamp time date binary boolean ).each do |column_type|
11
+ class_eval <<-EOV
12
+ def #{column_type}(*args) # def string(*args)
13
+ define_columns('#{column_type}', *args) # define_column('string', *args)
14
+ end # end
15
+ EOV
16
+ end
17
+
18
+ def define_columns(column_type, *args)
19
+ options = args.extract_options!
20
+ column_names = args
21
+
22
+ column_names.each do |name|
23
+ column_def = build_column_definition(name, column_type, options)
24
+ def_options = column_def.members.inject({}){|h, k| h[k.to_sym] = column_def[k]; h;}
25
+ #debugger
26
+ if column_exists?(name)
27
+ unless column_exists?(name, column_type, def_options)
28
+ change(name, column_def.sql_type, options)
29
+ puts "#{name} has been changed!"
30
+ end
31
+ else
32
+ puts "creating column"
33
+ @base.add_column(@table_name, name, column_def.sql_type, options)
34
+ end
35
+ end
36
+ end
37
+
38
+ def build_column_definition(column_name, column_type, options = {})
39
+ column = ColumnDefinition.new(@base, column_name, column_type)
40
+ if options[:limit]
41
+ column.limit = options[:limit]
42
+ elsif native[column_type.to_sym].is_a?(Hash)
43
+ column.limit = native[column_type.to_sym][:limit]
44
+ end
45
+ column.precision = options[:precision]
46
+ column.scale = options[:scale]
47
+ column.default = options[:default]
48
+ column.null = options[:null]
49
+ column
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,17 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ class MysqlColumn
4
+ def limit_exists?(new_limit)
5
+ return super unless type.to_s == 'integer'
6
+ case new_limit
7
+ when 5..8
8
+ self.limit == 8
9
+ when nil, 4, 11
10
+ self.limit == 4
11
+ else
12
+ self.limit == new_limit
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,7 @@
1
+ module ActiveRecord
2
+ class Schema
3
+ def self.ensure(options={}, &block)
4
+ self.define(options, &block)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,69 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module SchemaStatements
4
+ # Checks to see if an index exists on a table for a given index definition
5
+ #
6
+ # === Examples
7
+ # # Check an index exists
8
+ # index_exists?(:suppliers, :company_id)
9
+ #
10
+ # # Check an index on multiple columns exists
11
+ # index_exists?(:suppliers, [:company_id, :company_type])
12
+ #
13
+ # # Check a unique index exists
14
+ # index_exists?(:suppliers, :company_id, :unique => true)
15
+ #
16
+ # # Check an index with a custom name exists
17
+ # index_exists?(:suppliers, :company_id, :name => "idx_company_id"
18
+ def new_index_exists?(table_name, column_name, options = {}) # Don't overwrite existing index_exists?
19
+ column_names = Array.wrap(column_name)
20
+ index_name = options.key?(:name) ? options[:name].to_s : index_name(table_name, :column => column_names)
21
+ if options[:unique]
22
+ indexes(table_name).any?{ |i| i.unique && i.name == index_name }
23
+ else
24
+ indexes(table_name).any?{ |i| i.name == index_name }
25
+ end
26
+ end
27
+
28
+ # Checks to see if a column exists in a given table.
29
+ #
30
+ # === Examples
31
+ # # Check a column exists
32
+ # column_exists?(:suppliers, :name)
33
+ #
34
+ # # Check a column exists of a particular type
35
+ # column_exists?(:suppliers, :name, :string)
36
+ #
37
+ # # Check a column exists with a specific definition
38
+ # column_exists?(:suppliers, :name, :string, :limit => 100)
39
+ def column_exists?(table_name, column_name, type = nil, options = {})
40
+ #debugger
41
+ columns(table_name).any?{ |c| c.name == column_name.to_s &&
42
+ (!type || c.type.to_s == type.to_s) &&
43
+ (!options[:limit] || c.limit_exists?(options[:limit])) &&
44
+ (!options[:precision] || c.precision == options[:precision]) &&
45
+ (!options[:scale] || c.scale == options[:scale]) }
46
+ end
47
+
48
+ def table(table_name, options = {}, &block)
49
+ if table_exists?(table_name)
50
+ puts "table already exists"
51
+ ensure_table(table_name, &block) # what to do about changing table options
52
+ else
53
+ puts "creating table"
54
+ create_table(table_name, options, &block)
55
+ end
56
+ end
57
+
58
+ def ensure_table(table_name)
59
+ yield EnsuredTable.new(table_name, self)
60
+ end
61
+
62
+ def ensure_index(table_name, column_name, options = {})
63
+ unless new_index_exists?(table_name, column_name, options)
64
+ add_index(table_name, column_name, options)
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -1,3 +1,3 @@
1
1
  module EnsuredSchema
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -1,155 +1,5 @@
1
- module ActiveRecord
2
- module ConnectionAdapters
3
- class AbstractAdapter
4
- def table_exists?(table_name)
5
- tables.map(&:downcase).include?(table_name.to_s.downcase)
6
- end
7
- end
8
-
9
- module SchemaStatements
10
- # Checks to see if a column exists in a given table.
11
- #
12
- # === Examples
13
- # # Check a column exists
14
- # column_exists?(:suppliers, :name)
15
- #
16
- # # Check a column exists of a particular type
17
- # column_exists?(:suppliers, :name, :string)
18
- #
19
- # # Check a column exists with a specific definition
20
- # column_exists?(:suppliers, :name, :string, :limit => 100)
21
- def column_exists?(table_name, column_name, type = nil, options = {})
22
- #debugger
23
- columns(table_name).any?{ |c| c.name == column_name.to_s &&
24
- (!type || c.type.to_s == type.to_s) &&
25
- (!options[:limit] || c.limit_exists?(options[:limit])) &&
26
- (!options[:precision] || c.precision == options[:precision]) &&
27
- (!options[:scale] || c.scale == options[:scale]) }
28
- end
29
- end
30
- end
31
- end
32
-
33
- module ActiveRecord
34
- module ConnectionAdapters
35
- class Column
36
- def limit_exists?(new_limit)
37
- self.limit == new_limit
38
- end
39
- end
40
- end
41
- end
42
-
43
- module ActiveRecord
44
- module ConnectionAdapters
45
- class MysqlColumn
46
- def limit_exists?(new_limit)
47
- return super unless type.to_s == 'integer'
48
- case new_limit
49
- when 5..8
50
- self.limit == 8
51
- when nil, 4, 11
52
- self.limit == 4
53
- else
54
- self.limit == new_limit
55
- end
56
- end
57
- end
58
- end
59
- end
60
-
61
-
62
- module ActiveRecord
63
- module ConnectionAdapters
64
- class EnsuredTable < Table
65
-
66
- def column_exists?(column_name, type = nil, options = {})
67
- #debugger
68
- @base.column_exists?(@table_name, column_name, type, options)
69
- end
70
-
71
- %w( string text integer float decimal datetime timestamp time date binary boolean ).each do |column_type|
72
- class_eval <<-EOV
73
- def #{column_type}(*args) # def string(*args)
74
- define_columns('#{column_type}', *args) # define_column('string', *args)
75
- end # end
76
- EOV
77
- end
78
-
79
- def define_columns(column_type, *args)
80
- options = args.extract_options!
81
- column_names = args
82
-
83
- column_names.each do |name|
84
- column_def = build_column_definition(name, column_type, options)
85
- def_options = column_def.members.inject({}){|h, k| h[k.to_sym] = column_def[k]; h;}
86
- #debugger
87
- if column_exists?(name)
88
- unless column_exists?(name, column_type, def_options)
89
- debugger
90
- change(name, column_def.sql_type, options)
91
- puts "#{name} has been changed!"
92
- end
93
- else
94
- puts "creating column"
95
- @base.add_column(@table_name, name, column_def.sql_type, options)
96
- end
97
- end
98
- end
99
-
100
- def build_column_definition(column_name, column_type, options = {})
101
- column = ColumnDefinition.new(@base, column_name, column_type)
102
- if options[:limit]
103
- column.limit = options[:limit]
104
- elsif native[column_type.to_sym].is_a?(Hash)
105
- column.limit = native[column_type.to_sym][:limit]
106
- end
107
- column.precision = options[:precision]
108
- column.scale = options[:scale]
109
- column.default = options[:default]
110
- column.null = options[:null]
111
- column
112
- end
113
- end
114
- end
115
- end
116
-
117
- module ActiveRecord
118
- class Schema
119
- def self.ensure(options={}, &block)
120
- self.define(options, &block)
121
- end
122
- end
123
- end
124
-
125
- module ActiveRecord
126
- module ConnectionAdapters # :nodoc:
127
- module SchemaStatements
128
- def table(table_name, options = {}, &block)
129
- if table_exists?(table_name)
130
- puts "table already exists"
131
- ensure_table(table_name, &block) # what to do about changing table options
132
- else
133
- puts "creating table"
134
- create_table(table_name, options, &block)
135
- end
136
- end
137
-
138
- def ensure_table(table_name)
139
- yield EnsuredTable.new(table_name, self)
140
- end
141
-
142
- def ensure_index(table_name, column_name, options = {})
143
- begin
144
- add_index(table_name, column_name, options)
145
- rescue => e
146
- if e.message =~ /Duplicate key/
147
- puts "index already exists"
148
- else
149
- raise e
150
- end
151
- end
152
- end
153
- end
154
- end
155
- end
1
+ require 'ensured_schema/column'
2
+ require 'ensured_schema/mysql_column'
3
+ require 'ensured_schema/schema_statements'
4
+ require 'ensured_schema/ensured_table'
5
+ require 'ensured_schema/schema'
@@ -0,0 +1,206 @@
1
+ require "cases/helper"
2
+
3
+ require 'models/person'
4
+
5
+ if ActiveRecord::Base.connection.supports_migrations?
6
+ class ActiveRecord::Migration
7
+ class <<self
8
+ attr_accessor :message_count
9
+ def puts(text="")
10
+ self.message_count ||= 0
11
+ self.message_count += 1
12
+ end
13
+ end
14
+ end
15
+
16
+ class EnsuredSchemaTest < ActiveRecord::TestCase
17
+ def setup
18
+ @conn = ActiveRecord::Base.connection
19
+ @conn.drop_table("testings") if @conn.table_exists?("testings")
20
+ @conn.drop_table("testings") if @conn.table_exists?("testings")
21
+ end
22
+
23
+ def testings_definition
24
+ assert_nothing_raised do
25
+ ActiveRecord::Schema.ensure(:version => '1') do
26
+ table(:testings, :id => false, :force => true) do |t|
27
+ t.string :test, :limit => 30, :default => "", :null => false
28
+ end
29
+ end
30
+
31
+ ActiveRecord::Schema.ensure(:version => '1') do
32
+ table(:testings, :id => false, :force => true) do |t|
33
+ t.string :test, :limit => 30, :default => "", :null => false
34
+ end
35
+ end
36
+ end
37
+ assert @conn.table_exists?("testings")
38
+ end
39
+
40
+ def test_column_definition_does_not_raise
41
+ assert_nothing_raised do
42
+ ActiveRecord::Schema.ensure(:version => '1') do
43
+ table(:testings, :id => false, :force => true) do |t|
44
+ t.string :test, :limit => 30, :default => "", :null => false
45
+ end
46
+ table(:testings, :id => false, :force => true) do |t|
47
+ t.expects(:change).never
48
+ t.string :test, :limit => 30, :default => "", :null => false
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ # From original column_exists? patch in Rails 3: https://rails.lighthouseapp.com/projects/8994/tickets/4219
55
+ def test_column_exists
56
+ Person.connection.create_table :testings do |t|
57
+ t.column :foo, :string
58
+ end
59
+
60
+ assert Person.connection.column_exists?(:testings, :foo)
61
+ assert !Person.connection.column_exists?(:testings, :bar)
62
+ ensure
63
+ Person.connection.drop_table :testings rescue nil
64
+ end
65
+
66
+ # From original column_exists? patch in Rails 3: https://rails.lighthouseapp.com/projects/8994/tickets/4219
67
+ def test_column_exists_with_type
68
+ Person.connection.create_table :testings do |t|
69
+ t.column :foo, :string
70
+ t.column :bar, :decimal, :precision => 8, :scale => 2
71
+ end
72
+
73
+ assert Person.connection.column_exists?(:testings, :foo, :string)
74
+ assert !Person.connection.column_exists?(:testings, :foo, :integer)
75
+ assert Person.connection.column_exists?(:testings, :bar, :decimal)
76
+ assert !Person.connection.column_exists?(:testings, :bar, :integer)
77
+ ensure
78
+ Person.connection.drop_table :testings rescue nil
79
+ end
80
+
81
+ # From original column_exists? patch in Rails 3: https://rails.lighthouseapp.com/projects/8994/tickets/4219
82
+ def test_column_exists_with_definition
83
+ Person.connection.create_table :testings do |t|
84
+ t.column :foo, :string, :limit => 100
85
+ t.column :bar, :decimal, :precision => 8, :scale => 2
86
+ end
87
+
88
+ assert Person.connection.column_exists?(:testings, :foo, :string, :limit => 100)
89
+ assert !Person.connection.column_exists?(:testings, :foo, :string, :limit => 50)
90
+ assert Person.connection.column_exists?(:testings, :bar, :decimal, :precision => 8, :scale => 2)
91
+ assert !Person.connection.column_exists?(:testings, :bar, :decimal, :precision => 10, :scale => 2)
92
+ ensure
93
+ Person.connection.drop_table :testings rescue nil
94
+ end
95
+
96
+ # From original column_exists? patch in Rails 3: https://rails.lighthouseapp.com/projects/8994/tickets/4219
97
+ def test_new_index_exists?
98
+ Person.connection.create_table :testings do |t|
99
+ t.column :foo, :string, :limit => 100
100
+ t.column :bar, :string, :limit => 100
101
+ end
102
+ Person.connection.add_index :testings, :foo
103
+
104
+ assert Person.connection.new_index_exists?(:testings, :foo)
105
+ assert !Person.connection.new_index_exists?(:testings, :bar)
106
+ ensure
107
+ Person.connection.drop_table :testings rescue nil
108
+ end
109
+
110
+ # From original column_exists? patch in Rails 3: https://rails.lighthouseapp.com/projects/8994/tickets/4219
111
+ def test_new_index_exists?_on_multiple_columns
112
+ Person.connection.create_table :testings do |t|
113
+ t.column :foo, :string, :limit => 100
114
+ t.column :bar, :string, :limit => 100
115
+ end
116
+ Person.connection.add_index :testings, [:foo, :bar]
117
+
118
+ assert Person.connection.new_index_exists?(:testings, [:foo, :bar])
119
+ ensure
120
+ Person.connection.drop_table :testings rescue nil
121
+ end
122
+
123
+ # From original column_exists? patch in Rails 3: https://rails.lighthouseapp.com/projects/8994/tickets/4219
124
+ def test_unique_new_index_exists?
125
+ Person.connection.create_table :testings do |t|
126
+ t.column :foo, :string, :limit => 100
127
+ end
128
+ Person.connection.add_index :testings, :foo, :unique => true
129
+
130
+ assert Person.connection.new_index_exists?(:testings, :foo, :unique => true)
131
+ ensure
132
+ Person.connection.drop_table :testings rescue nil
133
+ end
134
+
135
+ # From original column_exists? patch in Rails 3: https://rails.lighthouseapp.com/projects/8994/tickets/4219
136
+ def test_named_new_index_exists?
137
+ Person.connection.create_table :testings do |t|
138
+ t.column :foo, :string, :limit => 100
139
+ end
140
+ Person.connection.add_index :testings, :foo, :name => "custom_index_name"
141
+
142
+ assert Person.connection.new_index_exists?(:testings, :foo, :name => "custom_index_name")
143
+ ensure
144
+ Person.connection.drop_table :testings rescue nil
145
+ end
146
+
147
+ def test_column_exists_with_integer_limit
148
+ @conn.create_table :testings do |t|
149
+ t.column :one, :integer, :limit => 1
150
+ t.column :two, :integer, :limit => 2
151
+ t.column :three, :integer, :limit => 3
152
+ t.column :four, :integer, :limit => 4
153
+ t.column :five, :integer, :limit => 5
154
+ t.column :six, :integer, :limit => 6
155
+ t.column :seven, :integer, :limit => 7
156
+ t.column :eight, :integer, :limit => 8
157
+ t.column :eleven, :integer, :limit => 11
158
+ end
159
+
160
+ assert @conn.column_exists?(:testings, :one, :integer, :limit => 1)
161
+ assert @conn.column_exists?(:testings, :two, :integer, :limit => 2)
162
+ assert @conn.column_exists?(:testings, :three, :integer, :limit => 3)
163
+ assert @conn.column_exists?(:testings, :four, :integer, :limit => 4)
164
+ assert @conn.column_exists?(:testings, :five, :integer, :limit => 5)
165
+ assert @conn.column_exists?(:testings, :six, :integer, :limit => 6)
166
+ assert @conn.column_exists?(:testings, :seven, :integer, :limit => 7)
167
+ assert @conn.column_exists?(:testings, :eight, :integer, :limit => 8)
168
+ assert @conn.column_exists?(:testings, :eleven, :integer, :limit => 11)
169
+ end
170
+
171
+ def test_column_gets_changed
172
+ ActiveRecord::Schema.ensure(:version => '1') do
173
+ table(:testings, :id => false, :force => true) do |t|
174
+ t.string :test, :limit => 30, :default => "", :null => false
175
+ end
176
+ table(:testings, :id => false, :force => true) do |t|
177
+ t.string :test, :limit => 20, :default => "", :null => false
178
+ end
179
+ end
180
+
181
+ assert !@conn.column_exists?(:testings, :test, :string, :limit => 30)
182
+ assert @conn.column_exists?(:testings, :test, :string, :limit => 20, :default => "", :null => false)
183
+ assert @conn.column_exists?(:testings, :test)
184
+ end
185
+
186
+ def test_ensure_index
187
+ assert_nothing_raised do
188
+ ActiveRecord::Schema.ensure(:version => '1') do
189
+ table(:testings, :id => false, :force => true) do |t|
190
+ t.string :test, :limit => 30, :default => "", :null => false
191
+ end
192
+ ensure_index :testings, [:test], :name => "test_index", :unique => true
193
+ ensure_index :testings, [:test], :name => "test_index", :unique => true
194
+ end
195
+ end
196
+ assert @conn.new_index_exists?(:testings, :test, :name => "test_index")
197
+ end
198
+
199
+ protected
200
+ def with_change_table
201
+ Person.connection.change_table :delete_me do |t|
202
+ yield t
203
+ end
204
+ end
205
+ end
206
+ end
@@ -0,0 +1,70 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/../../lib')
2
+ $:.unshift(File.dirname(__FILE__) + '/../../../activesupport/lib')
3
+
4
+ require 'config'
5
+
6
+ require 'rubygems'
7
+ require 'test/unit'
8
+ require 'stringio'
9
+
10
+ require 'active_record'
11
+ require 'active_record/test_case'
12
+ require 'active_record/fixtures'
13
+ require 'connection'
14
+
15
+ require 'cases/repair_helper'
16
+
17
+ require 'ensured_schema'
18
+
19
+ # Show backtraces for deprecated behavior for quicker cleanup.
20
+ ActiveSupport::Deprecation.debug = true
21
+
22
+ # Quote "type" if it's a reserved word for the current connection.
23
+ QUOTED_TYPE = ActiveRecord::Base.connection.quote_column_name('type')
24
+
25
+ def current_adapter?(*types)
26
+ types.any? do |type|
27
+ ActiveRecord::ConnectionAdapters.const_defined?(type) &&
28
+ ActiveRecord::Base.connection.is_a?(ActiveRecord::ConnectionAdapters.const_get(type))
29
+ end
30
+ end
31
+
32
+ ActiveRecord::Base.connection.class.class_eval do
33
+ IGNORED_SQL = [/^PRAGMA/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SAVEPOINT/, /^ROLLBACK TO SAVEPOINT/, /^RELEASE SAVEPOINT/, /SHOW FIELDS/]
34
+
35
+ def execute_with_query_record(sql, name = nil, &block)
36
+ $queries_executed ||= []
37
+ $queries_executed << sql unless IGNORED_SQL.any? { |r| sql =~ r }
38
+ execute_without_query_record(sql, name, &block)
39
+ end
40
+
41
+ alias_method_chain :execute, :query_record
42
+ end
43
+
44
+ # Make with_scope public for tests
45
+ class << ActiveRecord::Base
46
+ public :with_scope, :with_exclusive_scope
47
+ end
48
+
49
+ unless ENV['FIXTURE_DEBUG']
50
+ module ActiveRecord::TestFixtures::ClassMethods
51
+ def try_to_load_dependency_with_silence(*args)
52
+ ActiveRecord::Base.logger.silence { try_to_load_dependency_without_silence(*args)}
53
+ end
54
+
55
+ alias_method_chain :try_to_load_dependency, :silence
56
+ end
57
+ end
58
+
59
+ class ActiveSupport::TestCase
60
+ include ActiveRecord::TestFixtures
61
+ include ActiveRecord::Testing::RepairHelper
62
+
63
+ self.fixture_path = FIXTURES_ROOT
64
+ self.use_instantiated_fixtures = false
65
+ self.use_transactional_fixtures = true
66
+
67
+ def create_fixtures(*table_names, &block)
68
+ Fixtures.create_fixtures(ActiveSupport::TestCase.fixture_path, table_names, {}, &block)
69
+ end
70
+ end