ensured_schema 0.0.1 → 0.1.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.
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