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.
- data/.gitignore +2 -0
- data/Gemfile.lock +23 -0
- data/Rakefile +19 -0
- data/ensured_schema.gemspec +4 -0
- data/lib/ensured_schema/column.rb +9 -0
- data/lib/ensured_schema/ensured_table.rb +53 -0
- data/lib/ensured_schema/mysql_column.rb +17 -0
- data/lib/ensured_schema/schema.rb +7 -0
- data/lib/ensured_schema/schema_statements.rb +69 -0
- data/lib/ensured_schema/version.rb +1 -1
- data/lib/ensured_schema.rb +5 -155
- data/test/cases/ensured_schema_test.rb +206 -0
- data/test/cases/helper.rb +70 -0
- data/test/cases/migration_test.rb +1523 -0
- data/test/cases/repair_helper.rb +50 -0
- data/test/config.rb +5 -0
- data/test/connections/native_mysql/connection.rb +25 -0
- data/test/migrations/broken/100_migration_that_raises_exception.rb +10 -0
- data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -0
- data/test/migrations/duplicate/1_people_have_last_names.rb +9 -0
- data/test/migrations/duplicate/2_we_need_reminders.rb +12 -0
- data/test/migrations/duplicate/3_foo.rb +7 -0
- data/test/migrations/duplicate/3_innocent_jointable.rb +12 -0
- data/test/migrations/duplicate_names/20080507052938_chunky.rb +7 -0
- data/test/migrations/duplicate_names/20080507053028_chunky.rb +7 -0
- data/test/migrations/interleaved/pass_1/3_innocent_jointable.rb +12 -0
- data/test/migrations/interleaved/pass_2/1_people_have_last_names.rb +9 -0
- data/test/migrations/interleaved/pass_2/3_innocent_jointable.rb +12 -0
- data/test/migrations/interleaved/pass_3/1_people_have_last_names.rb +9 -0
- data/test/migrations/interleaved/pass_3/2_i_raise_on_down.rb +8 -0
- data/test/migrations/interleaved/pass_3/3_innocent_jointable.rb +12 -0
- data/test/migrations/missing/1000_people_have_middle_names.rb +9 -0
- data/test/migrations/missing/1_people_have_last_names.rb +9 -0
- data/test/migrations/missing/3_we_need_reminders.rb +12 -0
- data/test/migrations/missing/4_innocent_jointable.rb +12 -0
- data/test/migrations/valid/1_people_have_last_names.rb +9 -0
- data/test/migrations/valid/2_we_need_reminders.rb +12 -0
- data/test/migrations/valid/3_innocent_jointable.rb +12 -0
- data/test/models/author.rb +146 -0
- data/test/models/auto_id.rb +4 -0
- data/test/models/binary.rb +2 -0
- data/test/models/bird.rb +3 -0
- data/test/models/book.rb +4 -0
- data/test/models/categorization.rb +5 -0
- data/test/models/category.rb +34 -0
- data/test/models/citation.rb +6 -0
- data/test/models/club.rb +13 -0
- data/test/models/column_name.rb +3 -0
- data/test/models/comment.rb +29 -0
- data/test/models/company.rb +171 -0
- data/test/models/company_in_module.rb +61 -0
- data/test/models/computer.rb +3 -0
- data/test/models/contact.rb +16 -0
- data/test/models/contract.rb +5 -0
- data/test/models/course.rb +3 -0
- data/test/models/customer.rb +73 -0
- data/test/models/default.rb +2 -0
- data/test/models/developer.rb +101 -0
- data/test/models/edge.rb +5 -0
- data/test/models/entrant.rb +3 -0
- data/test/models/essay.rb +3 -0
- data/test/models/event.rb +3 -0
- data/test/models/guid.rb +2 -0
- data/test/models/item.rb +7 -0
- data/test/models/job.rb +5 -0
- data/test/models/joke.rb +3 -0
- data/test/models/keyboard.rb +3 -0
- data/test/models/legacy_thing.rb +3 -0
- data/test/models/matey.rb +4 -0
- data/test/models/member.rb +12 -0
- data/test/models/member_detail.rb +5 -0
- data/test/models/member_type.rb +3 -0
- data/test/models/membership.rb +9 -0
- data/test/models/minimalistic.rb +2 -0
- data/test/models/mixed_case_monkey.rb +3 -0
- data/test/models/movie.rb +5 -0
- data/test/models/order.rb +4 -0
- data/test/models/organization.rb +6 -0
- data/test/models/owner.rb +5 -0
- data/test/models/parrot.rb +16 -0
- data/test/models/person.rb +16 -0
- data/test/models/pet.rb +5 -0
- data/test/models/pirate.rb +70 -0
- data/test/models/post.rb +100 -0
- data/test/models/price_estimate.rb +3 -0
- data/test/models/project.rb +30 -0
- data/test/models/reader.rb +4 -0
- data/test/models/reference.rb +4 -0
- data/test/models/reply.rb +46 -0
- data/test/models/ship.rb +10 -0
- data/test/models/ship_part.rb +5 -0
- data/test/models/sponsor.rb +4 -0
- data/test/models/subject.rb +4 -0
- data/test/models/subscriber.rb +8 -0
- data/test/models/subscription.rb +4 -0
- data/test/models/tag.rb +7 -0
- data/test/models/tagging.rb +10 -0
- data/test/models/task.rb +3 -0
- data/test/models/topic.rb +80 -0
- data/test/models/toy.rb +6 -0
- data/test/models/treasure.rb +8 -0
- data/test/models/vertex.rb +9 -0
- data/test/models/warehouse_thing.rb +5 -0
- data/test/schema/mysql_specific_schema.rb +24 -0
- data/test/schema/postgresql_specific_schema.rb +114 -0
- data/test/schema/schema.rb +493 -0
- data/test/schema/schema2.rb +6 -0
- data/test/schema/sqlite_specific_schema.rb +25 -0
- metadata +237 -7
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
|
data/ensured_schema.gemspec
CHANGED
@@ -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,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,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
|
data/lib/ensured_schema.rb
CHANGED
@@ -1,155 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
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
|