schema_plus 1.1.2 → 1.2.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.
- checksums.yaml +7 -0
- data/.rspec +0 -1
- data/.travis.yml +12 -1
- data/README.md +27 -10
- data/gemfiles/rails-4.0/Gemfile.base +4 -0
- data/gemfiles/rails-4.0/Gemfile.mysql2 +4 -0
- data/gemfiles/rails-4.0/Gemfile.postgresql +4 -0
- data/gemfiles/rails-4.0/Gemfile.sqlite3 +4 -0
- data/gemfiles/rails-edge/Gemfile.base +4 -0
- data/gemfiles/rails-edge/Gemfile.mysql2 +4 -0
- data/gemfiles/rails-edge/Gemfile.postgresql +4 -0
- data/gemfiles/rails-edge/Gemfile.sqlite3 +4 -0
- data/lib/schema_plus/active_record/connection_adapters/abstract_adapter.rb +22 -1
- data/lib/schema_plus/active_record/connection_adapters/mysql_adapter.rb +6 -0
- data/lib/schema_plus/active_record/connection_adapters/postgresql_adapter.rb +17 -4
- data/lib/schema_plus/active_record/connection_adapters/schema_statements.rb +41 -26
- data/lib/schema_plus/active_record/connection_adapters/sqlite3_adapter.rb +10 -5
- data/lib/schema_plus/active_record/connection_adapters/table_definition.rb +29 -10
- data/lib/schema_plus/version.rb +1 -1
- data/lib/schema_plus.rb +4 -0
- data/runspecs +14 -3
- data/spec/foreign_key_spec.rb +22 -0
- data/spec/schema_dumper_spec.rb +33 -7
- data/spec/spec_helper.rb +6 -6
- metadata +28 -35
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 57e14aaa2266c620a64f9807c8eda09e72d7f87a
|
4
|
+
data.tar.gz: a2a284774dd0bd02b0ff0c21421a79278e93813b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 51859b083b8f9e245733efad553563b7dd53d569705f70b8fe371c95987b90775b6efde32f033dea70232d629345c6128e5aaf1d5f7b8b1494036286f3c12f4e
|
7
|
+
data.tar.gz: 9818a2241a8d90f4c5898af00ddb37a34c33011518b70c771533fec90ef63d9d8042ce9ab8850bfd59db45658813f1d118ac4f529396c40336c3be90ead10813
|
data/.rspec
CHANGED
data/.travis.yml
CHANGED
@@ -1,11 +1,17 @@
|
|
1
1
|
rvm:
|
2
|
-
- 1.9.2
|
3
2
|
- 1.9.3
|
3
|
+
- 2.0.0
|
4
4
|
gemfile:
|
5
5
|
- gemfiles/rails-3.2/Gemfile.postgresql
|
6
6
|
- gemfiles/rails-3.2/Gemfile.sqlite3
|
7
7
|
- gemfiles/rails-3.2/Gemfile.mysql
|
8
8
|
- gemfiles/rails-3.2/Gemfile.mysql2
|
9
|
+
- gemfiles/rails-4.0/Gemfile.postgresql
|
10
|
+
- gemfiles/rails-4.0/Gemfile.sqlite3
|
11
|
+
- gemfiles/rails-4.0/Gemfile.mysql2
|
12
|
+
- gemfiles/rails-edge/Gemfile.postgresql
|
13
|
+
- gemfiles/rails-edge/Gemfile.sqlite3
|
14
|
+
- gemfiles/rails-edge/Gemfile.mysql2
|
9
15
|
before_script:
|
10
16
|
- rake create_databases
|
11
17
|
after_script:
|
@@ -15,3 +21,8 @@ notifications:
|
|
15
21
|
recipients:
|
16
22
|
- michal.lomnicki@gmail.com
|
17
23
|
- ronen@barzel.org
|
24
|
+
matrix:
|
25
|
+
allow_failures:
|
26
|
+
- gemfile: gemfiles/rails-edge/Gemfile.postgresql
|
27
|
+
- gemfile: gemfiles/rails-edge/Gemfile.sqlite3
|
28
|
+
- gemfile: gemfiles/rails-edge/Gemfile.mysql2
|
data/README.md
CHANGED
@@ -9,19 +9,23 @@ For added rails DRYness see also the gems
|
|
9
9
|
[schema_associations](http://rubygems.org/gems/schema_associations) and
|
10
10
|
[schema_validations](http://rubygems.org/gems/schema_validations)
|
11
11
|
|
12
|
-
[
|
12
|
+
[](http://badge.fury.io/rb/schema_plus)
|
13
|
+
[](http://travis-ci.org/lomba/schema_plus)
|
14
|
+
[](https://gemnasium.com/lomba/schema_plus)
|
13
15
|
|
14
16
|
## Compatibility
|
15
17
|
|
16
18
|
SchemaPlus supports all combinations of:
|
17
|
-
* rails 3.2 (up through 3.2.12)
|
18
|
-
* PostgreSQL, MySQL (using mysql or mysql2 gem), or SQLite3 (using sqlite3
|
19
|
-
3.7.7 which has foreign key support)
|
20
|
-
* MRI ruby 1.9.2 or 1.9.3
|
21
19
|
|
20
|
+
* Rails 3.2 or Rails 4
|
21
|
+
* PostgreSQL, MySQL (using mysql2 gem; mysql gem only supported with Rails
|
22
|
+
3.2), or SQLite3 (using sqlite3 >= 3.7.7 which has foreign key support)
|
23
|
+
* MRI Ruby 1.9.3 or 2.0.0
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
+
|
26
|
+
Note: As of version 1.0.0, SchemaPlus no longer supports Rails 2.3, 3.0 and
|
27
|
+
3.1, and also no longer supports MRI Ruby 1.8.7; the last version
|
28
|
+
to support them was 0.4.1. As of version 1.2.0, SchemaPlus no longer supports MRI Ruby 1.9.2
|
25
29
|
|
26
30
|
## Installation
|
27
31
|
|
@@ -40,8 +44,8 @@ Here some examples that show off the high points. For full details see the
|
|
40
44
|
|
41
45
|
### Indexes
|
42
46
|
|
43
|
-
With standard
|
44
|
-
definition:
|
47
|
+
With standard Rails 3 migrations, you specify indexes separately from the
|
48
|
+
table definition:
|
45
49
|
|
46
50
|
# Standard Rails approach...
|
47
51
|
create_table :parts do |t|
|
@@ -87,7 +91,7 @@ which is equivalent to
|
|
87
91
|
|
88
92
|
t.string :product_code, index: { unique: true }
|
89
93
|
|
90
|
-
If you're using
|
94
|
+
If you're using PostgreSQL, SchemaPlus provides support for conditions,
|
91
95
|
expressions, index methods, and case-insensitive indexes:
|
92
96
|
|
93
97
|
t.string :last_name, index: { conditions: 'deleted_at IS NULL' }
|
@@ -168,6 +172,15 @@ list of foreign key constraints defined for a given table, and
|
|
168
172
|
that reference a given table. See
|
169
173
|
SchemaPlus::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.
|
170
174
|
|
175
|
+
#### Foreign Key Issues
|
176
|
+
|
177
|
+
Foreign keys can cause issues for Rails utilities that delete or load data
|
178
|
+
because referential integrity imposes a sequencing requirement that those
|
179
|
+
utilities may not take into consideration. Monkey-patching may be required
|
180
|
+
to address some of these issues. The Wiki article [Making yaml_db work with
|
181
|
+
foreign key constraints in PostgreSQL](https://github.com/lomba/schema_plus/wiki/Making-yaml_db-work-with-foreign-key-constraints-in-PostgreSQL)
|
182
|
+
has some information that may be of assistance in resolving these issues.
|
183
|
+
|
171
184
|
### Tables
|
172
185
|
|
173
186
|
SchemaPlus extends rails' `drop_table` method to accept these options:
|
@@ -277,6 +290,10 @@ of foreign key constraints, you can re-enable it:
|
|
277
290
|
|
278
291
|
## Release notes:
|
279
292
|
|
293
|
+
### 1.2.0
|
294
|
+
* Now works with rails 4, due to efforts of [@tovodeverett](https://github.com/tovodeverett)
|
295
|
+
* Test against MRI ruby 2.0.0, no longer test against 1.9.2
|
296
|
+
|
280
297
|
### 1.1.2
|
281
298
|
* Now works with rails 3.2.13 (fixed railtie initialization)
|
282
299
|
|
@@ -31,7 +31,6 @@ module SchemaPlus
|
|
31
31
|
# for this.
|
32
32
|
adapter_module = SchemaPlus::ActiveRecord::ConnectionAdapters.const_get(adapter)
|
33
33
|
self.class.send(:include, adapter_module) unless self.class.include?(adapter_module)
|
34
|
-
self.post_initialize if self.respond_to? :post_initialize
|
35
34
|
extend(SchemaPlus::ActiveRecord::ForeignKeys)
|
36
35
|
end
|
37
36
|
|
@@ -171,6 +170,28 @@ module SchemaPlus
|
|
171
170
|
# return a DATETIME object for the current time.
|
172
171
|
def sql_for_function(function_name) raise "Internal Error: Connection adapter didn't override abstract function"; end
|
173
172
|
|
173
|
+
|
174
|
+
if ::ActiveRecord::VERSION::MAJOR.to_i >= 4
|
175
|
+
module SchemaCreation
|
176
|
+
def self.included(base) #:nodoc:
|
177
|
+
base.alias_method_chain :visit_TableDefinition, :schema_plus
|
178
|
+
end
|
179
|
+
|
180
|
+
def visit_TableDefinition_with_schema_plus(o) #:nodoc:
|
181
|
+
create_sql = visit_TableDefinition_without_schema_plus(o)
|
182
|
+
last_chunk = ") #{o.options}"
|
183
|
+
|
184
|
+
unless create_sql.end_with?(last_chunk)
|
185
|
+
raise "Internal Error: Can't find '#{last_chunk}' at end of '#{create_sql}' - Rails internals have changed!"
|
186
|
+
end
|
187
|
+
|
188
|
+
unless o.foreign_keys.empty?
|
189
|
+
create_sql[create_sql.size - last_chunk.size, 0] = ', ' + o.foreign_keys.map(&:to_sql) * ', '
|
190
|
+
end
|
191
|
+
create_sql
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
174
195
|
end
|
175
196
|
end
|
176
197
|
end
|
@@ -15,6 +15,12 @@ module SchemaPlus
|
|
15
15
|
alias_method_chain :rename_table, :schema_plus
|
16
16
|
alias_method_chain :exec_stmt, :schema_plus rescue nil # only defined for mysql not mysql2
|
17
17
|
end
|
18
|
+
|
19
|
+
if ::ActiveRecord::VERSION::MAJOR.to_i >= 4
|
20
|
+
base.class_eval do
|
21
|
+
include ::ActiveRecord::ConnectionAdapters::SchemaStatements::AddIndex
|
22
|
+
end
|
23
|
+
end
|
18
24
|
end
|
19
25
|
|
20
26
|
def tables_with_schema_plus(name=nil, *args)
|
@@ -49,7 +49,9 @@ module SchemaPlus
|
|
49
49
|
|
50
50
|
def self.included(base) #:nodoc:
|
51
51
|
base.class_eval do
|
52
|
-
|
52
|
+
if ::ActiveRecord::VERSION::MAJOR.to_i < 4
|
53
|
+
remove_method :indexes
|
54
|
+
end
|
53
55
|
alias_method_chain :rename_table, :schema_plus
|
54
56
|
alias_method_chain :exec_cache, :schema_plus
|
55
57
|
end
|
@@ -95,7 +97,15 @@ module SchemaPlus
|
|
95
97
|
option_strings = Hash[column_names.map {|name| [name, '']}]
|
96
98
|
option_strings = add_index_sort_order(option_strings, column_names, options)
|
97
99
|
|
98
|
-
|
100
|
+
if options[:case_sensitive] == false
|
101
|
+
caseable_columns = columns(table_name).select { |col| [:string, :text].include?(col.type) }.map(&:name)
|
102
|
+
quoted_column_names = column_names.map do |col_name|
|
103
|
+
(caseable_columns.include?(col_name.to_s) ? "LOWER(#{quote_column_name(col_name)})" : quote_column_name(col_name)) + option_strings[col_name]
|
104
|
+
end
|
105
|
+
else
|
106
|
+
quoted_column_names = column_names.map { |col_name| quote_column_name(col_name) + option_strings[col_name] }
|
107
|
+
end
|
108
|
+
|
99
109
|
expression = "(#{quoted_column_names.join(', ')})"
|
100
110
|
expression = "USING #{kind} #{expression}" if kind
|
101
111
|
|
@@ -150,8 +160,11 @@ module SchemaPlus
|
|
150
160
|
# case-insensitive index
|
151
161
|
if expression
|
152
162
|
rexp_lower = %r{\blower\(\(?([^)]+)(\)::text)?\)}
|
153
|
-
if expression.match
|
154
|
-
|
163
|
+
if expression.match /\A#{rexp_lower}(?:, #{rexp_lower})*\z/
|
164
|
+
case_insensitive_columns = expression.scan(rexp_lower).map(&:first)
|
165
|
+
column_names = index_keys.map do |index_key|
|
166
|
+
index_key == '0' ? case_insensitive_columns.shift : columns[index_key]
|
167
|
+
end
|
155
168
|
case_sensitive = false
|
156
169
|
end
|
157
170
|
end
|
@@ -4,7 +4,7 @@ module SchemaPlus::ActiveRecord::ConnectionAdapters
|
|
4
4
|
def self.included(base) #:nodoc:
|
5
5
|
base.class_eval do
|
6
6
|
alias_method_chain :create_table, :schema_plus
|
7
|
-
|
7
|
+
include AddIndex
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
@@ -25,38 +25,26 @@ module SchemaPlus::ActiveRecord::ConnectionAdapters
|
|
25
25
|
# override rails' :force to cascade
|
26
26
|
drop_table(table, if_exists: true, cascade: true) if options.delete(:force)
|
27
27
|
|
28
|
-
|
28
|
+
if ::ActiveRecord::VERSION::MAJOR.to_i < 4
|
29
|
+
indexes = []
|
30
|
+
end
|
29
31
|
create_table_without_schema_plus(table, options) do |table_definition|
|
30
32
|
table_definition.schema_plus_config = SchemaPlus.config.merge(config_options)
|
31
|
-
|
33
|
+
if ::ActiveRecord::VERSION::MAJOR.to_i < 4
|
34
|
+
table_definition.name = table
|
35
|
+
end
|
32
36
|
yield table_definition if block_given?
|
33
|
-
|
37
|
+
if ::ActiveRecord::VERSION::MAJOR.to_i < 4
|
38
|
+
indexes = table_definition.indexes
|
39
|
+
end
|
34
40
|
end
|
35
|
-
|
36
|
-
|
41
|
+
if ::ActiveRecord::VERSION::MAJOR.to_i < 4
|
42
|
+
indexes.each do |index|
|
43
|
+
add_index(table, index.columns, index.opts)
|
44
|
+
end
|
37
45
|
end
|
38
46
|
end
|
39
47
|
|
40
|
-
##
|
41
|
-
# :method: add_index
|
42
|
-
#
|
43
|
-
# SchemaPlus modifies SchemaStatements::add_index so that it ignores
|
44
|
-
# errors raised about add an index that already exists -- i.e. that has
|
45
|
-
# the same index name, same columns, and same options -- and writes a
|
46
|
-
# warning to the log. Some combinations of rails & DB adapter versions
|
47
|
-
# would log such a warning, others would raise an error; with
|
48
|
-
# SchemaPlus all versions log the warning and do not raise the error.
|
49
|
-
#
|
50
|
-
# (This avoids collisions between SchemaPlus's auto index behavior and
|
51
|
-
# legacy explicit add_index statements, for platforms that would raise
|
52
|
-
# an error.)
|
53
|
-
#
|
54
|
-
def add_index_with_schema_plus(table, columns, options={})
|
55
|
-
add_index_without_schema_plus(table, columns, options)
|
56
|
-
rescue => e
|
57
|
-
SchemaStatements.add_index_exception_handler(self, table, columns, options, e)
|
58
|
-
end
|
59
|
-
|
60
48
|
def self.add_index_exception_handler(connection, table, columns, options, e) #:nodoc:
|
61
49
|
raise unless e.message.match(/["']([^"']+)["'].*already exists/)
|
62
50
|
name = $1
|
@@ -66,5 +54,32 @@ module SchemaPlus::ActiveRecord::ConnectionAdapters
|
|
66
54
|
::ActiveRecord::Base.logger.warn "[schema_plus] Index name #{name.inspect}' on table #{table.inspect} already exists. Skipping."
|
67
55
|
end
|
68
56
|
|
57
|
+
module AddIndex
|
58
|
+
def self.included(base) #:nodoc:
|
59
|
+
base.class_eval do
|
60
|
+
alias_method_chain :add_index, :schema_plus
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
##
|
65
|
+
# :method: add_index
|
66
|
+
#
|
67
|
+
# SchemaPlus modifies SchemaStatements::add_index so that it ignores
|
68
|
+
# errors raised about add an index that already exists -- i.e. that has
|
69
|
+
# the same index name, same columns, and same options -- and writes a
|
70
|
+
# warning to the log. Some combinations of rails & DB adapter versions
|
71
|
+
# would log such a warning, others would raise an error; with
|
72
|
+
# SchemaPlus all versions log the warning and do not raise the error.
|
73
|
+
#
|
74
|
+
# (This avoids collisions between SchemaPlus's auto index behavior and
|
75
|
+
# legacy explicit add_index statements, for platforms that would raise
|
76
|
+
# an error.)
|
77
|
+
#
|
78
|
+
def add_index_with_schema_plus(table, columns, options={})
|
79
|
+
add_index_without_schema_plus(table, columns, options)
|
80
|
+
rescue => e
|
81
|
+
SchemaStatements.add_index_exception_handler(self, table, columns, options, e)
|
82
|
+
end
|
83
|
+
end
|
69
84
|
end
|
70
85
|
end
|
@@ -21,7 +21,16 @@ module SchemaPlus
|
|
21
21
|
alias_method_chain :indexes, :schema_plus
|
22
22
|
alias_method_chain :rename_table, :schema_plus
|
23
23
|
end
|
24
|
-
::ActiveRecord::
|
24
|
+
if ::ActiveRecord::VERSION::MAJOR.to_i < 4
|
25
|
+
::ActiveRecord::ConnectionAdapters::SQLiteColumn.send(:include, SQLiteColumn) unless ::ActiveRecord::ConnectionAdapters::SQLiteColumn.include?(SQLiteColumn)
|
26
|
+
else
|
27
|
+
::ActiveRecord::ConnectionAdapters::SQLite3Column.send(:include, SQLiteColumn) unless ::ActiveRecord::ConnectionAdapters::SQLite3Column.include?(SQLiteColumn)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def initialize(*args)
|
32
|
+
super
|
33
|
+
execute('PRAGMA FOREIGN_KEYS = ON')
|
25
34
|
end
|
26
35
|
|
27
36
|
def indexes_with_schema_plus(table_name, name = nil)
|
@@ -71,10 +80,6 @@ module SchemaPlus
|
|
71
80
|
|
72
81
|
protected
|
73
82
|
|
74
|
-
def post_initialize
|
75
|
-
execute('PRAGMA FOREIGN_KEYS = 1')
|
76
|
-
end
|
77
|
-
|
78
83
|
def get_foreign_keys(table_name = nil, name = nil)
|
79
84
|
results = execute(<<-SQL, name)
|
80
85
|
SELECT name, sql FROM sqlite_master
|
@@ -67,30 +67,43 @@ module SchemaPlus::ActiveRecord::ConnectionAdapters
|
|
67
67
|
include SchemaPlus::ActiveRecord::ColumnOptionsHandler
|
68
68
|
|
69
69
|
attr_accessor :schema_plus_config #:nodoc:
|
70
|
+
attr_reader :foreign_keys #:nodoc:
|
70
71
|
|
71
72
|
def self.included(base) #:nodoc:
|
72
73
|
base.class_eval do
|
73
|
-
attr_accessor :name
|
74
|
-
attr_accessor :indexes
|
75
74
|
alias_method_chain :initialize, :schema_plus
|
76
75
|
alias_method_chain :column, :schema_plus
|
77
76
|
alias_method_chain :references, :schema_plus
|
78
77
|
alias_method_chain :belongs_to, :schema_plus
|
79
78
|
alias_method_chain :primary_key, :schema_plus
|
80
|
-
|
79
|
+
|
80
|
+
if ::ActiveRecord::VERSION::MAJOR.to_i < 4
|
81
|
+
attr_accessor :name
|
82
|
+
attr_accessor :indexes
|
83
|
+
alias_method_chain :to_sql, :schema_plus
|
84
|
+
end
|
81
85
|
end
|
82
86
|
end
|
83
|
-
|
87
|
+
|
84
88
|
def initialize_with_schema_plus(*args) #:nodoc:
|
85
89
|
initialize_without_schema_plus(*args)
|
86
90
|
@foreign_keys = []
|
87
|
-
|
91
|
+
if ::ActiveRecord::VERSION::MAJOR.to_i < 4
|
92
|
+
@indexes = []
|
93
|
+
end
|
88
94
|
end
|
89
95
|
|
90
|
-
|
91
|
-
|
96
|
+
if ::ActiveRecord::VERSION::MAJOR.to_i < 4
|
97
|
+
def primary_key_with_schema_plus(name, options = {}) #:nodoc:
|
98
|
+
column(name, :primary_key, options)
|
99
|
+
end
|
100
|
+
else
|
101
|
+
def primary_key_with_schema_plus(name, type = :primary_key, options = {}) #:nodoc:
|
102
|
+
column(name, type, options.merge(:primary_key => true))
|
103
|
+
end
|
92
104
|
end
|
93
105
|
|
106
|
+
|
94
107
|
# need detect :polymorphic at this level, because rails strips it out
|
95
108
|
# before calling #column (twice, once for _id and once for _type)
|
96
109
|
def references_with_schema_plus(*args) #:nodoc:
|
@@ -122,8 +135,10 @@ module SchemaPlus::ActiveRecord::ConnectionAdapters
|
|
122
135
|
end
|
123
136
|
|
124
137
|
# Define an index for the current
|
125
|
-
|
126
|
-
|
138
|
+
if ::ActiveRecord::VERSION::MAJOR.to_i < 4
|
139
|
+
def index(column_name, options={})
|
140
|
+
@indexes << ::ActiveRecord::ConnectionAdapters::IndexDefinition.new(self.name, column_name, options)
|
141
|
+
end
|
127
142
|
end
|
128
143
|
|
129
144
|
def foreign_key(column_names, references_table_name, references_column_names, options = {})
|
@@ -165,7 +180,11 @@ module SchemaPlus::ActiveRecord::ConnectionAdapters
|
|
165
180
|
# Determines if an indexes is queued to be created. Called from
|
166
181
|
# ColumnOptionsHandler as part of checking whether to auto-create an index
|
167
182
|
def index_exists?(_, column_name, options={})
|
168
|
-
|
183
|
+
if ::ActiveRecord::VERSION::MAJOR.to_i < 4
|
184
|
+
@indexes.find{|index| index.table == self.name && index.columns == Array.wrap(column_name) && options.all?{|k, v| index.send(k) == v}}
|
185
|
+
else
|
186
|
+
@indexes.find {|index_column_name, index_options| Array.wrap(index_column_name) == Array.wrap(column_name) && options.all?{|k, v| index_options[k] == v} }
|
187
|
+
end
|
169
188
|
end
|
170
189
|
|
171
190
|
|
data/lib/schema_plus/version.rb
CHANGED
data/lib/schema_plus.rb
CHANGED
@@ -124,6 +124,10 @@ module SchemaPlus
|
|
124
124
|
::ActiveRecord::ConnectionAdapters::IndexDefinition.send(:include, SchemaPlus::ActiveRecord::ConnectionAdapters::IndexDefinition)
|
125
125
|
::ActiveRecord::ConnectionAdapters::SchemaStatements.send(:include, SchemaPlus::ActiveRecord::ConnectionAdapters::SchemaStatements)
|
126
126
|
::ActiveRecord::ConnectionAdapters::TableDefinition.send(:include, SchemaPlus::ActiveRecord::ConnectionAdapters::TableDefinition)
|
127
|
+
|
128
|
+
if ::ActiveRecord::VERSION::MAJOR.to_i >= 4
|
129
|
+
::ActiveRecord::ConnectionAdapters::AbstractAdapter::SchemaCreation.send(:include, SchemaPlus::ActiveRecord::ConnectionAdapters::AbstractAdapter::SchemaCreation)
|
130
|
+
end
|
127
131
|
end
|
128
132
|
|
129
133
|
def self.insert #:nodoc:
|
data/runspecs
CHANGED
@@ -5,8 +5,8 @@ require 'ostruct'
|
|
5
5
|
require 'shellwords'
|
6
6
|
require 'tempfile'
|
7
7
|
|
8
|
-
RUBY_VERSIONS = %W[1.9.2
|
9
|
-
RAILS_VERSIONS = %W[3.2]
|
8
|
+
RUBY_VERSIONS = %W[1.9.3 2.0.0]
|
9
|
+
RAILS_VERSIONS = %W[3.2 4.0]
|
10
10
|
DB_ADAPTERS = %W[postgresql mysql mysql2 sqlite3]
|
11
11
|
|
12
12
|
o = OpenStruct.new
|
@@ -65,10 +65,21 @@ Combo = Struct.new(:ruby, :rails, :db_adapter)
|
|
65
65
|
combos = o.ruby_versions.product(o.rails_versions, o.db_adapters).map{|product| Combo.new(*product)}.select {|combo|
|
66
66
|
case
|
67
67
|
when combo.rails >= "3.2" && combo.ruby <= "1.8.7" then false # no longer happens, just keeping it as an example
|
68
|
+
when combo.rails >= "4" && combo.db_adapter == "mysql" then false
|
68
69
|
else true
|
69
70
|
end
|
70
71
|
}
|
71
72
|
|
73
|
+
def ruby_version_selector(ruby)
|
74
|
+
if @use_rvm ||= system("which -s rvm")
|
75
|
+
"rvm #{ruby} do"
|
76
|
+
else
|
77
|
+
@versions ||= `rbenv versions --bare`.split
|
78
|
+
version = @versions.select{|v| v.start_with? ruby}.last || abort("no ruby version '#{ruby}' installed in rbenv")
|
79
|
+
"RBENV_VERSION=#{version}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
72
83
|
|
73
84
|
GEMFILES_DIR = File.expand_path('../gemfiles', __FILE__)
|
74
85
|
errs = []
|
@@ -88,7 +99,7 @@ combos.each_with_index do |combo, n|
|
|
88
99
|
"bundle exec rake #{db_adapter}:spec"
|
89
100
|
end
|
90
101
|
|
91
|
-
command = %Q{BUNDLE_GEMFILE="#{File.join(GEMFILES_DIR, "rails-#{rails}", "Gemfile.#{db_adapter}")}"
|
102
|
+
command = %Q{BUNDLE_GEMFILE="#{File.join(GEMFILES_DIR, "rails-#{rails}", "Gemfile.#{db_adapter}")}" #{ruby_version_selector(ruby)} #{cmd} #{Shellwords.join(ARGV)}}
|
92
103
|
|
93
104
|
puts "\n\n*** ruby version #{ruby} - rails version #{rails} - db adapter: #{db_adapter} [#{n+1} of #{combos.size}]\n\n#{command}"
|
94
105
|
|
data/spec/foreign_key_spec.rb
CHANGED
@@ -29,6 +29,28 @@ describe "Foreign Key" do
|
|
29
29
|
|
30
30
|
end
|
31
31
|
|
32
|
+
if ::ActiveRecord::VERSION::MAJOR.to_i >= 4
|
33
|
+
context "with modifications to SQL generated by upstream visit_TableDefinition" do
|
34
|
+
before(:each) do
|
35
|
+
ActiveRecord::Base.connection.class.const_get(:SchemaCreation).any_instance.stub :visit_TableDefinition_without_schema_plus => "this is unexpected"
|
36
|
+
end
|
37
|
+
|
38
|
+
it "raises an exception when attempting to create a table" do
|
39
|
+
expect {
|
40
|
+
define_schema(:auto_create => true) do
|
41
|
+
create_table :users, :force => true do |t|
|
42
|
+
t.string :login
|
43
|
+
end
|
44
|
+
create_table :comments, :force => true do |t|
|
45
|
+
t.integer :user_id
|
46
|
+
t.foreign_key :user_id, :users, :id
|
47
|
+
end
|
48
|
+
end
|
49
|
+
}.to raise_error(RuntimeError, /Internal Error: Can't find.*Rails internals have changed/)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
32
54
|
context "modification" do
|
33
55
|
|
34
56
|
before(:all) do
|
data/spec/schema_dumper_spec.rb
CHANGED
@@ -22,6 +22,17 @@ describe "Schema dump" do
|
|
22
22
|
t.integer :user_id
|
23
23
|
t.integer :first_comment_id
|
24
24
|
t.string :string_no_default
|
25
|
+
t.integer :short_id
|
26
|
+
t.string :str_short
|
27
|
+
t.integer :integer_col
|
28
|
+
t.float :float_col
|
29
|
+
t.decimal :decimal_col
|
30
|
+
t.datetime :datetime_col
|
31
|
+
t.timestamp :timestamp_col
|
32
|
+
t.time :time_col
|
33
|
+
t.date :date_col
|
34
|
+
t.binary :binary_col
|
35
|
+
t.boolean :boolean_col
|
25
36
|
end
|
26
37
|
|
27
38
|
create_table :comments, :force => true do |t|
|
@@ -80,19 +91,19 @@ describe "Schema dump" do
|
|
80
91
|
if SchemaPlusHelpers.postgresql?
|
81
92
|
it "should dump the default hash expr as now()" do
|
82
93
|
with_additional_column Post, :posted_at, :datetime, :default => :now do
|
83
|
-
dump_posts.should match(
|
94
|
+
dump_posts.should match(%r{t\.datetime\s+"posted_at",\s*(?:default:|:default =>)\s*\{\s*(?:expr:|:expr =>)\s*"now\(\)"\s*\}})
|
84
95
|
end
|
85
96
|
end
|
86
97
|
|
87
98
|
it "should dump the default hash expr as CURRENT_TIMESTAMP" do
|
88
99
|
with_additional_column Post, :posted_at, :datetime, :default => {:expr => 'date \'2001-09-28\''} do
|
89
|
-
dump_posts.should match(%r{t
|
100
|
+
dump_posts.should match(%r{t\.datetime\s+"posted_at",\s*(?:default:|:default =>)\s*'2001-09-28 00:00:00'})
|
90
101
|
end
|
91
102
|
end
|
92
103
|
|
93
104
|
it "can dump a complex default expression" do
|
94
105
|
with_additional_column Post, :name, :string, :default => {:expr => 'substring(random()::text from 3 for 6)'} do
|
95
|
-
dump_posts.should match(%r{t
|
106
|
+
dump_posts.should match(%r{t\.string\s+"name",\s*(?:default:|:default =>)\s*{\s*(?:expr:|:expr =>)\s*"\\"substring\\"\(\(random\(\)\)::text, 3, 6\)"\s*}})
|
96
107
|
end
|
97
108
|
end
|
98
109
|
end
|
@@ -100,19 +111,19 @@ describe "Schema dump" do
|
|
100
111
|
if SchemaPlusHelpers.sqlite3?
|
101
112
|
it "should dump the default hash expr as now" do
|
102
113
|
with_additional_column Post, :posted_at, :datetime, :default => :now do
|
103
|
-
dump_posts.should match(
|
114
|
+
dump_posts.should match(%r{t\.datetime\s+"posted_at",\s*(?:default:|:default =>)\s*\{\s*(?:expr:|:expr =>)\s*"\(DATETIME\('now'\)\)"\s*\}})
|
104
115
|
end
|
105
116
|
end
|
106
117
|
|
107
118
|
it "should dump the default hash expr string as now" do
|
108
119
|
with_additional_column Post, :posted_at, :datetime, :default => { :expr => "(DATETIME('now'))" } do
|
109
|
-
dump_posts.should match(
|
120
|
+
dump_posts.should match(%r{t\.datetime\s+"posted_at",\s*(?:default:|:default =>)\s*\{\s*(?:expr:|:expr =>)\s*"\(DATETIME\('now'\)\)"\s*\}})
|
110
121
|
end
|
111
122
|
end
|
112
123
|
|
113
124
|
it "should dump the default value normally" do
|
114
125
|
with_additional_column Post, :posted_at, :string, :default => "now" do
|
115
|
-
dump_posts.should match(%r{t
|
126
|
+
dump_posts.should match(%r{t\.string\s*"posted_at",\s*(?:default:|:default =>)\s*"now"})
|
116
127
|
end
|
117
128
|
end
|
118
129
|
end
|
@@ -123,7 +134,7 @@ describe "Schema dump" do
|
|
123
134
|
ActiveRecord::Migration.suppress_messages do
|
124
135
|
ActiveRecord::Migration.change_column_default :posts, :string_no_default, nil
|
125
136
|
end
|
126
|
-
dump_posts.should match(%r{t
|
137
|
+
dump_posts.should match(%r{t\.string\s+"string_no_default"\s*$})
|
127
138
|
end
|
128
139
|
|
129
140
|
it "should include foreign_key options" do
|
@@ -168,6 +179,21 @@ describe "Schema dump" do
|
|
168
179
|
end
|
169
180
|
end
|
170
181
|
|
182
|
+
it "should define case insensitive index with mixed ids and strings" do
|
183
|
+
with_index Post, [:user_id, :str_short, :short_id, :body], :case_sensitive => false do
|
184
|
+
dump_posts.should match(to_regexp(%q{t.index ["user_id", "str_short", "short_id", "body"], :name => "index_posts_on_user_id_and_str_short_and_short_id_and_body", :case_sensitive => false}))
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
[:integer, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean].each do |col_type|
|
189
|
+
col_name = "#{col_type}_col"
|
190
|
+
it "should define case insensitive index that includes an #{col_type}" do
|
191
|
+
with_index Post, [:user_id, :str_short, col_name, :body], :case_sensitive => false do
|
192
|
+
dump_posts.should match(to_regexp(%Q!t.index ["user_id", "str_short", "#{col_name}", "body"], :name => "index_posts_on_user_id_and_str_short_and_#{col_name}_and_body", :case_sensitive => false!))
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
171
197
|
it "should define conditions" do
|
172
198
|
with_index Post, :user_id, :name => "posts_user_id_index", :conditions => "user_id IS NOT NULL" do
|
173
199
|
dump_posts.should match(to_regexp(%q{t.index ["user_id"], :name => "posts_user_id_index", :conditions => "(user_id IS NOT NULL)"}))
|
data/spec/spec_helper.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
require 'simplecov'
|
2
|
+
require 'simplecov-gem-adapter'
|
3
|
+
SimpleCov.use_merging true
|
4
|
+
SimpleCov.merge_timeout 3600
|
5
|
+
SimpleCov.start "gem"
|
6
6
|
|
7
7
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
8
8
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
@@ -55,4 +55,4 @@ def remove_all_models
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
-
SimpleCov.command_name ActiveRecord::Base.connection.adapter_name
|
58
|
+
SimpleCov.command_name "[ruby #{RUBY_VERSION} - ActiveRecord #{::ActiveRecord::VERSION::STRING} - #{ActiveRecord::Base.connection.adapter_name}]"
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: schema_plus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
5
|
-
prerelease:
|
4
|
+
version: 1.2.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Ronen Barzel
|
@@ -10,105 +9,93 @@ authors:
|
|
10
9
|
autorequire:
|
11
10
|
bindir: bin
|
12
11
|
cert_chain: []
|
13
|
-
date: 2013-
|
12
|
+
date: 2013-08-13 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: rails
|
17
16
|
requirement: !ruby/object:Gem::Requirement
|
18
|
-
none: false
|
19
17
|
requirements:
|
20
|
-
- -
|
18
|
+
- - '>='
|
21
19
|
- !ruby/object:Gem::Version
|
22
20
|
version: '3.2'
|
23
21
|
type: :runtime
|
24
22
|
prerelease: false
|
25
23
|
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
none: false
|
27
24
|
requirements:
|
28
|
-
- -
|
25
|
+
- - '>='
|
29
26
|
- !ruby/object:Gem::Version
|
30
27
|
version: '3.2'
|
31
28
|
- !ruby/object:Gem::Dependency
|
32
29
|
name: valuable
|
33
30
|
requirement: !ruby/object:Gem::Requirement
|
34
|
-
none: false
|
35
31
|
requirements:
|
36
|
-
- -
|
32
|
+
- - '>='
|
37
33
|
- !ruby/object:Gem::Version
|
38
34
|
version: '0'
|
39
35
|
type: :runtime
|
40
36
|
prerelease: false
|
41
37
|
version_requirements: !ruby/object:Gem::Requirement
|
42
|
-
none: false
|
43
38
|
requirements:
|
44
|
-
- -
|
39
|
+
- - '>='
|
45
40
|
- !ruby/object:Gem::Version
|
46
41
|
version: '0'
|
47
42
|
- !ruby/object:Gem::Dependency
|
48
43
|
name: rake
|
49
44
|
requirement: !ruby/object:Gem::Requirement
|
50
|
-
none: false
|
51
45
|
requirements:
|
52
|
-
- -
|
46
|
+
- - '>='
|
53
47
|
- !ruby/object:Gem::Version
|
54
48
|
version: '0'
|
55
49
|
type: :development
|
56
50
|
prerelease: false
|
57
51
|
version_requirements: !ruby/object:Gem::Requirement
|
58
|
-
none: false
|
59
52
|
requirements:
|
60
|
-
- -
|
53
|
+
- - '>='
|
61
54
|
- !ruby/object:Gem::Version
|
62
55
|
version: '0'
|
63
56
|
- !ruby/object:Gem::Dependency
|
64
57
|
name: rspec
|
65
58
|
requirement: !ruby/object:Gem::Requirement
|
66
|
-
none: false
|
67
59
|
requirements:
|
68
|
-
- -
|
60
|
+
- - '>='
|
69
61
|
- !ruby/object:Gem::Version
|
70
62
|
version: '0'
|
71
63
|
type: :development
|
72
64
|
prerelease: false
|
73
65
|
version_requirements: !ruby/object:Gem::Requirement
|
74
|
-
none: false
|
75
66
|
requirements:
|
76
|
-
- -
|
67
|
+
- - '>='
|
77
68
|
- !ruby/object:Gem::Version
|
78
69
|
version: '0'
|
79
70
|
- !ruby/object:Gem::Dependency
|
80
71
|
name: simplecov
|
81
72
|
requirement: !ruby/object:Gem::Requirement
|
82
|
-
none: false
|
83
73
|
requirements:
|
84
|
-
- -
|
74
|
+
- - '>='
|
85
75
|
- !ruby/object:Gem::Version
|
86
76
|
version: '0'
|
87
77
|
type: :development
|
88
78
|
prerelease: false
|
89
79
|
version_requirements: !ruby/object:Gem::Requirement
|
90
|
-
none: false
|
91
80
|
requirements:
|
92
|
-
- -
|
81
|
+
- - '>='
|
93
82
|
- !ruby/object:Gem::Version
|
94
83
|
version: '0'
|
95
84
|
- !ruby/object:Gem::Dependency
|
96
85
|
name: simplecov-gem-adapter
|
97
86
|
requirement: !ruby/object:Gem::Requirement
|
98
|
-
none: false
|
99
87
|
requirements:
|
100
|
-
- -
|
88
|
+
- - '>='
|
101
89
|
- !ruby/object:Gem::Version
|
102
90
|
version: '0'
|
103
91
|
type: :development
|
104
92
|
prerelease: false
|
105
93
|
version_requirements: !ruby/object:Gem::Requirement
|
106
|
-
none: false
|
107
94
|
requirements:
|
108
|
-
- -
|
95
|
+
- - '>='
|
109
96
|
- !ruby/object:Gem::Version
|
110
97
|
version: '0'
|
111
|
-
description:
|
98
|
+
description: 'SchemaPlus is an ActiveRecord extension that provides enhanced capabilities
|
112
99
|
for schema definition and querying, including: enhanced and more DRY index capabilities,
|
113
100
|
support and automation for foreign key constraints, and support for views.'
|
114
101
|
email:
|
@@ -130,6 +117,14 @@ files:
|
|
130
117
|
- gemfiles/rails-3.2/Gemfile.mysql2
|
131
118
|
- gemfiles/rails-3.2/Gemfile.postgresql
|
132
119
|
- gemfiles/rails-3.2/Gemfile.sqlite3
|
120
|
+
- gemfiles/rails-4.0/Gemfile.base
|
121
|
+
- gemfiles/rails-4.0/Gemfile.mysql2
|
122
|
+
- gemfiles/rails-4.0/Gemfile.postgresql
|
123
|
+
- gemfiles/rails-4.0/Gemfile.sqlite3
|
124
|
+
- gemfiles/rails-edge/Gemfile.base
|
125
|
+
- gemfiles/rails-edge/Gemfile.mysql2
|
126
|
+
- gemfiles/rails-edge/Gemfile.postgresql
|
127
|
+
- gemfiles/rails-edge/Gemfile.sqlite3
|
133
128
|
- init.rb
|
134
129
|
- lib/rails/tasks/database.rake
|
135
130
|
- lib/schema_plus.rb
|
@@ -177,27 +172,26 @@ files:
|
|
177
172
|
- spec/views_spec.rb
|
178
173
|
homepage: https://github.com/lomba/schema_plus
|
179
174
|
licenses: []
|
175
|
+
metadata: {}
|
180
176
|
post_install_message:
|
181
177
|
rdoc_options: []
|
182
178
|
require_paths:
|
183
179
|
- lib
|
184
180
|
required_ruby_version: !ruby/object:Gem::Requirement
|
185
|
-
none: false
|
186
181
|
requirements:
|
187
|
-
- -
|
182
|
+
- - '>='
|
188
183
|
- !ruby/object:Gem::Version
|
189
184
|
version: 1.9.2
|
190
185
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
191
|
-
none: false
|
192
186
|
requirements:
|
193
|
-
- -
|
187
|
+
- - '>='
|
194
188
|
- !ruby/object:Gem::Version
|
195
189
|
version: '0'
|
196
190
|
requirements: []
|
197
191
|
rubyforge_project: schema_plus
|
198
|
-
rubygems_version:
|
192
|
+
rubygems_version: 2.0.3
|
199
193
|
signing_key:
|
200
|
-
specification_version:
|
194
|
+
specification_version: 4
|
201
195
|
summary: Enhances ActiveRecord schema mechanism, including more DRY index creation
|
202
196
|
and support for foreign key constraints and views.
|
203
197
|
test_files:
|
@@ -224,4 +218,3 @@ test_files:
|
|
224
218
|
- spec/support/matchers/have_index.rb
|
225
219
|
- spec/support/matchers/reference.rb
|
226
220
|
- spec/views_spec.rb
|
227
|
-
has_rdoc:
|