declare_schema 0.4.2 → 0.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bf6d8bf1670910eeadc3f7ed08860af6630f1b5edc271a0740fe8bb94e7f5c71
4
- data.tar.gz: 4d058e02cb6b269f6b66fa20f8ac661ecdb7f8b31547cf43e65e27c869221902
3
+ metadata.gz: c0c13793a5b263a2f1134ee19168a42ceb57c472cf8fb656b8e86fcdd9500b79
4
+ data.tar.gz: ee92620b0a091538958957205ba940d97cd9f67bc606751cb52a8ae44370e541
5
5
  SHA512:
6
- metadata.gz: d95d741db5f9279cfe39f7bd972581708a0ccae7e2d9d209318282a9980d2980e3611592ba08b6b53136e23b92ac4aaa51e2a66187002de04bf818c29715820f
7
- data.tar.gz: 93c203bb2ff2255f014d76a3069d1530d97f9603293738844e2faf6f2c9cb6fb95dcc2aa9ad505df15c8e1e14567e076a5e2901b7b4847f804ce3dd85dc5b313
6
+ metadata.gz: 3bc0e18dd1b3a998640cc2e983c86182e19b855d8ce42b3f7233b3471a7849d0dc28fa2653d110b42d0544c513267f8066386496b1469085bb507541c068b87a
7
+ data.tar.gz: 34b9e31862291b85becf7eeb908c4ef1da5b29178b1ab387b35c6678680299cd921fa65b49e0ba89604518a66515092d3e7d6c38678267301c9399b4572d372e
@@ -0,0 +1,14 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: bundler
4
+ directory: "/"
5
+ schedule:
6
+ interval: weekly
7
+ day: friday
8
+ time: "22:00"
9
+ timezone: PST8PDT
10
+ open-pull-requests-limit: 99
11
+ versioning-strategy: lockfile-only
12
+ commit-message:
13
+ prefix: No-Jira
14
+ include: scope
@@ -0,0 +1,44 @@
1
+ ---
2
+ on: [push]
3
+
4
+ name: DeclareSchema Build
5
+
6
+ jobs:
7
+ build:
8
+ name: DeclareSchema Build
9
+ runs-on: ubuntu-latest
10
+ strategy:
11
+ matrix:
12
+ ruby: [ 2.4.5, 2.5.8, 2.6.5, 2.7.1 ]
13
+ gemfile: [ gemfiles/rails_4.gemfile, gemfiles/rails_5.gemfile, gemfiles/rails_6.gemfile ]
14
+ exclude:
15
+ - { gemfile: gemfiles/rails_4.gemfile, ruby: 2.7.1 }
16
+ - { gemfile: gemfiles/rails_5.gemfile, ruby: 2.4.5 }
17
+ - { gemfile: gemfiles/rails_6.gemfile, ruby: 2.4.5 }
18
+ env:
19
+ BUNDLE_GEMFILE: "${{ matrix.gemfile }}"
20
+ steps:
21
+ - name: Checkout Branch
22
+ id: checkout_branch
23
+ uses: actions/checkout@v2
24
+ - name: Setup Ruby
25
+ id: setup_ruby
26
+ uses: ruby/setup-ruby@v1
27
+ with:
28
+ bundler: 1.17.3
29
+ ruby-version: ${{matrix.ruby}}
30
+ - name: Remove Bundler 2
31
+ id: remove_bundler_2
32
+ if: ${{ matrix.ruby >= '2.6.5' }}
33
+ run: |
34
+ rm -f /opt/hostedtoolcache/Ruby/2.*/x64/lib/ruby/gems/2.*/specifications/default/bundler-2.*.gemspec
35
+ gem install bundler:1.17.3 --force --default
36
+ gem install bundler -v 1.17.3
37
+ - name: Appraisals
38
+ id: appraisals
39
+ run: |
40
+ bundle install --jobs=3 --retry=3 --path=${BUNDLE_PATH:-vendor/bundle} --gemfile=${{ matrix.gemfile }}
41
+ git config --global user.email "dummy@example.com"
42
+ git config --global user.name "dummy"
43
+ bundle exec rake test:prepare_testapp[force]
44
+ bundle exec rake test:all < test_responses.txt
data/.gitignore CHANGED
@@ -12,3 +12,4 @@
12
12
 
13
13
  # appraisal
14
14
  gemfiles/*.lock
15
+ .idea
@@ -4,6 +4,22 @@ Inspired by [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
4
4
 
5
5
  Note: this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.6.0] - 2020-12-23
8
+ ### Added
9
+ - Fields may now be declared with `:bigint` type which is identical to `:integer, limit 8`
10
+ - FieldSpec#initialize interface now includes `position` keyword argument and `**options` hash.
11
+
12
+ ### Fixed
13
+ - Fixed cycle in which FieldSpec#initialize was calling `model.field_specs`
14
+
15
+ ### Changed
16
+ - Changed ci support from Travis to Github Workflow
17
+
18
+ ## [0.5.0] - 2020-12-21
19
+ ### Added
20
+ - Added support for configuring the character set and collation for MySQL databases
21
+ at the global, table, and field level
22
+
7
23
  ## [0.4.2] - 2020-12-05
8
24
  ### Fixed
9
25
  - Generalize the fix below to sqlite || Rails 4.
@@ -15,7 +31,7 @@ Note: this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0
15
31
  ## [0.4.0] - 2020-11-20
16
32
  ### Added
17
33
  - Fields may be declared with `serialize: true` (any value with a valid `.to_yaml` stored as YAML),
18
- or `serialize: <serializeable-class>`, where `<serializeable-class>`
34
+ or `serialize: <serializeable-class>`, where `<serializeable-class>`
19
35
  may be `Array` (`Array` stored as YAML) or `Hash` (`Hash` stored as YAML) or `JSON` (any value with a valid `.to_json`, stored as JSON)
20
36
  or any custom serializable class.
21
37
  This invokes `ActiveSupport`'s `serialize` macro for that field, passing the serializable class, if given.
@@ -68,6 +84,8 @@ using the appropriate Rails configuration attributes.
68
84
  ### Added
69
85
  - Initial version from https://github.com/Invoca/hobo_fields v4.1.0.
70
86
 
87
+ [0.6.0]: https://github.com/Invoca/declare_schema/compare/v0.5.0...v0.6.0
88
+ [0.5.0]: https://github.com/Invoca/declare_schema/compare/v0.4.2...v0.5.0
71
89
  [0.4.2]: https://github.com/Invoca/declare_schema/compare/v0.4.1...v0.4.2
72
90
  [0.4.1]: https://github.com/Invoca/declare_schema/compare/v0.4.0...v0.4.1
73
91
  [0.4.0]: https://github.com/Invoca/declare_schema/compare/v0.3.1...v0.4.0
data/Gemfile CHANGED
@@ -14,6 +14,7 @@ gem 'bundler', '< 2'
14
14
  gem "climate_control", '~> 0.2'
15
15
  gem 'pry'
16
16
  gem 'pry-byebug'
17
+ gem 'mysql2'
17
18
  gem 'rails', '~> 5.2', '>= 5.2.4.3'
18
19
  gem 'responders'
19
20
  gem 'rspec'
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- declare_schema (0.4.2)
4
+ declare_schema (0.6.0)
5
5
  rails (>= 4.2)
6
6
 
7
7
  GEM
@@ -85,6 +85,7 @@ GEM
85
85
  mini_portile2 (2.4.0)
86
86
  minitest (5.14.2)
87
87
  msgpack (1.3.3)
88
+ mysql2 (0.5.3)
88
89
  nio4r (2.5.4)
89
90
  nokogiri (1.10.10)
90
91
  mini_portile2 (~> 2.4.0)
@@ -187,6 +188,7 @@ DEPENDENCIES
187
188
  climate_control (~> 0.2)
188
189
  declare_schema!
189
190
  listen
191
+ mysql2
190
192
  pry
191
193
  pry-byebug
192
194
  rails (~> 5.2, >= 5.2.4.3)
data/README.md CHANGED
@@ -70,6 +70,72 @@ DeclareSchema::Migration::Migrator.before_generating_migration do
70
70
  end
71
71
  ```
72
72
 
73
+ ## Declaring Character Set and Collation
74
+ _Note: This feature currently only works for MySQL database configurations._
75
+
76
+ MySQL originally supported UTF-8 in the range of 1-3 bytes (`mb3` or "multi-byte 3")
77
+ which covered the full set of Unicode code points at the time: U+0000 - U+FFFF.
78
+ But later, Unicode was extended beyond U+FFFF to make room for emojis, and with that
79
+ UTF-8 require 1-4 bytes (`mb4` or "multi-byte 4"). With this addition, there has
80
+ come a need to dynamically define the character set and collation for individual
81
+ tables and columns in the database. With `declare_schema` this can be configured
82
+ at three separate levels
83
+
84
+ ### Global Configuration
85
+ The character set and collation for all tables and fields can be set at the global level
86
+ using the `Generators::DeclareSchema::Migrator.default_charset=` and
87
+ `Generators::DeclareSchema::Migrator.default_collation=` configuration methods.
88
+
89
+ For example, adding the following to your `config/initializers` directory will
90
+ turn all tables into `utf8mb4` supporting tables:
91
+
92
+ **declare_schema.rb**
93
+ ```ruby
94
+ # frozen_string_literal: true
95
+
96
+ Generators::DeclareSchema::Migration::Migrator.default_charset = "utf8mb4"
97
+ Generators::DeclareSchema::Migration::Migrator.default_collation = "utf8mb4_general"
98
+ ```
99
+
100
+ ### Table Configuration
101
+ In order to configure a table's default character set and collation, the `charset` and
102
+ `collation` arguments can be added to the `fields` block.
103
+
104
+ For example, if you have a comments model that needs `utf8mb4` support, it would look
105
+ like the following:
106
+
107
+ **app/models/comment.rb**
108
+ ```ruby
109
+ # frozen_string_literal: true
110
+
111
+ class Comment < ActiveRecord::Base
112
+ fields charset: "utf8mb4", collation: "utf8mb4_general" do
113
+ subject :string, limit: 255
114
+ content :text, limit: 0xffff_ffff
115
+ end
116
+ end
117
+ ```
118
+
119
+ ### Field Configuration
120
+ If you're looking to only change the character set and collation for a single field
121
+ in the table, simply set the `charset` and `collation` configuration options on the
122
+ field definition itself.
123
+
124
+ For example, if you only want to support `utf8mb4` for the content of a comment, it would
125
+ look like the following:
126
+
127
+ **app/models/comment.rb**
128
+ ```ruby
129
+ # frozen_string_literal: true
130
+
131
+ class Comment < ActiveRecord::Base
132
+ fields do
133
+ subject :string, limit: 255
134
+ context :text, limit: 0xffff_ffff, charset: "utf8mb4", collation: "utf8mb4_general"
135
+ end
136
+ end
137
+ ```
138
+
73
139
  ## Installing
74
140
 
75
141
  Install the `DeclareSchema` gem directly:
@@ -7,6 +7,7 @@ gem "bundler", "< 2"
7
7
  gem "climate_control", "~> 0.2"
8
8
  gem "pry"
9
9
  gem "pry-byebug"
10
+ gem "mysql2"
10
11
  gem "rails", "~> 4.2"
11
12
  gem "responders"
12
13
  gem "rspec"
@@ -7,6 +7,7 @@ gem "bundler", "< 2"
7
7
  gem "climate_control", "~> 0.2"
8
8
  gem "pry"
9
9
  gem "pry-byebug"
10
+ gem "mysql2"
10
11
  gem "rails", "~> 5.2"
11
12
  gem "responders"
12
13
  gem "rspec"
@@ -7,6 +7,7 @@ gem "bundler", "< 2"
7
7
  gem "climate_control", "~> 0.2"
8
8
  gem "pry"
9
9
  gem "pry-byebug"
10
+ gem "mysql2"
10
11
  gem "rails", "~> 6.0"
11
12
  gem "responders"
12
13
  gem "rspec"
@@ -41,5 +41,6 @@ require 'declare_schema/model'
41
41
  require 'declare_schema/model/field_spec'
42
42
  require 'declare_schema/model/index_definition'
43
43
  require 'declare_schema/model/foreign_key_definition'
44
+ require 'declare_schema/model/table_options_definition'
44
45
 
45
46
  require 'declare_schema/railtie' if defined?(Rails)
@@ -6,12 +6,13 @@ require 'declare_schema/field_declaration_dsl'
6
6
 
7
7
  module DeclareSchema
8
8
  module FieldsDsl
9
- def fields(&block)
9
+ def fields(table_options = {}, &block)
10
10
  # Any model that calls 'fields' gets DeclareSchema::Model behavior
11
11
  DeclareSchema::Model.mix_in(self)
12
12
 
13
13
  # @include_in_migration = false #||= options.fetch(:include_in_migration, true); options.delete(:include_in_migration)
14
14
  @include_in_migration = true
15
+ @table_options = table_options
15
16
 
16
17
  if block
17
18
  dsl = DeclareSchema::FieldDeclarationDsl.new(self, null: false)
@@ -30,6 +30,10 @@ module DeclareSchema
30
30
  inheriting_cattr_reader ignore_indexes: []
31
31
  inheriting_cattr_reader constraint_specs: []
32
32
 
33
+ # table_options holds optional configuration for the create_table statement
34
+ # supported options include :charset and :collation
35
+ inheriting_cattr_reader table_options: HashWithIndifferentAccess.new
36
+
33
37
  # eval avoids the ruby 1.9.2 "super from singleton method ..." error
34
38
 
35
39
  eval %(
@@ -84,7 +88,7 @@ module DeclareSchema
84
88
  add_formatting_for_field(name, type)
85
89
  add_validations_for_field(name, type, args, options)
86
90
  add_index_for_field(name, args, options)
87
- field_specs[name] = ::DeclareSchema::Model::FieldSpec.new(self, name, type, options)
91
+ field_specs[name] = ::DeclareSchema::Model::FieldSpec.new(self, name, type, position: field_specs.size, **options)
88
92
  attr_order << name unless attr_order.include?(name)
89
93
  end
90
94
 
@@ -33,7 +33,8 @@ module DeclareSchema
33
33
 
34
34
  attr_reader :model, :name, :type, :position, :options
35
35
 
36
- def initialize(model, name, type, options = {})
36
+ def initialize(model, name, type, position: 0, **options)
37
+ # TODO: TECH-5116
37
38
  # Invoca change - searching for the primary key was causing an additional database read on every model load. Assume
38
39
  # "id" which works for invoca.
39
40
  # raise ArgumentError, "you cannot provide a field spec for the primary key" if name == model.primary_key
@@ -43,9 +44,8 @@ module DeclareSchema
43
44
  @name = name.to_sym
44
45
  type.is_a?(Symbol) or raise ArgumentError, "type must be a Symbol; got #{type.inspect}"
45
46
  @type = type
46
- position_option = options.delete(:position)
47
+ @position = position
47
48
  @options = options
48
-
49
49
  case type
50
50
  when :text
51
51
  @options[:default] and raise "default may not be given for :text field #{model}##{@name}"
@@ -54,8 +54,15 @@ module DeclareSchema
54
54
  end
55
55
  when :string
56
56
  @options[:limit] or raise "limit must be given for :string field #{model}##{@name}: #{@options.inspect}; do you want `limit: 255`?"
57
+ when :bigint
58
+ @type = :integer
59
+ @options = options.merge(limit: 8)
60
+ end
61
+
62
+ unless type.in?([:text, :string])
63
+ @options[:collation] and raise "collation may only given for :string and :text fields"
64
+ @options[:charset] and raise "charset may only given for :string and :text fields"
57
65
  end
58
- @position = position_option || model.field_specs.length
59
66
  end
60
67
 
61
68
  TYPE_SYNONYMS = { timestamp: :datetime }.freeze
@@ -102,6 +109,18 @@ module DeclareSchema
102
109
  @options[:default]
103
110
  end
104
111
 
112
+ def collation
113
+ if ActiveRecord::Base.connection.class.name.match?(/mysql/i)
114
+ (@options[:collation] || model.table_options[:collation] || Generators::DeclareSchema::Migration::Migrator.default_collation).to_s
115
+ end
116
+ end
117
+
118
+ def charset
119
+ if ActiveRecord::Base.connection.class.name.match?(/mysql/i)
120
+ (@options[:charset] || model.table_options[:charset] || Generators::DeclareSchema::Migration::Migrator.default_charset).to_s
121
+ end
122
+ end
123
+
105
124
  def same_type?(col_spec)
106
125
  type = sql_type
107
126
  normalized_type = TYPE_SYNONYMS[type] || type
@@ -109,36 +128,77 @@ module DeclareSchema
109
128
  normalized_type == normalized_col_spec_type
110
129
  end
111
130
 
112
- def different_to?(col_spec)
113
- !same_type?(col_spec) ||
114
- begin
115
- native_type = native_types[type]
116
- check_attributes = [:null, :default]
117
- check_attributes += [:precision, :scale] if sql_type == :decimal && !col_spec.is_a?(SQLITE_COLUMN_CLASS) # remove when rails fixes https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/2872
118
- check_attributes -= [:default] if sql_type == :text && col_spec.class.name =~ /mysql/i
119
- check_attributes << :limit if sql_type.in?([:string, :binary, :varbinary, :integer, :enum]) ||
120
- (sql_type == :text && self.class.mysql_text_limits?)
121
- check_attributes.any? do |k|
122
- if k == :default
123
- case Rails::VERSION::MAJOR
124
- when 4
125
- col_spec.type_cast_from_database(col_spec.default) != col_spec.type_cast_from_database(default)
126
- else
127
- cast_type = ActiveRecord::Base.connection.lookup_cast_type_from_column(col_spec) or raise "cast_type not found for #{col_spec.inspect}"
128
- cast_type.deserialize(col_spec.default) != cast_type.deserialize(default)
129
- end
130
- else
131
- col_value = col_spec.send(k)
132
- if col_value.nil? && native_type
133
- col_value = native_type[k]
134
- end
135
- col_value != send(k)
136
- end
131
+ def different_to?(table_name, col_spec)
132
+ !same_as(table_name, col_spec)
133
+ end
134
+
135
+ def same_as(table_name, col_spec)
136
+ same_type?(col_spec) &&
137
+ same_attributes?(col_spec) &&
138
+ (!type.in?([:text, :string]) || same_charset_and_collation?(table_name, col_spec))
139
+ end
140
+
141
+ private
142
+
143
+ def same_attributes?(col_spec)
144
+ native_type = native_types[type]
145
+ check_attributes = [:null, :default]
146
+ check_attributes += [:precision, :scale] if sql_type == :decimal && !col_spec.is_a?(SQLITE_COLUMN_CLASS) # remove when rails fixes https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/2872
147
+ check_attributes -= [:default] if sql_type == :text && col_spec.class.name =~ /mysql/i
148
+ check_attributes << :limit if sql_type.in?([:string, :binary, :varbinary, :integer, :enum]) ||
149
+ (sql_type == :text && self.class.mysql_text_limits?)
150
+ check_attributes.all? do |k|
151
+ if k == :default
152
+ case Rails::VERSION::MAJOR
153
+ when 4
154
+ col_spec.type_cast_from_database(col_spec.default) == col_spec.type_cast_from_database(default)
155
+ else
156
+ cast_type = ActiveRecord::Base.connection.lookup_cast_type_from_column(col_spec) or raise "cast_type not found for #{col_spec.inspect}"
157
+ cast_type.deserialize(col_spec.default) == cast_type.deserialize(default)
137
158
  end
159
+ else
160
+ col_value = col_spec.send(k)
161
+ if col_value.nil? && native_type
162
+ col_value = native_type[k]
163
+ end
164
+ col_value == send(k)
138
165
  end
166
+ end
139
167
  end
140
168
 
141
- private
169
+ def same_charset_and_collation?(table_name, col_spec)
170
+ current_collation_and_charset = collation_and_charset_for_column(table_name, col_spec)
171
+
172
+ collation == current_collation_and_charset[:collation] &&
173
+ charset == current_collation_and_charset[:charset]
174
+ end
175
+
176
+ def collation_and_charset_for_column(table_name, col_spec)
177
+ column_name = col_spec.name
178
+ connection = ActiveRecord::Base.connection
179
+
180
+ if connection.class.name.match?(/mysql/i)
181
+ database_name = connection.current_database
182
+
183
+ defaults = connection.select_one(<<~EOS)
184
+ SELECT C.character_set_name, C.collation_name
185
+ FROM information_schema.`COLUMNS` C
186
+ WHERE C.table_schema = '#{connection.quote_string(database_name)}' AND
187
+ C.table_name = '#{connection.quote_string(table_name)}' AND
188
+ C.column_name = '#{connection.quote_string(column_name)}';
189
+ EOS
190
+
191
+ defaults["character_set_name"] or raise "character_set_name missing from #{defaults.inspect}"
192
+ defaults["collation_name"] or raise "collation_name missing from #{defaults.inspect}"
193
+
194
+ {
195
+ charset: defaults["character_set_name"],
196
+ collation: defaults["collation_name"]
197
+ }
198
+ else
199
+ {}
200
+ end
201
+ end
142
202
 
143
203
  def native_type?(type)
144
204
  type.to_sym != :primary_key && native_types.has_key?(type)
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeclareSchema
4
+ module Model
5
+ class TableOptionsDefinition
6
+ include Comparable
7
+
8
+ TABLE_OPTIONS_TO_SQL_MAPPINGS = {
9
+ charset: 'CHARACTER SET',
10
+ collation: 'COLLATE'
11
+ }.freeze
12
+
13
+ class << self
14
+ def for_model(model, old_table_name = nil)
15
+ table_name = old_table_name || model.table_name
16
+ table_options = if model.connection.class.name.match?(/mysql/i)
17
+ mysql_table_options(model.connection, table_name)
18
+ else
19
+ {}
20
+ end
21
+
22
+ new(table_name, table_options)
23
+ end
24
+
25
+ private
26
+
27
+ def mysql_table_options(connection, table_name)
28
+ database = connection.current_database
29
+ defaults = connection.select_one(<<~EOS)
30
+ SELECT CCSA.character_set_name, CCSA.collation_name
31
+ FROM information_schema.`TABLES` T, information_schema.`COLLATION_CHARACTER_SET_APPLICABILITY` CCSA
32
+ WHERE CCSA.collation_name = T.table_collation AND
33
+ T.table_schema = '#{connection.quote_string(database)}' AND
34
+ T.table_name = '#{connection.quote_string(table_name)}';
35
+ EOS
36
+
37
+ defaults["character_set_name"] or raise "character_set_name missing from #{defaults.inspect}"
38
+ defaults["collation_name"] or raise "collation_name missing from #{defaults.inspect}"
39
+
40
+ {
41
+ charset: defaults["character_set_name"],
42
+ collation: defaults["collation_name"]
43
+ }
44
+ end
45
+ end
46
+
47
+ attr_reader :table_name, :table_options
48
+
49
+ def initialize(table_name, table_options = {})
50
+ @table_name = table_name
51
+ @table_options = table_options
52
+ end
53
+
54
+ def to_key
55
+ @key ||= [table_name, table_options].map(&:to_s)
56
+ end
57
+
58
+ def settings
59
+ @settings ||= table_options.map { |name, value| "#{TABLE_OPTIONS_TO_SQL_MAPPINGS[name]} #{value}" if value }.compact.join(" ")
60
+ end
61
+
62
+ def hash
63
+ to_key.hash
64
+ end
65
+
66
+ def <=>(rhs)
67
+ to_key <=> rhs.to_key
68
+ end
69
+
70
+ def equivalent?(rhs)
71
+ settings == rhs.settings
72
+ end
73
+
74
+ alias eql? ==
75
+ alias to_s settings
76
+
77
+ def alter_table_statement
78
+ statement = "ALTER TABLE #{ActiveRecord::Base.connection.quote_table_name(table_name)} #{to_s};"
79
+ "execute #{statement.inspect}"
80
+ end
81
+ end
82
+ end
83
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DeclareSchema
4
- VERSION = "0.4.2"
4
+ VERSION = "0.6.0"
5
5
  end
@@ -23,6 +23,10 @@ module Generators
23
23
  end
24
24
  end
25
25
 
26
+ def table_options
27
+ {}
28
+ end
29
+
26
30
  def table_name
27
31
  join_table
28
32
  end
@@ -33,11 +37,9 @@ module Generators
33
37
 
34
38
  def field_specs
35
39
  i = 0
36
- foreign_keys.reduce({}) do |h, v|
37
- # some trickery to avoid an infinite loop when FieldSpec#initialize tries to call model.field_specs
38
- h[v] = ::DeclareSchema::Model::FieldSpec.new(self, v, :integer, position: i, null: false)
40
+ foreign_keys.each_with_object({}) do |v, result|
41
+ result[v] = ::DeclareSchema::Model::FieldSpec.new(self, v, :integer, position: i, null: false)
39
42
  i += 1
40
- h
41
43
  end
42
44
  end
43
45
 
@@ -69,13 +71,19 @@ module Generators
69
71
  class Migrator
70
72
  class Error < RuntimeError; end
71
73
 
72
- @ignore_models = []
73
- @ignore_tables = []
74
+ DEFAULT_CHARSET = :utf8mb4
75
+ DEFAULT_COLLATION = :utf8mb4_general
76
+
77
+ @ignore_models = []
78
+ @ignore_tables = []
74
79
  @before_generating_migration_callback = nil
75
- @active_record_class = ActiveRecord::Base
80
+ @active_record_class = ActiveRecord::Base
81
+ @default_charset = DEFAULT_CHARSET
82
+ @default_collation = DEFAULT_COLLATION
76
83
 
77
84
  class << self
78
- attr_accessor :ignore_models, :ignore_tables, :disable_indexing, :disable_constraints, :active_record_class
85
+ attr_accessor :ignore_models, :ignore_tables, :disable_indexing, :disable_constraints,
86
+ :active_record_class, :default_charset, :default_collation
79
87
  attr_reader :before_generating_migration_callback
80
88
 
81
89
  def active_record_class
@@ -292,52 +300,76 @@ module Generators
292
300
  "drop_table :#{t}"
293
301
  end * "\n"
294
302
 
295
- changes = []
296
- undo_changes = []
297
- index_changes = []
298
- undo_index_changes = []
299
- fk_changes = []
300
- undo_fk_changes = []
303
+ changes = []
304
+ undo_changes = []
305
+ index_changes = []
306
+ undo_index_changes = []
307
+ fk_changes = []
308
+ undo_fk_changes = []
309
+ table_options_changes = []
310
+ undo_table_options_changes = []
311
+
301
312
  to_change.each do |t|
302
313
  model = models_by_table_name[t]
303
314
  table = to_rename.key(t) || model.table_name
304
315
  if table.in?(db_tables)
305
- change, undo, index_change, undo_index, fk_change, undo_fk = change_table(model, table)
316
+ change, undo, index_change, undo_index, fk_change, undo_fk, table_options_change, undo_table_options_change = change_table(model, table)
306
317
  changes << change
307
318
  undo_changes << undo
308
319
  index_changes << index_change
309
320
  undo_index_changes << undo_index
310
321
  fk_changes << fk_change
311
322
  undo_fk_changes << undo_fk
323
+ table_options_changes << table_options_change
324
+ undo_table_options_changes << undo_table_options_change
312
325
  end
313
326
  end
314
327
 
315
- up = [renames, drops, creates, changes, index_changes, fk_changes].flatten.reject(&:blank?) * "\n\n"
316
- down = [undo_changes, undo_renames, undo_drops, undo_creates, undo_index_changes, undo_fk_changes].flatten.reject(&:blank?) * "\n\n"
328
+ up = [renames, drops, creates, changes, index_changes, fk_changes, table_options_changes].flatten.reject(&:blank?) * "\n\n"
329
+ down = [undo_changes, undo_renames, undo_drops, undo_creates, undo_index_changes, undo_fk_changes, undo_table_options_changes].flatten.reject(&:blank?) * "\n\n"
317
330
 
318
331
  [up, down]
319
332
  end
320
333
 
321
334
  def create_table(model)
322
- longest_field_name = model.field_specs.values.map { |f| f.sql_type.to_s.length }.max
323
- disable_auto_increment = model.respond_to?(:disable_auto_increment) && model.disable_auto_increment
324
- primary_key_option =
325
- if model.primary_key.blank? || disable_auto_increment
326
- ", id: false"
327
- elsif model.primary_key == "id"
328
- ", id: :bigint"
329
- else
330
- ", primary_key: :#{model.primary_key}"
335
+ longest_field_name = model.field_specs.values.map { |f| f.sql_type.to_s.length }.max
336
+ disable_auto_increment = model.respond_to?(:disable_auto_increment) && model.disable_auto_increment
337
+ table_options_definition = ::DeclareSchema::Model::TableOptionsDefinition.new(model.table_name, table_options_for_model(model))
338
+ field_definitions = [
339
+ disable_auto_increment ? "t.integer :id, limit: 8, auto_increment: false, primary_key: true" : nil,
340
+ *(model.field_specs.values.sort_by(&:position).map { |f| create_field(f, longest_field_name) })
341
+ ].compact
342
+
343
+ <<~EOS.strip
344
+ create_table :#{model.table_name}, #{create_table_options(model, disable_auto_increment)} do |t|
345
+ #{field_definitions.join("\n")}
331
346
  end
332
- (["create_table :#{model.table_name}#{primary_key_option} do |t|"] +
333
- [(disable_auto_increment ? " t.integer :id, limit: 8, auto_increment: false, primary_key: true" : nil)] +
334
- model.field_specs.values.sort_by(&:position).map { |f| create_field(f, longest_field_name) } +
335
- ["end"] + (if Migrator.disable_indexing
336
- []
337
- else
338
- create_indexes(model) +
339
- create_constraints(model)
340
- end)).compact * "\n"
347
+
348
+ #{table_options_definition.alter_table_statement unless ActiveRecord::Base.connection.class.name.match?(/SQLite3Adapter/)}
349
+ #{create_indexes(model).join("\n") unless Migrator.disable_indexing}
350
+ #{create_constraints(model).join("\n") unless Migrator.disable_indexing}
351
+ EOS
352
+ end
353
+
354
+ def create_table_options(model, disable_auto_increment)
355
+ if model.primary_key.blank? || disable_auto_increment
356
+ "id: false"
357
+ elsif model.primary_key == "id"
358
+ "id: :bigint"
359
+ else
360
+ "primary_key: :#{model.primary_key}"
361
+ end
362
+ end
363
+
364
+ def table_options_for_model(model)
365
+ if ActiveRecord::Base.connection.class.name.match?(/SQLite3Adapter/)
366
+ {}
367
+ else
368
+ {
369
+ charset: model.table_options[:charset] || Migrator.default_charset,
370
+ collation: model.table_options[:collation] || Migrator.default_collation
371
+ }
372
+ end
341
373
  end
342
374
 
343
375
  def create_indexes(model)
@@ -351,7 +383,7 @@ module Generators
351
383
  def create_field(field_spec, field_name_width)
352
384
  options = fk_field_options(field_spec.model, field_spec.name).merge(field_spec.sql_options)
353
385
  args = [field_spec.name.inspect] + format_options(options, field_spec.sql_type)
354
- format(" t.%-*s %s", field_name_width, field_spec.sql_type, args.join(', '))
386
+ format("t.%-*s %s", field_name_width, field_spec.sql_type, args.join(', '))
355
387
  end
356
388
 
357
389
  def change_table(model, current_table_name)
@@ -413,15 +445,17 @@ module Generators
413
445
  col_name = old_names[c] || c
414
446
  col = db_columns[col_name]
415
447
  spec = model.field_specs[c]
416
- if spec.different_to?(col) # TODO: TECH-4814 DRY this up to a diff function that returns the differences. It's different if it has differences. -Colin
448
+ if spec.different_to?(current_table_name, col) # TODO: TECH-4814 DRY this up to a diff function that returns the differences. It's different if it has differences. -Colin
417
449
  change_spec = fk_field_options(model, c)
418
450
  change_spec[:limit] ||= spec.limit if (spec.sql_type != :text ||
419
451
  ::DeclareSchema::Model::FieldSpec.mysql_text_limits?) &&
420
452
  (spec.limit || col.limit)
421
- change_spec[:precision] = spec.precision unless spec.precision.nil?
422
- change_spec[:scale] = spec.scale unless spec.scale.nil?
423
- change_spec[:null] = spec.null unless spec.null && col.null
424
- change_spec[:default] = spec.default unless spec.default.nil? && col.default.nil?
453
+ change_spec[:precision] = spec.precision unless spec.precision.nil?
454
+ change_spec[:scale] = spec.scale unless spec.scale.nil?
455
+ change_spec[:null] = spec.null unless spec.null && col.null
456
+ change_spec[:default] = spec.default unless spec.default.nil? && col.default.nil?
457
+ change_spec[:collation] = spec.collation unless spec.collation.nil?
458
+ change_spec[:charset] = spec.charset unless spec.charset.nil?
425
459
 
426
460
  changes << "change_column :#{new_table_name}, :#{c}, " +
427
461
  ([":#{spec.sql_type}"] + format_options(change_spec, spec.sql_type, changing: true)).join(", ")
@@ -436,13 +470,20 @@ module Generators
436
470
  else
437
471
  change_foreign_key_constraints(model, current_table_name)
438
472
  end
473
+ table_options_changes, undo_table_options_changes = if ActiveRecord::Base.connection.class.name.match?(/mysql/i)
474
+ change_table_options(model, current_table_name)
475
+ else
476
+ [[], []]
477
+ end
439
478
 
440
479
  [(renames + adds + removes + changes) * "\n",
441
480
  (undo_renames + undo_adds + undo_removes + undo_changes) * "\n",
442
481
  index_changes * "\n",
443
482
  undo_index_changes * "\n",
444
483
  fk_changes * "\n",
445
- undo_fk_changes * "\n"]
484
+ undo_fk_changes * "\n",
485
+ table_options_changes * "\n",
486
+ undo_table_options_changes * "\n"]
446
487
  end
447
488
 
448
489
  def change_indexes(model, old_table_name)
@@ -552,6 +593,20 @@ module Generators
552
593
  end
553
594
  end
554
595
 
596
+ def change_table_options(model, current_table_name)
597
+ old_options_definition = ::DeclareSchema::Model::TableOptionsDefinition.for_model(model, current_table_name)
598
+ new_options_definition = ::DeclareSchema::Model::TableOptionsDefinition.new(model.table_name, table_options_for_model(model))
599
+
600
+ if old_options_definition.equivalent?(new_options_definition)
601
+ [[], []]
602
+ else
603
+ [
604
+ [new_options_definition.alter_table_statement],
605
+ [old_options_definition.alter_table_statement]
606
+ ]
607
+ end
608
+ end
609
+
555
610
  def revert_table(table)
556
611
  res = StringIO.new
557
612
  schema_dumper_klass = case Rails::VERSION::MAJOR
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe 'DeclareSchema Model FieldSpec' do
4
+ before do
5
+ load File.expand_path('prepare_testapp.rb', __dir__)
6
+ end
7
+
8
+ context 'There are no model columns to change' do
9
+ it '#different_to should return false for int8 == int8' do
10
+ subject = DeclareSchema::Model::FieldSpec.new(Object, :price, :integer, limit: 8, null: false, position: 0)
11
+
12
+ case Rails::VERSION::MAJOR
13
+ when 4
14
+ cast_type = ActiveRecord::Type::Integer.new(limit: 8)
15
+ col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, cast_type, "integer(8)", false)
16
+ else
17
+ sql_type_metadata = ActiveRecord::ConnectionAdapters::SqlTypeMetadata.new(sql_type: "integer(8)", type: :integer, limit: 8)
18
+ col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, sql_type_metadata, false, "adverts")
19
+ end
20
+
21
+ expect(subject.different_to?(subject.name, col)).to eq(false)
22
+ end
23
+
24
+ it '#different_to should return false for bigint == bigint' do
25
+ subject = DeclareSchema::Model::FieldSpec.new(Object, :price, :bigint, null: false, position: 0)
26
+
27
+ case Rails::VERSION::MAJOR
28
+ when 4
29
+ cast_type = ActiveRecord::Type::BigInteger.new(limit: 8)
30
+ col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, cast_type, "bigint(20)", false)
31
+ else
32
+ sql_type_metadata = ActiveRecord::ConnectionAdapters::SqlTypeMetadata.new(sql_type: "bigint(20)", type: :integer, limit: 8)
33
+ col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, sql_type_metadata, false, "adverts")
34
+ end
35
+
36
+ expect(subject.different_to?(subject.name, col)).to eq(false)
37
+ end
38
+
39
+ it '#different_to should return false for int8 == bigint' do
40
+ subject = DeclareSchema::Model::FieldSpec.new(Object, :price, :integer, limit: 8, null: false, position: 0)
41
+
42
+ case Rails::VERSION::MAJOR
43
+ when 4
44
+ cast_type = ActiveRecord::Type::BigInteger.new(limit: 8)
45
+ col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, cast_type, "bigint(20)", false)
46
+ else
47
+ sql_type_metadata = ActiveRecord::ConnectionAdapters::SqlTypeMetadata.new(sql_type: "bigint(20)", type: :integer, limit: 8)
48
+ col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, sql_type_metadata, false, "adverts")
49
+ end
50
+
51
+ expect(subject.different_to?(subject.name, col)).to eq(false)
52
+ end
53
+
54
+ it '#different_to should return false for bigint == int8' do
55
+ subject = DeclareSchema::Model::FieldSpec.new(Object, :price, :bigint, null: false, position: 0)
56
+
57
+ case Rails::VERSION::MAJOR
58
+ when 4
59
+ cast_type = ActiveRecord::Type::Integer.new(limit: 8)
60
+ col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, cast_type, "integer(8)", false)
61
+ else
62
+ sql_type_metadata = ActiveRecord::ConnectionAdapters::SqlTypeMetadata.new(sql_type: "integer(8)", type: :integer, limit: 8)
63
+ col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, sql_type_metadata, false, "adverts")
64
+ end
65
+
66
+ expect(subject.different_to?(subject.name, col)).to eq(false)
67
+ end
68
+ end
69
+ end
@@ -27,15 +27,28 @@ RSpec.describe 'DeclareSchema Migration Generator' do
27
27
  end
28
28
  EOS
29
29
 
30
- expect_test_definition_to_eq('alpha/beta', <<~EOS)
31
- require 'test_helper'
32
-
33
- class Alpha::BetaTest < ActiveSupport::TestCase
34
- # test "the truth" do
35
- # assert true
36
- # end
37
- end
38
- EOS
30
+ case Rails::VERSION::MAJOR
31
+ when 4, 5
32
+ expect_test_definition_to_eq('alpha/beta', <<~EOS)
33
+ require 'test_helper'
34
+
35
+ class Alpha::BetaTest < ActiveSupport::TestCase
36
+ # test "the truth" do
37
+ # assert true
38
+ # end
39
+ end
40
+ EOS
41
+ else
42
+ expect_test_definition_to_eq('alpha/beta', <<~EOS)
43
+ require "test_helper"
44
+
45
+ class Alpha::BetaTest < ActiveSupport::TestCase
46
+ # test "the truth" do
47
+ # assert true
48
+ # end
49
+ end
50
+ EOS
51
+ end
39
52
 
40
53
  case Rails::VERSION::MAJOR
41
54
  when 4
@@ -1093,4 +1093,29 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1093
1093
  expect(base_class).to eq("(Rails::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[4.2] : ActiveRecord::Migration)")
1094
1094
  end
1095
1095
  end
1096
+
1097
+ context 'Does not generate migrations' do
1098
+ it 'for aliased fields bigint -> integer limit 8' do
1099
+ if Rails::VERSION::MAJOR >= 5 || !ActiveRecord::Base.connection.class.name.match?(/SQLite3Adapter/)
1100
+ class Advert < active_record_base_class.constantize
1101
+ fields do
1102
+ price :bigint
1103
+ end
1104
+ end
1105
+
1106
+ generate_migrations '-n', '-m'
1107
+
1108
+ migrations = Dir.glob('db/migrate/*declare_schema_migration*.rb')
1109
+ expect(migrations.size).to eq(1), migrations.inspect
1110
+
1111
+ class Advert < active_record_base_class.constantize
1112
+ fields do
1113
+ price :integer, limit: 8
1114
+ end
1115
+ end
1116
+
1117
+ expect { generate_migrations '-n', '-g' }.to output("Database and models match -- nothing to change\n").to_stdout
1118
+ end
1119
+ end
1120
+ end
1096
1121
  end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_record/connection_adapters/mysql2_adapter'
4
+ require_relative '../../../../lib/declare_schema/model/table_options_definition'
5
+
6
+ RSpec.describe DeclareSchema::Model::TableOptionsDefinition do
7
+ before do
8
+ load File.expand_path('../prepare_testapp.rb', __dir__)
9
+
10
+ class TableOptionsDefinitionTestModel < ActiveRecord::Base
11
+ fields do
12
+ name :string, limit: 127, index: true
13
+ end
14
+ end
15
+ end
16
+
17
+ let(:model_class) { TableOptionsDefinitionTestModel }
18
+
19
+ context 'instance methods' do
20
+ let(:table_options) { { charset: "utf8", collation: "utf8_general"} }
21
+ let(:model) { described_class.new('table_options_definition_test_models', table_options) }
22
+
23
+ describe '#to_key' do
24
+ subject { model.to_key }
25
+ it { should eq(["table_options_definition_test_models", "{:charset=>\"utf8\", :collation=>\"utf8_general\"}"]) }
26
+ end
27
+
28
+ describe '#settings' do
29
+ subject { model.settings }
30
+ it { should eq("CHARACTER SET utf8 COLLATE utf8_general") }
31
+ end
32
+
33
+ describe '#hash' do
34
+ subject { model.hash }
35
+ it { should eq(["table_options_definition_test_models", "{:charset=>\"utf8\", :collation=>\"utf8_general\"}"].hash) }
36
+ end
37
+
38
+ describe '#to_s' do
39
+ subject { model.to_s }
40
+ it { should eq("CHARACTER SET utf8 COLLATE utf8_general") }
41
+ end
42
+
43
+ describe '#alter_table_statement' do
44
+ subject { model.alter_table_statement }
45
+ it { should eq('execute "ALTER TABLE \"table_options_definition_test_models\" CHARACTER SET utf8 COLLATE utf8_general;"') }
46
+ end
47
+ end
48
+
49
+
50
+ context 'class << self' do
51
+ describe '#for_model' do
52
+ context 'when using a SQLite connection' do
53
+ subject { described_class.for_model(model_class) }
54
+ it { should eq(described_class.new(model_class.table_name, {})) }
55
+ end
56
+ # TODO: Convert these tests to run against a MySQL database so that we can
57
+ # perform them without mocking out so much
58
+ context 'when using a MySQL connection' do
59
+ before do
60
+ double(ActiveRecord::ConnectionAdapters::Mysql2Adapter).tap do |stub_connection|
61
+ expect(stub_connection).to receive(:class).and_return(ActiveRecord::ConnectionAdapters::Mysql2Adapter)
62
+ expect(stub_connection).to receive(:current_database).and_return('test_database')
63
+ expect(stub_connection).to receive(:quote_string).with('test_database').and_return('test_database')
64
+ expect(stub_connection).to receive(:quote_string).with(model_class.table_name).and_return(model_class.table_name)
65
+ expect(stub_connection).to(
66
+ receive(:select_one).with(<<~EOS)
67
+ SELECT CCSA.character_set_name, CCSA.collation_name
68
+ FROM information_schema.`TABLES` T, information_schema.`COLLATION_CHARACTER_SET_APPLICABILITY` CCSA
69
+ WHERE CCSA.collation_name = T.table_collation AND
70
+ T.table_schema = 'test_database' AND
71
+ T.table_name = '#{model_class.table_name}';
72
+ EOS
73
+ .and_return({ "character_set_name" => "utf8", "collation_name" => "utf8_general" })
74
+ )
75
+ allow(model_class).to receive(:connection).and_return(stub_connection)
76
+ end
77
+ end
78
+
79
+ subject { described_class.for_model(model_class) }
80
+ it { should eq(described_class.new(model_class.table_name, { charset: "utf8", collation: "utf8_general" })) }
81
+ end
82
+ end
83
+ end
84
+ end
@@ -43,6 +43,34 @@ module Generators
43
43
  end
44
44
  end
45
45
 
46
+ describe '#default_charset' do
47
+ subject { described_class.default_charset }
48
+
49
+ context 'when not explicitly set' do
50
+ it { should eq(:utf8mb4) }
51
+ end
52
+
53
+ context 'when explicitly set' do
54
+ before { described_class.default_charset = :utf8 }
55
+ after { described_class.default_charset = described_class::DEFAULT_CHARSET }
56
+ it { should eq(:utf8) }
57
+ end
58
+ end
59
+
60
+ describe '#default_collation' do
61
+ subject { described_class.default_collation }
62
+
63
+ context 'when not explicitly set' do
64
+ it { should eq(:utf8mb4_general) }
65
+ end
66
+
67
+ context 'when explicitly set' do
68
+ before { described_class.default_collation = :utf8mb4_general_ci }
69
+ after { described_class.default_collation = described_class::DEFAULT_COLLATION }
70
+ it { should eq(:utf8mb4_general_ci) }
71
+ end
72
+ end
73
+
46
74
  describe 'load_rails_models' do
47
75
  before do
48
76
  expect(Rails.application).to receive(:eager_load!)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: declare_schema
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Invoca Development adapted from hobo_fields by Tom Locke
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-05 00:00:00.000000000 Z
11
+ date: 2020-12-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -32,13 +32,13 @@ executables:
32
32
  extensions: []
33
33
  extra_rdoc_files: []
34
34
  files:
35
- - ".dependabot/config.yml"
35
+ - ".github/dependabot.yml"
36
+ - ".github/workflows/declare_schema_build.yml"
36
37
  - ".github/workflows/gem_release.yml"
37
38
  - ".gitignore"
38
39
  - ".rspec"
39
40
  - ".rubocop.yml"
40
41
  - ".ruby-version"
41
- - ".travis.yml"
42
42
  - Appraisals
43
43
  - CHANGELOG.md
44
44
  - Gemfile
@@ -61,6 +61,7 @@ files:
61
61
  - lib/declare_schema/model/field_spec.rb
62
62
  - lib/declare_schema/model/foreign_key_definition.rb
63
63
  - lib/declare_schema/model/index_definition.rb
64
+ - lib/declare_schema/model/table_options_definition.rb
64
65
  - lib/declare_schema/railtie.rb
65
66
  - lib/declare_schema/version.rb
66
67
  - lib/generators/declare_schema/migration/USAGE
@@ -74,10 +75,12 @@ files:
74
75
  - lib/generators/declare_schema/support/thor_shell.rb
75
76
  - spec/lib/declare_schema/api_spec.rb
76
77
  - spec/lib/declare_schema/field_declaration_dsl_spec.rb
78
+ - spec/lib/declare_schema/field_spec_spec.rb
77
79
  - spec/lib/declare_schema/generator_spec.rb
78
80
  - spec/lib/declare_schema/interactive_primary_key_spec.rb
79
81
  - spec/lib/declare_schema/migration_generator_spec.rb
80
82
  - spec/lib/declare_schema/model/index_definition_spec.rb
83
+ - spec/lib/declare_schema/model/table_options_definition_spec.rb
81
84
  - spec/lib/declare_schema/prepare_testapp.rb
82
85
  - spec/lib/generators/declare_schema/migration/migrator_spec.rb
83
86
  - spec/spec_helper.rb
@@ -87,7 +90,7 @@ homepage: https://github.com/Invoca/declare_schema
87
90
  licenses: []
88
91
  metadata:
89
92
  allowed_push_host: https://rubygems.org
90
- post_install_message:
93
+ post_install_message:
91
94
  rdoc_options: []
92
95
  require_paths:
93
96
  - lib
@@ -103,7 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
103
106
  version: 1.3.6
104
107
  requirements: []
105
108
  rubygems_version: 3.0.3
106
- signing_key:
109
+ signing_key:
107
110
  specification_version: 4
108
111
  summary: Database migration generator for Rails
109
112
  test_files: []
@@ -1,10 +0,0 @@
1
- ---
2
- version: 1
3
- update_configs:
4
- - package_manager: "ruby:bundler"
5
- directory: "/"
6
- update_schedule: "weekly"
7
- version_requirement_updates: "off"
8
- commit_message:
9
- prefix: "No-Jira"
10
- include_scope: true
@@ -1,37 +0,0 @@
1
- ---
2
- dist: trusty
3
- os: linux
4
- language: ruby
5
- cache: bundler
6
- rvm:
7
- - 2.4.5
8
- - 2.5.8
9
- - 2.6.5
10
- - 2.7.1
11
- - ruby-head
12
- gemfile:
13
- - gemfiles/rails_4.gemfile
14
- - gemfiles/rails_5.gemfile
15
- - gemfiles/rails_6.gemfile
16
- jobs:
17
- fast_finish: false
18
- exclude:
19
- - gemfile: gemfiles/rails_4.gemfile
20
- rvm: 2.7.1
21
- - gemfile: gemfiles/rails_5.gemfile
22
- rvm: 2.4.5
23
- - gemfile: gemfiles/rails_6.gemfile
24
- rvm: 2.4.5
25
- allow_failures:
26
- - rvm: ruby-head
27
- before_install:
28
- - rm -f /home/travis/.rvm/rubies/ruby-2.*/lib/ruby/gems/2.*/specifications/default/bundler-2.*.gemspec
29
- - echo y | rvm @global do gem install bundler -v 1.17.3 --force --default
30
- - gem install bundler -v 1.17.3 --force --default
31
- - gem install bundler -v 1.17.3
32
- install:
33
- - bundle --version
34
- - bundle install --jobs=3 --retry=3 --path=${BUNDLE_PATH:-vendor/bundle}
35
- script:
36
- - bundle exec rake test:prepare_testapp[force]
37
- - bundle exec rake test:all < test_responses.txt