declare_schema 0.1.0 → 0.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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +37 -0
  3. data/CHANGELOG.md +28 -4
  4. data/Gemfile +0 -2
  5. data/Gemfile.lock +1 -4
  6. data/README.md +59 -2
  7. data/Rakefile +13 -20
  8. data/gemfiles/rails_4.gemfile +4 -7
  9. data/gemfiles/rails_5.gemfile +4 -7
  10. data/gemfiles/rails_6.gemfile +4 -7
  11. data/lib/declare_schema/model.rb +0 -1
  12. data/lib/declare_schema/model/field_spec.rb +4 -14
  13. data/lib/declare_schema/version.rb +1 -1
  14. data/lib/generators/declare_schema/migration/migration_generator.rb +20 -13
  15. data/lib/generators/declare_schema/migration/migrator.rb +58 -38
  16. data/lib/generators/declare_schema/migration/templates/migration.rb.erb +1 -1
  17. data/lib/generators/declare_schema/support/eval_template.rb +12 -3
  18. data/lib/generators/declare_schema/support/model.rb +77 -2
  19. data/spec/lib/declare_schema/api_spec.rb +125 -0
  20. data/spec/lib/declare_schema/field_declaration_dsl_spec.rb +8 -4
  21. data/spec/lib/declare_schema/generator_spec.rb +57 -0
  22. data/spec/lib/declare_schema/interactive_primary_key_spec.rb +51 -0
  23. data/spec/lib/declare_schema/migration_generator_spec.rb +686 -0
  24. data/spec/lib/declare_schema/prepare_testapp.rb +29 -0
  25. data/spec/lib/generators/declare_schema/migration/migrator_spec.rb +42 -0
  26. data/spec/spec_helper.rb +26 -0
  27. metadata +9 -12
  28. data/.jenkins/Jenkinsfile +0 -72
  29. data/.jenkins/ruby_build_pod.yml +0 -19
  30. data/lib/generators/declare_schema/model/templates/model_injection.rb.erb +0 -25
  31. data/test/api.rdoctest +0 -136
  32. data/test/doc-only.rdoctest +0 -76
  33. data/test/generators.rdoctest +0 -60
  34. data/test/interactive_primary_key.rdoctest +0 -56
  35. data/test/migration_generator.rdoctest +0 -846
  36. data/test/migration_generator_comments.rdoctestDISABLED +0 -74
  37. data/test/prepare_testapp.rb +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5cf5ebc856041d2f6a90e4a6f30a56e5a538545f79b227cd2ca691eb99dcf9a8
4
- data.tar.gz: 3d2b3efe4d0647f8c94052e2e8a22433a021503f458203e9f0f73d131d7c6225
3
+ metadata.gz: 3f3116a6fbb5a47de5809f3f813c88783284bad601452679fa59784f3598834b
4
+ data.tar.gz: 8f4b6fee7b4d17e5b644f32a4b624a3f77526f91826a8c0b82d61b6e25130332
5
5
  SHA512:
6
- metadata.gz: 4771090d9ef1dbe0267eddfa4ac7d2fc25dd37a9c75a8e76bdb27ea9a072aac894671dc8115387eb9489855f6849ff7cf4c1f2f4e82eb36039824fd83328f2f3
7
- data.tar.gz: 7fc9feb7d02f2b71f11ec4c21f3624c3dc503df64c443f304b1d19f75d6a81102a86d0b27be3c32749a191f966440a88c54c86db260123cd2e6457bdacd474cf
6
+ metadata.gz: b833000d28d64e7856de05c9ae822c88dcceeb7861f777f13177ea8017e56bf937aba42b9da14ae1ce4810fd275c5462cb08c18c32839255ab46f1de116eee1d
7
+ data.tar.gz: c41c8cbdafd96eeb92fcf5c646ff9d18f4ce2374f06ecc6977015fa8406bc4639ab3722354212d1a75274c5af982f10b6c2f4c838de94f4b9436da20f836d5d3
@@ -0,0 +1,37 @@
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
@@ -1,11 +1,35 @@
1
- # CHANGELOG for `declarative_schema`
1
+ # CHANGELOG for `declare_schema`
2
2
 
3
3
  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.1.0] - Unreleased
7
+ ## [0.2.0] - 2020-10-26
8
8
  ### Added
9
- - Initial version from https://github.com/Invoca/declare_schema v4.0.0.
9
+ - Automatically eager_load! all Rails::Engines before generating migrations.
10
10
 
11
- [0.1.0]: https://github.com/Invoca/declarative_schema/tree/v0.1.0
11
+ ### Changed
12
+ - Changed tests from rdoctest to rspec.
13
+
14
+ ### Fixed
15
+ - Fixed a bug where `:text limit: 0xffff_ffff` (max size) was omitted from migrations.
16
+ - Fixed a bug where `:bigint` foreign keys were omitted from the migration.
17
+
18
+ ## [0.1.3] - 2020-10-08
19
+ ### Changed
20
+ - Updated the `always_ignore_tables` list in `Migrator` to access Rails metadata table names
21
+ using the appropriate Rails configuration attributes.
22
+
23
+ ## [0.1.2] - 2020-09-29
24
+ ### Changed
25
+ - Added travis support and created 2 specs as a starting point.
26
+
27
+
28
+ ## [0.1.1] - 2020-09-24
29
+ ### Added
30
+ - Initial version from https://github.com/Invoca/hobo_fields v4.1.0.
31
+
32
+ [0.2.0]: https://github.com/Invoca/declare_schema/compare/v0.1.3...v0.2.0
33
+ [0.1.3]: https://github.com/Invoca/declare_schema/compare/v0.1.2...v0.1.3
34
+ [0.1.2]: https://github.com/Invoca/declare_schema/compare/v0.1.1...v0.1.2
35
+ [0.1.1]: https://github.com/Invoca/declare_schema/tree/v0.1.1
data/Gemfile CHANGED
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  source 'https://rubygems.org'
4
- source 'https://gem.fury.io/invoca'
5
4
 
6
5
  gemspec
7
6
 
@@ -19,6 +18,5 @@ gem 'rails', '~> 5.2', '>= 5.2.4.3'
19
18
  gem 'responders'
20
19
  gem 'rspec'
21
20
  gem 'rubocop'
22
- gem 'rubydoctest'
23
21
  gem 'sqlite3'
24
22
  gem 'yard'
@@ -1,12 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- declare_schema (0.1.0)
4
+ declare_schema (0.2.0)
5
5
  rails (>= 4.2)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
- remote: https://gem.fury.io/invoca/
10
9
  specs:
11
10
  actioncable (5.2.4.4)
12
11
  actionpack (= 5.2.4.4)
@@ -160,7 +159,6 @@ GEM
160
159
  rubocop-ast (0.4.2)
161
160
  parser (>= 2.7.1.4)
162
161
  ruby-progressbar (1.10.1)
163
- rubydoctest (1.1.5)
164
162
  sprockets (4.0.2)
165
163
  concurrent-ruby (~> 1.0)
166
164
  rack (> 1, < 3)
@@ -195,7 +193,6 @@ DEPENDENCIES
195
193
  responders
196
194
  rspec
197
195
  rubocop
198
- rubydoctest
199
196
  sqlite3
200
197
  yard
201
198
 
data/README.md CHANGED
@@ -1,11 +1,68 @@
1
1
  # DeclareSchema
2
2
 
3
- Declare your active_record model schemas and have database migrations generated for you!
3
+ Declare your Rails/active_record model schemas and have database migrations generated for you!
4
4
 
5
+ ## Example
6
+
7
+ Make a model and declare your schema within a `fields do ... end` block:
8
+ ```ruby
9
+ class Company < ActiveRecord::Base
10
+ fields do
11
+ company_name :string, limit: 100
12
+ ticker_symbol :string, limit: 4, null: true, index: true, unique: true
13
+ employee_count :integer
14
+ comments :text
15
+
16
+ timestamps
17
+ end
18
+
19
+ belongs_to :industry
20
+ end
21
+ ```
22
+ Then generate the migration:
23
+ ```sh
24
+ $ rails generate declare_schema:migration
25
+
26
+ ---------- Up Migration ----------
27
+ create_table :companies, id: :bigint do |t|
28
+ t.string :company_name, null: false, limit: 100
29
+ t.string :ticker_symbol, limit: 4
30
+ t.integer :employee_count, null: false
31
+ t.text :comments, null: false
32
+ t.datetime :created_at
33
+ t.datetime :updated_at
34
+ t.integer :industry_id, null: false
35
+ end
36
+ add_index :companies, [:ticker_symbol], unique: true, name: 'on_ticker_symbol'
37
+ add_index :companies, [:industry_id], name: 'on_industry_id'
38
+ execute "ALTER TABLE companies ADD CONSTRAINT index_companies_on_industry_id FOREIGN KEY index_companies_on_industry_id(industry_id) REFERENCES industries(id) "
39
+ ----------------------------------
40
+
41
+ ---------- Down Migration --------
42
+ drop_table :companies
43
+ ----------------------------------
44
+
45
+
46
+ What now: [g]enerate migration, generate and [m]igrate now or [c]ancel? g
47
+ => "g"
48
+
49
+ Migration filename: [<enter>=declare_schema_migration_1|<custom_name>]: add_company_model
50
+ ```
51
+ Note that the migration generator is interactive -- it can't tell the difference between renaming something vs. adding one thing and removing another, so sometimes it will ask you to clarify.
52
+
53
+ ## Installing
54
+
55
+ Install the `DeclareSchema` gem directly:
56
+ ```
57
+ $ gem install declare_schema
58
+ ```
59
+ or add it to your `bundler` Gemfile:
60
+ ```
61
+ gem 'declare_schema'
62
+ ```
5
63
  ## Testing
6
64
  To run tests:
7
65
  ```
8
66
  rake test:prepare_testapp[force]
9
67
  rake test:all < test_responses.txt
10
68
  ```
11
- (Note: there currently are no unit tests. The above will run the `rdoctests`.)
data/Rakefile CHANGED
@@ -14,7 +14,6 @@ $LOAD_PATH.unshift File.expand_path('lib', __dir__)
14
14
  require 'declare_schema'
15
15
 
16
16
  RUBY = 'ruby'
17
- RUBYDOCTEST = ENV['RUBYDOCTEST'] || "#{RUBY} -S rubydoctest"
18
17
  GEM_ROOT = __dir__
19
18
  TESTAPP_PATH = ENV['TESTAPP_PATH'] || File.join(Dir.tmpdir, 'declare_schema_testapp')
20
19
  BIN = File.expand_path('bin/declare_schema', __dir__)
@@ -24,13 +23,7 @@ task default: 'test:all'
24
23
  include Rake::DSL
25
24
 
26
25
  namespace "test" do
27
- task all: [:doctest, :spec]
28
-
29
- desc "Run the doctests"
30
- task :doctest do |_t|
31
- files = Dir['test/*.rdoctest'].sort.map { |f| File.expand_path(f) }.join(' ')
32
- system("#{RUBYDOCTEST} #{files}") or exit(1)
33
- end
26
+ task all: :spec
34
27
 
35
28
  desc "Prepare a rails application for testing"
36
29
  task :prepare_testapp, :force do |_t, args|
@@ -38,19 +31,19 @@ namespace "test" do
38
31
  FileUtils.remove_entry_secure(TESTAPP_PATH, true)
39
32
  sh %(#{BIN} new #{TESTAPP_PATH} --skip-wizard --skip-bundle)
40
33
  FileUtils.chdir TESTAPP_PATH
41
- sh %(bundle install)
42
- sh %(echo "" >> Gemfile)
43
- sh %(echo "gem 'irt', :group => :development" >> Gemfile) # to make the bundler happy
44
- sh %(echo "gem 'therubyracer'" >> Gemfile)
45
- sh %(echo "gem 'kramdown'" >> Gemfile)
46
- sh %(echo "" > app/models/.gitignore) # because git reset --hard would rm the dir
47
- rm %(.gitignore) # we need to reset everything in a testapp
48
- sh %(git init && git add . && git commit -m "initial commit")
49
- puts %(The testapp has been created in '#{TESTAPP_PATH}')
34
+ sh "bundle install"
35
+ sh "(echo '';
36
+ echo \"gem 'irt', :group => :development\";
37
+ echo \"gem 'therubyracer'\";
38
+ echo \"gem 'kramdown'\") > Gemfile"
39
+ sh "echo '' > app/models/.gitignore" # because git reset --hard would rm the dir
40
+ rm ".gitignore" # we need to reset everything in a testapp
41
+ sh "git init && git add . && git commit -m \"initial commit\""
42
+ puts "The testapp has been created in '#{TESTAPP_PATH}'"
50
43
  else
51
- FileUtils.chdir TESTAPP_PATH
52
- sh %(git add .)
53
- sh %(git reset --hard -q HEAD)
44
+ FileUtils.chdir(TESTAPP_PATH)
45
+ sh "git add ."
46
+ sh "git reset --hard -q HEAD"
54
47
  end
55
48
  end
56
49
  end
@@ -1,25 +1,22 @@
1
- # frozen_string_literal: true
2
-
3
1
  # This file was generated by Appraisal
4
2
 
5
3
  source "https://rubygems.org"
6
- source "https://gem.fury.io/invoca"
7
4
 
8
5
  gem "appraisal"
6
+ gem "bundler", "< 2"
7
+ gem "climate_control", "~> 0.2"
9
8
  gem "pry"
10
9
  gem "pry-byebug"
11
10
  gem "rails", "~> 4.2"
12
11
  gem "responders"
13
- gem "rubydoctest"
12
+ gem "rspec"
13
+ gem "rubocop"
14
14
  gem "sqlite3", "~> 1.3.0"
15
- gem "test_overrides"
16
15
  gem "yard"
17
16
 
18
17
  group :testapp do
19
18
  gem "bootsnap", ">= 1.1.0", require: false
20
- gem "kramdown"
21
19
  gem "listen"
22
- gem "RedCloth"
23
20
  end
24
21
 
25
22
  gemspec path: "../"
@@ -1,25 +1,22 @@
1
- # frozen_string_literal: true
2
-
3
1
  # This file was generated by Appraisal
4
2
 
5
3
  source "https://rubygems.org"
6
- source "https://gem.fury.io/invoca"
7
4
 
8
5
  gem "appraisal"
6
+ gem "bundler", "< 2"
7
+ gem "climate_control", "~> 0.2"
9
8
  gem "pry"
10
9
  gem "pry-byebug"
11
10
  gem "rails", "~> 5.2"
12
11
  gem "responders"
13
- gem "rubydoctest"
12
+ gem "rspec"
13
+ gem "rubocop"
14
14
  gem "sqlite3"
15
- gem "test_overrides"
16
15
  gem "yard"
17
16
 
18
17
  group :testapp do
19
18
  gem "bootsnap", ">= 1.1.0", require: false
20
- gem "kramdown"
21
19
  gem "listen"
22
- gem "RedCloth"
23
20
  end
24
21
 
25
22
  gemspec path: "../"
@@ -1,25 +1,22 @@
1
- # frozen_string_literal: true
2
-
3
1
  # This file was generated by Appraisal
4
2
 
5
3
  source "https://rubygems.org"
6
- source "https://gem.fury.io/invoca"
7
4
 
8
5
  gem "appraisal"
6
+ gem "bundler", "< 2"
7
+ gem "climate_control", "~> 0.2"
9
8
  gem "pry"
10
9
  gem "pry-byebug"
11
10
  gem "rails", "~> 6.0"
12
11
  gem "responders"
13
- gem "rubydoctest"
12
+ gem "rspec"
13
+ gem "rubocop"
14
14
  gem "sqlite3"
15
- gem "test_overrides"
16
15
  gem "yard"
17
16
 
18
17
  group :testapp do
19
18
  gem "bootsnap", ">= 1.1.0", require: false
20
- gem "kramdown"
21
19
  gem "listen"
22
- gem "RedCloth"
23
20
  end
24
21
 
25
22
  gemspec path: "../"
@@ -117,7 +117,6 @@ module DeclareSchema
117
117
  end
118
118
  column_options = {}
119
119
  column_options[:null] = options.delete(:null) || false
120
- column_options[:comment] = options.delete(:comment) if options.has_key?(:comment)
121
120
  column_options[:default] = options.delete(:default) if options.has_key?(:default)
122
121
  column_options[:limit] = options.delete(:limit) if options.has_key?(:limit)
123
122
 
@@ -41,7 +41,8 @@ module DeclareSchema
41
41
 
42
42
  @model = model
43
43
  @name = name.to_sym
44
- @type = type.is_a?(String) ? type.to_sym : type
44
+ type.is_a?(Symbol) or raise ArgumentError, "type must be a Symbol; got #{type.inspect}"
45
+ @type = type
45
46
  position_option = options.delete(:position)
46
47
  @options = options
47
48
 
@@ -52,7 +53,7 @@ module DeclareSchema
52
53
  @options[:limit] = self.class.round_up_mysql_text_limit(@options[:limit] || MYSQL_LONGTEXT_LIMIT)
53
54
  end
54
55
  when :string
55
- @options[:limit] or raise "limit must be given for :string field #{model}##{@name}: #{@options.inspect}; do you want 255?"
56
+ @options[:limit] or raise "limit must be given for :string field #{model}##{@name}: #{@options.inspect}; do you want `limit: 255`?"
56
57
  end
57
58
  @position = position_option || model.field_specs.length
58
59
  end
@@ -72,7 +73,7 @@ module DeclareSchema
72
73
  type
73
74
  else
74
75
  field_class = DeclareSchema.to_class(type)
75
- field_class && field_class::COLUMN_TYPE or raise UnknownSqlTypeError, "#{type.inspect} for #{model}.#{@name}"
76
+ field_class && field_class::COLUMN_TYPE or raise UnknownSqlTypeError, "#{type.inspect} for #{model}##{@name}"
76
77
  end
77
78
  end
78
79
  end
@@ -101,10 +102,6 @@ module DeclareSchema
101
102
  @options[:default]
102
103
  end
103
104
 
104
- def comment
105
- @options[:comment]
106
- end
107
-
108
105
  def same_type?(col_spec)
109
106
  type = sql_type
110
107
  normalized_type = TYPE_SYNONYMS[type] || type
@@ -114,13 +111,6 @@ module DeclareSchema
114
111
 
115
112
  def different_to?(col_spec)
116
113
  !same_type?(col_spec) ||
117
- # we should be able to use col_spec.comment, but col_spec has
118
- # a nil table_name for some strange reason.
119
- (model.table_exists? &&
120
- ActiveRecord::Base.respond_to?(:column_comment) &&
121
- !(col_comment = ActiveRecord::Base.column_comment(col_spec.name, model.table_name)).nil? &&
122
- col_comment != comment
123
- ) ||
124
114
  begin
125
115
  native_type = native_types[type]
126
116
  check_attributes = [:null, :default]
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DeclareSchema
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
@@ -3,6 +3,7 @@
3
3
  require 'rails/generators/migration'
4
4
  require 'rails/generators/active_record'
5
5
  require 'generators/declare_schema/support/thor_shell'
6
+ require 'declare_schema/model/field_spec'
6
7
 
7
8
  module DeclareSchema
8
9
  class MigrationGenerator < Rails::Generators::Base
@@ -85,7 +86,7 @@ module DeclareSchema
85
86
  @down = down
86
87
  @migration_class_name = final_migration_name.camelize
87
88
 
88
- migration_template 'migration.rb.erb', "db/migrate/#{final_migration_name.underscore}.rb"
89
+ migration_template('migration.rb.erb', "db/migrate/#{final_migration_name.underscore}.rb")
89
90
  if action == 'm'
90
91
  case Rails::VERSION::MAJOR
91
92
  when 4
@@ -117,14 +118,13 @@ module DeclareSchema
117
118
  ActiveRecord::Migrator.new(:up, migrations, ActiveRecord::SchemaMigration).pending_migrations
118
119
  end
119
120
 
120
- if pending_migrations.any?
121
- say "You have #{pending_migrations.size} pending migration#{'s' if pending_migrations.size > 1}:"
122
- pending_migrations.each do |pending_migration|
123
- say format(' %4d %s', pending_migration.version, pending_migration.name)
121
+ pending_migrations.any?.tap do |any|
122
+ if any
123
+ say "You have #{pending_migrations.size} pending migration#{'s' if pending_migrations.size > 1}:"
124
+ pending_migrations.each do |pending_migration|
125
+ say format(' %4d %s', pending_migration.version, pending_migration.name)
126
+ end
124
127
  end
125
- true
126
- else
127
- false
128
128
  end
129
129
  end
130
130
 
@@ -138,10 +138,10 @@ module DeclareSchema
138
138
  loop do
139
139
  if rename_to_choices.empty?
140
140
  say "\nCONFIRM DROP! #{kind_str} #{name_prefix}#{t}"
141
- resp = ask("Enter 'drop #{t}' to confirm or press enter to keep:")
142
- if resp.strip == "drop #{t}"
141
+ resp = ask("Enter 'drop #{t}' to confirm or press enter to keep:").strip
142
+ if resp == "drop #{t}"
143
143
  break
144
- elsif resp.strip.empty?
144
+ elsif resp.empty?
145
145
  to_drop.delete(t)
146
146
  break
147
147
  else
@@ -150,8 +150,7 @@ module DeclareSchema
150
150
  else
151
151
  say "\nDROP, RENAME or KEEP?: #{kind_str} #{name_prefix}#{t}"
152
152
  say "Rename choices: #{to_create * ', '}"
153
- resp = ask "Enter either 'drop #{t}' or one of the rename choices or press enter to keep:"
154
- resp = resp.strip
153
+ resp = ask("Enter either 'drop #{t}' or one of the rename choices or press enter to keep:").strip
155
154
 
156
155
  if resp == "drop #{t}"
157
156
  # Leave things as they are
@@ -182,3 +181,11 @@ module DeclareSchema
182
181
  end
183
182
  end
184
183
  end
184
+
185
+ module Generators
186
+ module DeclareSchema
187
+ module Migration
188
+ MigrationGenerator = ::DeclareSchema::MigrationGenerator
189
+ end
190
+ end
191
+ end