declare_schema 0.3.0.pre.2 → 0.3.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: 3364c39b6579bb69804417a10b5b287208e6fdfe5a23bf57b6b3f928f69fe539
4
- data.tar.gz: 2fbc6abab32d750ef1af34d6888b5954ee27da2563acd8595728d3d23d184244
3
+ metadata.gz: f3ae0814480b116b32a822887c83612b33458cc910384ae0c2122e547757f141
4
+ data.tar.gz: 133b7bd6d7d91dae9320a4e8002a8591e43ebb97f57013cbe266cef40a169088
5
5
  SHA512:
6
- metadata.gz: 7e884c085c0d72f1146d7b7f52abbf1f44b19389e2f96e2858b855b11041c94406b0be159a300366d0abeec2f36cf9056d3eddd61352600c780a992ca3971817
7
- data.tar.gz: 1d45f652bd8d0de74b71fec913c4005be8f3212de7fa7942ad587d67059f67115ce8d797be9d71121e792ab66aee84c2adaaa013766b6d96cb21eda1d35522b4
6
+ metadata.gz: 77b840eb5feb07d38c4fd96f4212d4c81f19c61a2aa2b4bbffb4f4f11594ba55c30e65ca4b77a68e7b29448f7762dba52782f1845307c5bbc02f7603f080c2e8
7
+ data.tar.gz: 2f85affbd44a6973595883afa01766ede6c950a70c4e783f3064e5c2a59ec5c71a3731d7d484bab133c18c698584077e2c14a8b98c81ce024e2e55bae59dabba
@@ -4,10 +4,19 @@ 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.3.0] - Unreleased
7
+ ## [0.3.0] - 2020-11-02
8
8
  ### Added
9
+ - Added support for `belongs_to optional:`.
10
+ If given, it is passed through to `ActiveRecord`'s `belong_to`.
11
+ If not given in Rails 5+, the `optional:` value is set equal to the `null:` value (default: `false`) and that
12
+ is passed to `ActiveRecord`'s `belong_to`.
13
+ Similarly, if `null:` is not given, it is inferred from `optional:`.
14
+ If both are given, their values are respected, even if contradictory;
15
+ this is a legitimate case when migrating to/from an optional association.
9
16
  - Added a new callback `before_generating_migration` to the `Migrator` that can be
10
17
  defined in order to custom load more models that might be missed by `eager_load!`
18
+ ### Fixed
19
+ - Migrations are now generated where the `[4.2]` is only applied after `ActiveRecord::Migration` in Rails 5+ (since Rails 4 didn't know about that notation).
11
20
 
12
21
  ## [0.2.0] - 2020-10-26
13
22
  ### Added
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- declare_schema (0.3.0.pre.2)
4
+ declare_schema (0.3.0)
5
5
  rails (>= 4.2)
6
6
 
7
7
  GEM
@@ -106,17 +106,14 @@ module DeclareSchema
106
106
  end
107
107
 
108
108
  # Extend belongs_to so that it creates a FieldSpec for the foreign key
109
- def belongs_to(name, *args, &block)
110
- if args.size == 0 || (args.size == 1 && args[0].is_a?(Proc))
111
- options = {}
112
- args.push(options)
113
- elsif args.size == 1
114
- options = args[0]
115
- else
116
- options = args[1]
117
- end
109
+ def belongs_to(name, scope = nil, **options, &block)
118
110
  column_options = {}
119
- column_options[:null] = options.delete(:null) || false
111
+
112
+ column_options[:null] = if options.has_key?(:null)
113
+ options.delete(:null)
114
+ elsif options.has_key?(:optional)
115
+ options[:optional] # infer :null from :optional
116
+ end || false
120
117
  column_options[:default] = options.delete(:default) if options.has_key?(:default)
121
118
  column_options[:limit] = options.delete(:limit) if options.has_key?(:limit)
122
119
 
@@ -129,20 +126,27 @@ module DeclareSchema
129
126
  fk_options[:constraint_name] = options.delete(:constraint) if options.has_key?(:constraint)
130
127
  fk_options[:index_name] = index_options[:name]
131
128
 
129
+ fk = options[:foreign_key]&.to_s || "#{name}_id"
130
+
131
+ if !options.has_key?(:optional) && Rails::VERSION::MAJOR >= 5
132
+ options[:optional] = column_options[:null] # infer :optional from :null
133
+ end
134
+
132
135
  fk_options[:dependent] = options.delete(:far_end_dependent) if options.has_key?(:far_end_dependent)
133
- super(name, *args, &block).tap do |_bt|
134
- refl = reflections[name.to_s] or raise "Couldn't find reflection #{name} in #{reflections.keys}"
135
- fkey = refl.foreign_key
136
- declare_field(fkey.to_sym, :integer, column_options)
137
- if refl.options[:polymorphic]
138
- foreign_type = options[:foreign_type] || "#{name}_type"
139
- declare_polymorphic_type_field(foreign_type, column_options)
140
- index([foreign_type, fkey], index_options) if index_options[:name] != false
141
- else
142
- index(fkey, index_options) if index_options[:name] != false
143
- options[:constraint_name] = options
144
- constraint(fkey, fk_options) if fk_options[:constraint_name] != false
145
- end
136
+
137
+ super(name, scope, options)
138
+
139
+ refl = reflections[name.to_s] or raise "Couldn't find reflection #{name} in #{reflections.keys}"
140
+ fkey = refl.foreign_key or raise "Couldn't find foreign_key for #{name} in #{refl.inspect}"
141
+ declare_field(fkey.to_sym, :integer, column_options)
142
+ if refl.options[:polymorphic]
143
+ foreign_type = options[:foreign_type] || "#{name}_type"
144
+ declare_polymorphic_type_field(foreign_type, column_options)
145
+ index([foreign_type, fkey], index_options) if index_options[:name] != false
146
+ else
147
+ index(fkey, index_options) if index_options[:name] != false
148
+ options[:constraint_name] = options
149
+ constraint(fkey, fk_options) if fk_options[:constraint_name] != false
146
150
  end
147
151
  end
148
152
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DeclareSchema
4
- VERSION = "0.3.0.pre.2"
4
+ VERSION = "0.3.0"
5
5
  end
@@ -1,4 +1,4 @@
1
- class <%= @migration_class_name %> < ActiveRecord::Migration<%= ('[4.2]' if Rails::VERSION::MAJOR >= 5) %>
1
+ class <%= @migration_class_name %> < (Rails::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[4.2] : ActiveRecord::Migration)
2
2
  def self.up
3
3
  <%= @up %>
4
4
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'rails'
4
+
3
5
  RSpec.describe 'DeclareSchema Migration Generator' do
4
6
  before do
5
7
  load File.expand_path('prepare_testapp.rb', __dir__)
@@ -53,7 +55,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
53
55
 
54
56
  add_index :adverts, [:id], unique: true, name: 'PRIMARY_KEY'
55
57
  EOS
56
- # TODO: ^ add_index should not be there?
58
+ # TODO: ^ TECH-4975 add_index should not be there
57
59
 
58
60
  expect(down).to eq(<<~EOS.strip)
59
61
  remove_column :adverts, :body
@@ -129,7 +131,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
129
131
  end
130
132
  end
131
133
 
132
- up, down = Generators::DeclareSchema::Migration::Migrator.run
134
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
133
135
  expect(up).to eq("add_column :adverts, :price, :integer, limit: 2")
134
136
 
135
137
  # Now run the migration, then change the limit:
@@ -154,7 +156,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
154
156
  end
155
157
  end
156
158
 
157
- up, down = Generators::DeclareSchema::Migration::Migrator.run
159
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
158
160
  expect(up).to eq("add_column :adverts, :price, :decimal")
159
161
 
160
162
  # Limits are generally not needed for `text` fields, because by default, `text` fields will use the maximum size
@@ -170,7 +172,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
170
172
  end
171
173
  end
172
174
 
173
- up, down = Generators::DeclareSchema::Migration::Migrator.run
175
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
174
176
  expect(up).to eq(<<~EOS.strip)
175
177
  add_column :adverts, :price, :decimal
176
178
  add_column :adverts, :notes, :text, null: false
@@ -194,7 +196,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
194
196
  end
195
197
  end
196
198
 
197
- up, down = Generators::DeclareSchema::Migration::Migrator.run
199
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
198
200
  expect(up).to eq(<<~EOS.strip)
199
201
  add_column :adverts, :notes, :text, null: false, limit: 4294967295
200
202
  add_column :adverts, :description, :text, null: false, limit: 255
@@ -266,7 +268,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
266
268
  end
267
269
  end
268
270
 
269
- up, down = Generators::DeclareSchema::Migration::Migrator.run
271
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
270
272
  ActiveRecord::Migration.class_eval up
271
273
  Advert.connection.schema_cache.clear!
272
274
  Advert.reset_column_information
@@ -278,6 +280,9 @@ RSpec.describe 'DeclareSchema Migration Generator' do
278
280
 
279
281
  class Category < ActiveRecord::Base; end
280
282
  class Advert < ActiveRecord::Base
283
+ fields do
284
+ name :string, limit: 255, null: true
285
+ end
281
286
  belongs_to :category
282
287
  end
283
288
 
@@ -298,9 +303,10 @@ RSpec.describe 'DeclareSchema Migration Generator' do
298
303
 
299
304
  class Category < ActiveRecord::Base; end
300
305
  class Advert < ActiveRecord::Base
306
+ fields { }
301
307
  belongs_to :category, foreign_key: "c_id", class_name: 'Category'
302
308
  end
303
- up, down = Generators::DeclareSchema::Migration::Migrator.run
309
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
304
310
  expect(up.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
305
311
  add_column :adverts, :c_id, :integer, limit: 8, null: false
306
312
  add_index :adverts, [:c_id], name: 'on_c_id'
@@ -313,9 +319,10 @@ RSpec.describe 'DeclareSchema Migration Generator' do
313
319
 
314
320
  class Category < ActiveRecord::Base; end
315
321
  class Advert < ActiveRecord::Base
322
+ fields { }
316
323
  belongs_to :category, index: false
317
324
  end
318
- up, down = Generators::DeclareSchema::Migration::Migrator.run
325
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
319
326
  expect(up.gsub(/\n+/, "\n")).to eq("add_column :adverts, :category_id, :integer, limit: 8, null: false")
320
327
 
321
328
  Advert.field_specs.delete(:category_id)
@@ -325,9 +332,10 @@ RSpec.describe 'DeclareSchema Migration Generator' do
325
332
 
326
333
  class Category < ActiveRecord::Base; end
327
334
  class Advert < ActiveRecord::Base
335
+ fields { }
328
336
  belongs_to :category, index: 'my_index'
329
337
  end
330
- up, down = Generators::DeclareSchema::Migration::Migrator.run
338
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
331
339
  expect(up.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
332
340
  add_column :adverts, :category_id, :integer, limit: 8, null: false
333
341
  add_index :adverts, [:category_id], name: 'my_index'
@@ -372,7 +380,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
372
380
  title :string, index: true, limit: 255, null: true
373
381
  end
374
382
  end
375
- up, down = Generators::DeclareSchema::Migration::Migrator.run
383
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
376
384
  expect(up.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
377
385
  add_column :adverts, :title, :string, limit: 255
378
386
  add_index :adverts, [:title], name: 'on_title'
@@ -387,7 +395,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
387
395
  title :string, index: true, unique: true, null: true, limit: 255
388
396
  end
389
397
  end
390
- up, down = Generators::DeclareSchema::Migration::Migrator.run
398
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
391
399
  expect(up.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
392
400
  add_column :adverts, :title, :string, limit: 255
393
401
  add_index :adverts, [:title], unique: true, name: 'on_title'
@@ -402,20 +410,20 @@ RSpec.describe 'DeclareSchema Migration Generator' do
402
410
  title :string, index: 'my_index', limit: 255, null: true
403
411
  end
404
412
  end
405
- up, down = Generators::DeclareSchema::Migration::Migrator.run
413
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
406
414
  expect(up.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
407
415
  add_column :adverts, :title, :string, limit: 255
408
416
  add_index :adverts, [:title], name: 'my_index'
409
417
  EOS
410
418
 
411
- Advert.index_specs.delete_if {|spec| spec.fields==["title"]}
419
+ Advert.index_specs.delete_if { |spec| spec.fields==["title"] }
412
420
 
413
421
  # You can ask for an index outside of the fields block
414
422
 
415
423
  class Advert < ActiveRecord::Base
416
424
  index :title
417
425
  end
418
- up, down = Generators::DeclareSchema::Migration::Migrator.run
426
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
419
427
  expect(up.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
420
428
  add_column :adverts, :title, :string, limit: 255
421
429
  add_index :adverts, [:title], name: 'on_title'
@@ -428,7 +436,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
428
436
  class Advert < ActiveRecord::Base
429
437
  index :title, unique: true, name: 'my_index'
430
438
  end
431
- up, down = Generators::DeclareSchema::Migration::Migrator.run
439
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
432
440
  expect(up.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
433
441
  add_column :adverts, :title, :string, limit: 255
434
442
  add_index :adverts, [:title], unique: true, name: 'my_index'
@@ -441,7 +449,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
441
449
  class Advert < ActiveRecord::Base
442
450
  index [:title, :category_id]
443
451
  end
444
- up, down = Generators::DeclareSchema::Migration::Migrator.run
452
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
445
453
  expect(up.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
446
454
  add_column :adverts, :title, :string, limit: 255
447
455
  add_index :adverts, [:title, :category_id], name: 'on_title_and_category_id'
@@ -544,7 +552,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
544
552
  title :string, default: "Untitled", limit: 255, null: true
545
553
  end
546
554
  end
547
- up, down = Generators::DeclareSchema::Migration::Migrator.run
555
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
548
556
  ActiveRecord::Migration.class_eval(up)
549
557
 
550
558
  class FancyAdvert < Advert
@@ -613,7 +621,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
613
621
  created_at :datetime
614
622
  end
615
623
  end
616
- up, down = Generators::DeclareSchema::Migration::Migrator.run(adverts: :ads)
624
+ up = Generators::DeclareSchema::Migration::Migrator.run(adverts: :ads).first
617
625
  expect(up.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
618
626
  rename_table :adverts, :ads
619
627
  add_column :ads, :created_at, :datetime, null: false
@@ -682,5 +690,106 @@ RSpec.describe 'DeclareSchema Migration Generator' do
682
690
  ActiveRecord::Migration.class_eval(up)
683
691
  expect(Ad.field_specs['company'].options[:validates].inspect).to eq("{:presence=>true, :uniqueness=>{:case_sensitive=>false}}")
684
692
  end
685
- end
686
693
 
694
+ if Rails::VERSION::MAJOR >= 5
695
+ describe 'belongs_to' do
696
+ before do
697
+ unless defined?(AdCategory)
698
+ class AdCategory < ActiveRecord::Base
699
+ fields { }
700
+ end
701
+ end
702
+
703
+ class Advert < ActiveRecord::Base
704
+ fields do
705
+ name :string, limit: 255, null: true
706
+ category_id :integer, limit: 8
707
+ nullable_category_id :integer, limit: 8, null: true
708
+ end
709
+ end
710
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
711
+ ActiveRecord::Migration.class_eval(up)
712
+ end
713
+
714
+ it 'passes through optional: when given' do
715
+ class AdvertBelongsTo < ActiveRecord::Base
716
+ self.table_name = 'adverts'
717
+ fields { }
718
+ reset_column_information
719
+ belongs_to :ad_category, optional: true
720
+ end
721
+ expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional: true)
722
+ end
723
+
724
+ describe 'contradictory settings' do # contradictory settings are ok during migration
725
+ it 'passes through optional: true, null: false' do
726
+ class AdvertBelongsTo < ActiveRecord::Base
727
+ self.table_name = 'adverts'
728
+ fields { }
729
+ reset_column_information
730
+ belongs_to :ad_category, optional: true, null: false
731
+ end
732
+ expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional: true)
733
+ expect(AdvertBelongsTo.field_specs['ad_category_id'].options&.[](:null)).to eq(false)
734
+ end
735
+
736
+ it 'passes through optional: false, null: true' do
737
+ class AdvertBelongsTo < ActiveRecord::Base
738
+ self.table_name = 'adverts'
739
+ fields { }
740
+ reset_column_information
741
+ belongs_to :ad_category, optional: false, null: true
742
+ end
743
+ expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional: false)
744
+ expect(AdvertBelongsTo.field_specs['ad_category_id'].options&.[](:null)).to eq(true)
745
+ end
746
+ end
747
+
748
+ [false, true].each do |nullable|
749
+ context "nullable=#{nullable}" do
750
+ it 'infers optional: from null:' do
751
+ eval <<~EOS
752
+ class AdvertBelongsTo < ActiveRecord::Base
753
+ fields { }
754
+ belongs_to :ad_category, null: #{nullable}
755
+ end
756
+ EOS
757
+ expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional: nullable)
758
+ expect(AdvertBelongsTo.field_specs['ad_category_id'].options&.[](:null)).to eq(nullable)
759
+ end
760
+
761
+ it 'infers null: from optional:' do
762
+ eval <<~EOS
763
+ class AdvertBelongsTo < ActiveRecord::Base
764
+ fields { }
765
+ belongs_to :ad_category, optional: #{nullable}
766
+ end
767
+ EOS
768
+ expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional: nullable)
769
+ expect(AdvertBelongsTo.field_specs['ad_category_id'].options&.[](:null)).to eq(nullable)
770
+ end
771
+ end
772
+ end
773
+ end
774
+ end
775
+
776
+ describe 'migration base class' do
777
+ it 'adapts to Rails 4' do
778
+ class Advert < active_record_base_class.constantize
779
+ fields do
780
+ title :string, limit: 100
781
+ end
782
+ end
783
+
784
+ Rails::Generators.invoke('declare_schema:migration', %w[-n -m])
785
+
786
+ migrations = Dir.glob('db/migrate/*declare_schema_migration*.rb')
787
+ expect(migrations.size).to eq(1), migrations.inspect
788
+
789
+ migration_content = File.read(migrations.first)
790
+ first_line = migration_content.split("\n").first
791
+ base_class = first_line.split(' < ').last
792
+ expect(base_class).to eq("(Rails::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[4.2] : ActiveRecord::Migration)")
793
+ end
794
+ end
795
+ end
@@ -18,6 +18,8 @@ require "#{TESTAPP_PATH}/config/environment"
18
18
  require 'rails/generators'
19
19
  Rails::Generators.configure!(Rails.application.config.generators)
20
20
 
21
+ ActiveRecord::Base.connection.schema_cache.clear!
22
+
21
23
  (ActiveRecord::Base.connection.tables - Generators::DeclareSchema::Migration::Migrator.always_ignore_tables).each do |table|
22
24
  ActiveRecord::Base.connection.execute("DROP TABLE #{ActiveRecord::Base.connection.quote_table_name(table)}")
23
25
  end
metadata CHANGED
@@ -1,11 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: declare_schema
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0.pre.2
4
+ version: 0.3.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
11
  date: 2020-11-02 00:00:00.000000000 Z
@@ -84,7 +84,7 @@ homepage: https://github.com/Invoca/declare_schema
84
84
  licenses: []
85
85
  metadata:
86
86
  allowed_push_host: https://rubygems.org
87
- post_install_message:
87
+ post_install_message:
88
88
  rdoc_options: []
89
89
  require_paths:
90
90
  - lib
@@ -100,7 +100,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
100
100
  version: 1.3.6
101
101
  requirements: []
102
102
  rubygems_version: 3.0.3
103
- signing_key:
103
+ signing_key:
104
104
  specification_version: 4
105
105
  summary: Database migration generator for Rails
106
106
  test_files: []