declare_schema 0.3.0 → 0.5.0.pre.1

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.
@@ -10,14 +10,14 @@ RSpec.describe 'DeclareSchema API' do
10
10
 
11
11
  describe 'example models' do
12
12
  it 'generates a model' do
13
- expect(system("bundle exec rails generate declare_schema:model advert title:string body:text")).to be_truthy
13
+ generate_model 'advert', 'title:string', 'body:text'
14
14
 
15
15
  # The above will generate the test, fixture and a model file like this:
16
16
  # model_declaration = Rails::Generators.invoke('declare_schema:model', ['advert2', 'title:string', 'body:text'])
17
17
  # expect(model_declaration.first).to eq([["Advert"], nil, "app/models/advert.rb", nil,
18
18
  # [["AdvertTest"], "test/models/advert_test.rb", nil, "test/fixtures/adverts.yml"]])
19
19
 
20
- expect(File.read("#{TESTAPP_PATH}/app/models/advert.rb")).to eq(<<~EOS)
20
+ expect_model_definition_to_eq('advert', <<~EOS)
21
21
  class Advert < #{active_record_base_class}
22
22
 
23
23
  fields do
@@ -27,7 +27,8 @@ RSpec.describe 'DeclareSchema API' do
27
27
 
28
28
  end
29
29
  EOS
30
- system("rm -rf #{TESTAPP_PATH}/app/models/advert2.rb #{TESTAPP_PATH}/test/models/advert2.rb #{TESTAPP_PATH}/test/fixtures/advert2.rb")
30
+
31
+ clean_up_model('advert2')
31
32
 
32
33
  # The migration generator uses this information to create a migration.
33
34
  # The following creates and runs the migration:
@@ -36,13 +37,11 @@ RSpec.describe 'DeclareSchema API' do
36
37
 
37
38
  # We're now ready to start demonstrating the API
38
39
 
39
- Rails.application.config.autoload_paths += ["#{TESTAPP_PATH}/app/models"]
40
-
41
- $LOAD_PATH << "#{TESTAPP_PATH}/app/models"
40
+ load_models
42
41
 
43
- unless Rails::VERSION::MAJOR >= 6
42
+ if Rails::VERSION::MAJOR == 5
44
43
  # TODO: get this to work on Travis for Rails 6
45
- Rails::Generators.invoke('declare_schema:migration', %w[-n -m])
44
+ generate_migrations '-n', '-m'
46
45
  end
47
46
 
48
47
  require 'advert'
@@ -6,22 +6,20 @@ RSpec.describe 'DeclareSchema Migration Generator' do
6
6
  end
7
7
 
8
8
  it "generates nested models" do
9
- Rails::Generators.invoke('declare_schema:model', %w[alpha/beta one:string two:integer])
9
+ generate_model 'alpha/beta', 'one:string', 'two:integer'
10
10
 
11
- expect(File.exist?('app/models/alpha/beta.rb')).to be_truthy
12
-
13
- expect(File.read('app/models/alpha/beta.rb')).to eq(<<~EOS)
11
+ expect_model_definition_to_eq('alpha/beta', <<~EOS)
14
12
  class Alpha::Beta < #{active_record_base_class}
15
-
13
+
16
14
  fields do
17
15
  one :string, limit: 255
18
16
  two :integer
19
17
  end
20
-
18
+
21
19
  end
22
20
  EOS
23
21
 
24
- expect(File.read('app/models/alpha.rb')).to eq(<<~EOS)
22
+ expect_model_definition_to_eq('alpha', <<~EOS)
25
23
  module Alpha
26
24
  def self.table_name_prefix
27
25
  'alpha_'
@@ -29,9 +27,9 @@ RSpec.describe 'DeclareSchema Migration Generator' do
29
27
  end
30
28
  EOS
31
29
 
32
- expect(File.read('test/models/alpha/beta_test.rb')).to eq(<<~EOS)
30
+ expect_test_definition_to_eq('alpha/beta', <<~EOS)
33
31
  require 'test_helper'
34
-
32
+
35
33
  class Alpha::BetaTest < ActiveSupport::TestCase
36
34
  # test "the truth" do
37
35
  # assert true
@@ -39,7 +37,50 @@ RSpec.describe 'DeclareSchema Migration Generator' do
39
37
  end
40
38
  EOS
41
39
 
42
- expect(File.exist?('test/fixtures/alpha/beta.yml')).to be_truthy
40
+ case Rails::VERSION::MAJOR
41
+ when 4
42
+ expect_test_fixture_to_eq('alpha/beta', <<~EOS)
43
+ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
44
+
45
+ # This model initially had no columns defined. If you add columns to the
46
+ # model remove the '{}' from the fixture names and add the columns immediately
47
+ # below each fixture, per the syntax in the comments below
48
+ #
49
+ one: {}
50
+ # column: value
51
+ #
52
+ two: {}
53
+ # column: value
54
+ EOS
55
+ when 5
56
+ expect_test_fixture_to_eq('alpha/beta', <<~EOS)
57
+ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
58
+
59
+ # This model initially had no columns defined. If you add columns to the
60
+ # model remove the '{}' from the fixture names and add the columns immediately
61
+ # below each fixture, per the syntax in the comments below
62
+ #
63
+ one: {}
64
+ # column: value
65
+ #
66
+ two: {}
67
+ # column: value
68
+ EOS
69
+ when 6
70
+ expect_test_fixture_to_eq('alpha/beta', <<~EOS)
71
+ # Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
72
+
73
+ # This model initially had no columns defined. If you add columns to the
74
+ # model remove the '{}' from the fixture names and add the columns immediately
75
+ # below each fixture, per the syntax in the comments below
76
+ #
77
+ one: {}
78
+ # column: value
79
+ #
80
+ two: {}
81
+ # column: value
82
+ EOS
83
+ end
43
84
 
44
85
  $LOAD_PATH << "#{TESTAPP_PATH}/app/models"
45
86
 
@@ -12,7 +12,7 @@ RSpec.describe 'DeclareSchema Migration Generator interactive primary key' do
12
12
  self.primary_key = "foo_id"
13
13
  end
14
14
 
15
- Rails::Generators.invoke('declare_schema:migration', %w[-n -m])
15
+ generate_migrations '-n', '-m'
16
16
  expect(Foo.primary_key).to eq('foo_id')
17
17
 
18
18
  ### migrate from
@@ -24,28 +24,30 @@ RSpec.describe 'DeclareSchema Migration Generator interactive primary key' do
24
24
  end
25
25
 
26
26
  puts "\n\e[45m Please enter 'id' (no quotes) at the next prompt \e[0m"
27
- Rails::Generators.invoke('declare_schema:migration', %w[-n -m])
27
+ generate_migrations '-n', '-m'
28
28
  expect(Foo.primary_key).to eq('id')
29
29
 
30
30
  nuke_model_class(Foo)
31
31
 
32
32
  ### migrate to
33
33
 
34
- # rename to custom primary_key
35
- class Foo < ActiveRecord::Base
36
- fields do
34
+ if Rails::VERSION::MAJOR >= 5
35
+ # rename to custom primary_key
36
+ class Foo < ActiveRecord::Base
37
+ fields do
38
+ end
39
+ self.primary_key = "foo_id"
37
40
  end
38
- self.primary_key = "foo_id"
39
- end
40
41
 
41
- puts "\n\e[45m Please enter 'drop id' (no quotes) at the next prompt \e[0m"
42
- Rails::Generators.invoke('declare_schema:migration', %w[-n -m])
43
- expect(Foo.primary_key).to eq('foo_id')
42
+ puts "\n\e[45m Please enter 'drop id' (no quotes) at the next prompt \e[0m"
43
+ generate_migrations '-n', '-m'
44
+ expect(Foo.primary_key).to eq('foo_id')
44
45
 
45
- ### ensure it doesn't cause further migrations
46
+ ### ensure it doesn't cause further migrations
46
47
 
47
- # check no further migrations
48
- up, down = Generators::DeclareSchema::Migration::Migrator.run
49
- expect(up).to eq("")
48
+ # check no further migrations
49
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
50
+ expect(up).to eq("")
51
+ end
50
52
  end
51
53
  end
@@ -11,14 +11,12 @@ RSpec.describe 'DeclareSchema Migration Generator' do
11
11
  it 'generates migrations' do
12
12
  ## The migration generator -- introduction
13
13
 
14
- up_down = Generators::DeclareSchema::Migration::Migrator.run
15
- expect(up_down).to eq(["", ""])
14
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to migrate_up("").and migrate_down("")
16
15
 
17
16
  class Advert < ActiveRecord::Base
18
17
  end
19
18
 
20
- up_down = Generators::DeclareSchema::Migration::Migrator.run
21
- expect(up_down).to eq(["", ""])
19
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to migrate_up("").and migrate_down("")
22
20
 
23
21
  Generators::DeclareSchema::Migration::Migrator.ignore_tables = ["green_fishes"]
24
22
 
@@ -30,17 +28,27 @@ RSpec.describe 'DeclareSchema Migration Generator' do
30
28
  name :string, limit: 255, null: true
31
29
  end
32
30
  end
33
- up, down = Generators::DeclareSchema::Migration::Migrator.run
34
- expect(up).to eq(<<~EOS.strip)
35
- create_table :adverts, id: :bigint do |t|
36
- t.string :name, limit: 255
37
- end
38
- EOS
39
- expect(down).to eq("drop_table :adverts")
31
+
32
+ up, _ = Generators::DeclareSchema::Migration::Migrator.run.tap do |migrations|
33
+ expect(migrations).to(
34
+ migrate_up(<<~EOS.strip)
35
+ create_table :adverts, id: :bigint do |t|
36
+ t.string :name, limit: 255
37
+ end
38
+ EOS
39
+ .and migrate_down("drop_table :adverts")
40
+ )
41
+ end
40
42
 
41
43
  ActiveRecord::Migration.class_eval(up)
42
44
  expect(Advert.columns.map(&:name)).to eq(["id", "name"])
43
45
 
46
+ if Rails::VERSION::MAJOR < 5
47
+ # Rails 4 sqlite driver doesn't create PK properly. Fix that by dropping and recreating.
48
+ ActiveRecord::Base.connection.execute("drop table adverts")
49
+ ActiveRecord::Base.connection.execute('CREATE TABLE "adverts" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255))')
50
+ end
51
+
44
52
  class Advert < ActiveRecord::Base
45
53
  fields do
46
54
  name :string, limit: 255, null: true
@@ -48,19 +56,20 @@ RSpec.describe 'DeclareSchema Migration Generator' do
48
56
  published_at :datetime, null: true
49
57
  end
50
58
  end
51
- up, down = migrate
52
- expect(up).to eq(<<~EOS.strip)
53
- add_column :adverts, :body, :text
54
- add_column :adverts, :published_at, :datetime
55
59
 
56
- add_index :adverts, [:id], unique: true, name: 'PRIMARY_KEY'
57
- EOS
58
- # TODO: ^ TECH-4975 add_index should not be there
60
+ Advert.connection.schema_cache.clear!
61
+ Advert.reset_column_information
59
62
 
60
- expect(down).to eq(<<~EOS.strip)
61
- remove_column :adverts, :body
62
- remove_column :adverts, :published_at
63
- EOS
63
+ expect(migrate).to(
64
+ migrate_up(<<~EOS.strip)
65
+ add_column :adverts, :body, :text
66
+ add_column :adverts, :published_at, :datetime
67
+ EOS
68
+ .and migrate_down(<<~EOS.strip)
69
+ remove_column :adverts, :body
70
+ remove_column :adverts, :published_at
71
+ EOS
72
+ )
64
73
 
65
74
  Advert.field_specs.clear # not normally needed
66
75
  class Advert < ActiveRecord::Base
@@ -70,9 +79,11 @@ RSpec.describe 'DeclareSchema Migration Generator' do
70
79
  end
71
80
  end
72
81
 
73
- up, down = migrate
74
- expect(up).to eq("remove_column :adverts, :published_at")
75
- expect(down).to eq("add_column :adverts, :published_at, :datetime")
82
+ expect(migrate).to(
83
+ migrate_up("remove_column :adverts, :published_at").and(
84
+ migrate_down("add_column :adverts, :published_at, :datetime")
85
+ )
86
+ )
76
87
 
77
88
  nuke_model_class(Advert)
78
89
  class Advert < ActiveRecord::Base
@@ -82,20 +93,22 @@ RSpec.describe 'DeclareSchema Migration Generator' do
82
93
  end
83
94
  end
84
95
 
85
- up, down = Generators::DeclareSchema::Migration::Migrator.run
86
- expect(up).to eq(<<~EOS.strip)
87
- add_column :adverts, :title, :string, limit: 255
88
- remove_column :adverts, :name
89
- EOS
90
-
91
- expect(down).to eq(<<~EOS.strip)
92
- remove_column :adverts, :title
93
- add_column :adverts, :name, :string, limit: 255
94
- EOS
95
-
96
- up, down = Generators::DeclareSchema::Migration::Migrator.run(adverts: { name: :title })
97
- expect(up).to eq("rename_column :adverts, :name, :title")
98
- expect(down).to eq("rename_column :adverts, :title, :name")
96
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to(
97
+ migrate_up(<<~EOS.strip)
98
+ add_column :adverts, :title, :string, limit: 255
99
+ remove_column :adverts, :name
100
+ EOS
101
+ .and migrate_down(<<~EOS.strip)
102
+ remove_column :adverts, :title
103
+ add_column :adverts, :name, :string, limit: 255
104
+ EOS
105
+ )
106
+
107
+ expect(Generators::DeclareSchema::Migration::Migrator.run(adverts: { name: :title })).to(
108
+ migrate_up("rename_column :adverts, :name, :title").and(
109
+ migrate_down("rename_column :adverts, :title, :name")
110
+ )
111
+ )
99
112
 
100
113
  migrate
101
114
 
@@ -106,9 +119,11 @@ RSpec.describe 'DeclareSchema Migration Generator' do
106
119
  end
107
120
  end
108
121
 
109
- up_down = Generators::DeclareSchema::Migration::Migrator.run
110
- expect(up_down).to eq(["change_column :adverts, :title, :text",
111
- "change_column :adverts, :title, :string, limit: 255"])
122
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to(
123
+ migrate_up("change_column :adverts, :title, :text").and(
124
+ migrate_down("change_column :adverts, :title, :string, limit: 255")
125
+ )
126
+ )
112
127
 
113
128
  class Advert < ActiveRecord::Base
114
129
  fields do
@@ -117,11 +132,14 @@ RSpec.describe 'DeclareSchema Migration Generator' do
117
132
  end
118
133
  end
119
134
 
120
- up, down = migrate
121
- expect(up.split(',').slice(0,3).join(',')).to eq('change_column :adverts, :title, :string')
122
- expect(up.split(',').slice(3,2).sort.join(',')).to eq(" default: \"Untitled\", limit: 255")
123
- expect(down).to eq("change_column :adverts, :title, :string, limit: 255")
124
-
135
+ expect(migrate).to(
136
+ migrate_up(<<~EOS.strip)
137
+ change_column :adverts, :title, :string, limit: 255, default: "Untitled"
138
+ EOS
139
+ .and migrate_down(<<~EOS.strip)
140
+ change_column :adverts, :title, :string, limit: 255
141
+ EOS
142
+ )
125
143
 
126
144
  ### Limits
127
145
 
@@ -131,8 +149,9 @@ RSpec.describe 'DeclareSchema Migration Generator' do
131
149
  end
132
150
  end
133
151
 
134
- up = Generators::DeclareSchema::Migration::Migrator.run.first
135
- expect(up).to eq("add_column :adverts, :price, :integer, limit: 2")
152
+ up, _ = Generators::DeclareSchema::Migration::Migrator.run.tap do |migrations|
153
+ expect(migrations).to migrate_up("add_column :adverts, :price, :integer, limit: 2")
154
+ end
136
155
 
137
156
  # Now run the migration, then change the limit:
138
157
 
@@ -143,9 +162,14 @@ RSpec.describe 'DeclareSchema Migration Generator' do
143
162
  end
144
163
  end
145
164
 
146
- up, down = Generators::DeclareSchema::Migration::Migrator.run
147
- expect(up).to eq("change_column :adverts, :price, :integer, limit: 3")
148
- expect(down).to eq("change_column :adverts, :price, :integer, limit: 2")
165
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to(
166
+ migrate_up(<<~EOS.strip)
167
+ change_column :adverts, :price, :integer, limit: 3
168
+ EOS
169
+ .and migrate_down(<<~EOS.strip)
170
+ change_column :adverts, :price, :integer, limit: 2
171
+ EOS
172
+ )
149
173
 
150
174
  # Note that limit on a decimal column is ignored (use :scale and :precision)
151
175
 
@@ -156,8 +180,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
156
180
  end
157
181
  end
158
182
 
159
- up = Generators::DeclareSchema::Migration::Migrator.run.first
160
- expect(up).to eq("add_column :adverts, :price, :decimal")
183
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to migrate_up("add_column :adverts, :price, :decimal")
161
184
 
162
185
  # Limits are generally not needed for `text` fields, because by default, `text` fields will use the maximum size
163
186
  # allowed for that database type (0xffffffff for LONGTEXT in MySQL unlimited in Postgres, 1 billion in Sqlite).
@@ -172,12 +195,13 @@ RSpec.describe 'DeclareSchema Migration Generator' do
172
195
  end
173
196
  end
174
197
 
175
- up = Generators::DeclareSchema::Migration::Migrator.run.first
176
- expect(up).to eq(<<~EOS.strip)
177
- add_column :adverts, :price, :decimal
178
- add_column :adverts, :notes, :text, null: false
179
- add_column :adverts, :description, :text, null: false
180
- EOS
198
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to(
199
+ migrate_up(<<~EOS.strip)
200
+ add_column :adverts, :price, :decimal
201
+ add_column :adverts, :notes, :text, null: false
202
+ add_column :adverts, :description, :text, null: false
203
+ EOS
204
+ )
181
205
 
182
206
  # (There is no limit on `add_column ... :description` above since these tests are run against SQLite.)
183
207
 
@@ -196,11 +220,12 @@ RSpec.describe 'DeclareSchema Migration Generator' do
196
220
  end
197
221
  end
198
222
 
199
- up = Generators::DeclareSchema::Migration::Migrator.run.first
200
- expect(up).to eq(<<~EOS.strip)
201
- add_column :adverts, :notes, :text, null: false, limit: 4294967295
202
- add_column :adverts, :description, :text, null: false, limit: 255
203
- EOS
223
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to(
224
+ migrate_up(<<~EOS.strip)
225
+ add_column :adverts, :notes, :text, null: false, limit: 4294967295
226
+ add_column :adverts, :description, :text, null: false, limit: 255
227
+ EOS
228
+ )
204
229
 
205
230
  Advert.field_specs.delete :notes
206
231
 
@@ -239,9 +264,14 @@ RSpec.describe 'DeclareSchema Migration Generator' do
239
264
  end
240
265
  end
241
266
 
242
- up, down = Generators::DeclareSchema::Migration::Migrator.run
243
- expect(up).to eq("change_column :adverts, :description, :text, limit: 4294967295, null: false")
244
- expect(down).to eq("change_column :adverts, :description, :text")
267
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to(
268
+ migrate_up(<<~EOS.strip)
269
+ change_column :adverts, :description, :text, limit: 4294967295, null: false
270
+ EOS
271
+ .and migrate_down(<<~EOS.strip)
272
+ change_column :adverts, :description, :text
273
+ EOS
274
+ )
245
275
 
246
276
  # TODO TECH-4814: The above test should have this output:
247
277
  # TODO => "change_column :adverts, :description, :text, limit: 255
@@ -254,9 +284,14 @@ RSpec.describe 'DeclareSchema Migration Generator' do
254
284
  end
255
285
  end
256
286
 
257
- up, down = Generators::DeclareSchema::Migration::Migrator.run
258
- expect(up).to eq("change_column :adverts, :description, :text, limit: 4294967295, null: false")
259
- expect(down).to eq("change_column :adverts, :description, :text")
287
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to(
288
+ migrate_up(<<~EOS.strip)
289
+ change_column :adverts, :description, :text, limit: 4294967295, null: false
290
+ EOS
291
+ .and migrate_down(<<~EOS.strip)
292
+ change_column :adverts, :description, :text
293
+ EOS
294
+ )
260
295
  ::DeclareSchema::Model::FieldSpec::instance_variable_set(:@mysql_text_limits, false)
261
296
 
262
297
  Advert.field_specs.clear
@@ -286,18 +321,21 @@ RSpec.describe 'DeclareSchema Migration Generator' do
286
321
  belongs_to :category
287
322
  end
288
323
 
289
- up, down = Generators::DeclareSchema::Migration::Migrator.run
290
- expect(up.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
291
- add_column :adverts, :category_id, :integer, limit: 8, null: false
292
- add_index :adverts, [:category_id], name: 'on_category_id'
293
- EOS
294
- expect(down.sub(/\n+/, "\n")).to eq(<<~EOS.strip)
295
- remove_column :adverts, :category_id
296
- remove_index :adverts, name: :on_category_id rescue ActiveRecord::StatementInvalid
297
- EOS
324
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to(
325
+ migrate_up(<<~EOS.strip)
326
+ add_column :adverts, :category_id, :integer, limit: 8, null: false
327
+
328
+ add_index :adverts, [:category_id], name: 'on_category_id'
329
+ EOS
330
+ .and migrate_down(<<~EOS.strip)
331
+ remove_column :adverts, :category_id
332
+
333
+ remove_index :adverts, name: :on_category_id rescue ActiveRecord::StatementInvalid
334
+ EOS
335
+ )
298
336
 
299
337
  Advert.field_specs.delete(:category_id)
300
- Advert.index_specs.delete_if {|spec| spec.fields==["category_id"]}
338
+ Advert.index_definitions.delete_if { |spec| spec.fields==["category_id"] }
301
339
 
302
340
  # If you specify a custom foreign key, the migration generator observes that:
303
341
 
@@ -306,14 +344,17 @@ RSpec.describe 'DeclareSchema Migration Generator' do
306
344
  fields { }
307
345
  belongs_to :category, foreign_key: "c_id", class_name: 'Category'
308
346
  end
309
- up = Generators::DeclareSchema::Migration::Migrator.run.first
310
- expect(up.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
311
- add_column :adverts, :c_id, :integer, limit: 8, null: false
312
- add_index :adverts, [:c_id], name: 'on_c_id'
313
- EOS
347
+
348
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to(
349
+ migrate_up(<<~EOS.strip)
350
+ add_column :adverts, :c_id, :integer, limit: 8, null: false
351
+
352
+ add_index :adverts, [:c_id], name: 'on_c_id'
353
+ EOS
354
+ )
314
355
 
315
356
  Advert.field_specs.delete(:c_id)
316
- Advert.index_specs.delete_if { |spec| spec.fields == ["c_id"] }
357
+ Advert.index_definitions.delete_if { |spec| spec.fields == ["c_id"] }
317
358
 
318
359
  # You can avoid generating the index by specifying `index: false`
319
360
 
@@ -322,11 +363,15 @@ RSpec.describe 'DeclareSchema Migration Generator' do
322
363
  fields { }
323
364
  belongs_to :category, index: false
324
365
  end
325
- up = Generators::DeclareSchema::Migration::Migrator.run.first
326
- expect(up.gsub(/\n+/, "\n")).to eq("add_column :adverts, :category_id, :integer, limit: 8, null: false")
366
+
367
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to(
368
+ migrate_up(<<~EOS.strip)
369
+ add_column :adverts, :category_id, :integer, limit: 8, null: false
370
+ EOS
371
+ )
327
372
 
328
373
  Advert.field_specs.delete(:category_id)
329
- Advert.index_specs.delete_if { |spec| spec.fields == ["category_id"] }
374
+ Advert.index_definitions.delete_if { |spec| spec.fields == ["category_id"] }
330
375
 
331
376
  # You can specify the index name with :index
332
377
 
@@ -335,14 +380,17 @@ RSpec.describe 'DeclareSchema Migration Generator' do
335
380
  fields { }
336
381
  belongs_to :category, index: 'my_index'
337
382
  end
338
- up = Generators::DeclareSchema::Migration::Migrator.run.first
339
- expect(up.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
340
- add_column :adverts, :category_id, :integer, limit: 8, null: false
341
- add_index :adverts, [:category_id], name: 'my_index'
342
- EOS
383
+
384
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to(
385
+ migrate_up(<<~EOS.strip)
386
+ add_column :adverts, :category_id, :integer, limit: 8, null: false
387
+
388
+ add_index :adverts, [:category_id], name: 'my_index'
389
+ EOS
390
+ )
343
391
 
344
392
  Advert.field_specs.delete(:category_id)
345
- Advert.index_specs.delete_if { |spec| spec.fields == ["category_id"] }
393
+ Advert.index_definitions.delete_if { |spec| spec.fields == ["category_id"] }
346
394
 
347
395
  ### Timestamps and Optimimistic Locking
348
396
 
@@ -355,17 +403,19 @@ RSpec.describe 'DeclareSchema Migration Generator' do
355
403
  optimistic_lock
356
404
  end
357
405
  end
358
- up, down = Generators::DeclareSchema::Migration::Migrator.run
359
- expect(up.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
360
- add_column :adverts, :created_at, :datetime
361
- add_column :adverts, :updated_at, :datetime
362
- add_column :adverts, :lock_version, :integer, null: false, default: 1
363
- EOS
364
- expect(down.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
365
- remove_column :adverts, :created_at
366
- remove_column :adverts, :updated_at
367
- remove_column :adverts, :lock_version
368
- EOS
406
+
407
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to(
408
+ migrate_up(<<~EOS.strip)
409
+ add_column :adverts, :created_at, :datetime
410
+ add_column :adverts, :updated_at, :datetime
411
+ add_column :adverts, :lock_version, :integer, null: false, default: 1
412
+ EOS
413
+ .and migrate_down(<<~EOS.strip)
414
+ remove_column :adverts, :created_at
415
+ remove_column :adverts, :updated_at
416
+ remove_column :adverts, :lock_version
417
+ EOS
418
+ )
369
419
 
370
420
  Advert.field_specs.delete(:updated_at)
371
421
  Advert.field_specs.delete(:created_at)
@@ -380,13 +430,16 @@ RSpec.describe 'DeclareSchema Migration Generator' do
380
430
  title :string, index: true, limit: 255, null: true
381
431
  end
382
432
  end
383
- up = Generators::DeclareSchema::Migration::Migrator.run.first
384
- expect(up.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
385
- add_column :adverts, :title, :string, limit: 255
386
- add_index :adverts, [:title], name: 'on_title'
387
- EOS
388
433
 
389
- Advert.index_specs.delete_if { |spec| spec.fields==["title"] }
434
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to(
435
+ migrate_up(<<~EOS.strip)
436
+ add_column :adverts, :title, :string, limit: 255
437
+
438
+ add_index :adverts, [:title], name: 'on_title'
439
+ EOS
440
+ )
441
+
442
+ Advert.index_definitions.delete_if { |spec| spec.fields==["title"] }
390
443
 
391
444
  # You can ask for a unique index
392
445
 
@@ -395,13 +448,16 @@ RSpec.describe 'DeclareSchema Migration Generator' do
395
448
  title :string, index: true, unique: true, null: true, limit: 255
396
449
  end
397
450
  end
398
- up = Generators::DeclareSchema::Migration::Migrator.run.first
399
- expect(up.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
400
- add_column :adverts, :title, :string, limit: 255
401
- add_index :adverts, [:title], unique: true, name: 'on_title'
402
- EOS
403
451
 
404
- Advert.index_specs.delete_if { |spec| spec.fields == ["title"] }
452
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to(
453
+ migrate_up(<<~EOS.strip)
454
+ add_column :adverts, :title, :string, limit: 255
455
+
456
+ add_index :adverts, [:title], unique: true, name: 'on_title'
457
+ EOS
458
+ )
459
+
460
+ Advert.index_definitions.delete_if { |spec| spec.fields == ["title"] }
405
461
 
406
462
  # You can specify the name for the index
407
463
 
@@ -410,52 +466,64 @@ RSpec.describe 'DeclareSchema Migration Generator' do
410
466
  title :string, index: 'my_index', limit: 255, null: true
411
467
  end
412
468
  end
413
- up = Generators::DeclareSchema::Migration::Migrator.run.first
414
- expect(up.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
415
- add_column :adverts, :title, :string, limit: 255
416
- add_index :adverts, [:title], name: 'my_index'
417
- EOS
418
469
 
419
- Advert.index_specs.delete_if { |spec| spec.fields==["title"] }
470
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to(
471
+ migrate_up(<<~EOS.strip)
472
+ add_column :adverts, :title, :string, limit: 255
473
+
474
+ add_index :adverts, [:title], name: 'my_index'
475
+ EOS
476
+ )
477
+
478
+ Advert.index_definitions.delete_if { |spec| spec.fields==["title"] }
420
479
 
421
480
  # You can ask for an index outside of the fields block
422
481
 
423
482
  class Advert < ActiveRecord::Base
424
483
  index :title
425
484
  end
426
- up = Generators::DeclareSchema::Migration::Migrator.run.first
427
- expect(up.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
428
- add_column :adverts, :title, :string, limit: 255
429
- add_index :adverts, [:title], name: 'on_title'
430
- EOS
431
485
 
432
- Advert.index_specs.delete_if { |spec| spec.fields == ["title"] }
486
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to(
487
+ migrate_up(<<~EOS.strip)
488
+ add_column :adverts, :title, :string, limit: 255
489
+
490
+ add_index :adverts, [:title], name: 'on_title'
491
+ EOS
492
+ )
493
+
494
+ Advert.index_definitions.delete_if { |spec| spec.fields == ["title"] }
433
495
 
434
496
  # The available options for the index function are `:unique` and `:name`
435
497
 
436
498
  class Advert < ActiveRecord::Base
437
499
  index :title, unique: true, name: 'my_index'
438
500
  end
439
- up = Generators::DeclareSchema::Migration::Migrator.run.first
440
- expect(up.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
441
- add_column :adverts, :title, :string, limit: 255
442
- add_index :adverts, [:title], unique: true, name: 'my_index'
443
- EOS
444
501
 
445
- Advert.index_specs.delete_if { |spec| spec.fields == ["title"] }
502
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to(
503
+ migrate_up(<<~EOS.strip)
504
+ add_column :adverts, :title, :string, limit: 255
505
+
506
+ add_index :adverts, [:title], unique: true, name: 'my_index'
507
+ EOS
508
+ )
509
+
510
+ Advert.index_definitions.delete_if { |spec| spec.fields == ["title"] }
446
511
 
447
512
  # You can create an index on more than one field
448
513
 
449
514
  class Advert < ActiveRecord::Base
450
515
  index [:title, :category_id]
451
516
  end
452
- up = Generators::DeclareSchema::Migration::Migrator.run.first
453
- expect(up.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
454
- add_column :adverts, :title, :string, limit: 255
455
- add_index :adverts, [:title, :category_id], name: 'on_title_and_category_id'
456
- EOS
457
517
 
458
- Advert.index_specs.delete_if { |spec| spec.fields==["title", "category_id"] }
518
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to(
519
+ migrate_up(<<~EOS.strip)
520
+ add_column :adverts, :title, :string, limit: 255
521
+
522
+ add_index :adverts, [:title, :category_id], name: 'on_title_and_category_id'
523
+ EOS
524
+ )
525
+
526
+ Advert.index_definitions.delete_if { |spec| spec.fields==["title", "category_id"] }
459
527
 
460
528
  # Finally, you can specify that the migration generator should completely ignore an
461
529
  # index by passing its name to ignore_index in the model.
@@ -476,19 +544,24 @@ RSpec.describe 'DeclareSchema Migration Generator' do
476
544
  Advert.connection.schema_cache.clear!
477
545
  Advert.reset_column_information
478
546
 
479
- up, down = Generators::DeclareSchema::Migration::Migrator.run("adverts" => "ads")
480
- expect(up.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
481
- rename_table :adverts, :ads
482
- add_column :ads, :title, :string, limit: 255
483
- add_column :ads, :body, :text
484
- add_index :ads, [:id], unique: true, name: 'PRIMARY_KEY'
485
- EOS
486
- expect(down.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
487
- remove_column :ads, :title
488
- remove_column :ads, :body
489
- rename_table :ads, :adverts
490
- add_index :adverts, [:id], unique: true, name: 'PRIMARY_KEY'
491
- EOS
547
+ expect(Generators::DeclareSchema::Migration::Migrator.run("adverts" => "ads")).to(
548
+ migrate_up(<<~EOS.strip)
549
+ rename_table :adverts, :ads
550
+
551
+ add_column :ads, :title, :string, limit: 255
552
+ add_column :ads, :body, :text
553
+
554
+ add_index :ads, [:id], unique: true, name: 'PRIMARY'
555
+ EOS
556
+ .and migrate_down(<<~EOS.strip)
557
+ remove_column :ads, :title
558
+ remove_column :ads, :body
559
+
560
+ rename_table :ads, :adverts
561
+
562
+ add_index :adverts, [:id], unique: true, name: 'PRIMARY'
563
+ EOS
564
+ )
492
565
 
493
566
  # Set the table name back to what it should be and confirm we're in sync:
494
567
 
@@ -512,21 +585,27 @@ RSpec.describe 'DeclareSchema Migration Generator' do
512
585
  body :text, null: true
513
586
  end
514
587
  end
515
- up, down = Generators::DeclareSchema::Migration::Migrator.run("adverts" => "advertisements")
516
- expect(up.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
517
- rename_table :adverts, :advertisements
518
- add_column :advertisements, :title, :string, limit: 255
519
- add_column :advertisements, :body, :text
520
- remove_column :advertisements, :name
521
- add_index :advertisements, [:id], unique: true, name: 'PRIMARY_KEY'
522
- EOS
523
- expect(down.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
524
- remove_column :advertisements, :title
525
- remove_column :advertisements, :body
526
- add_column :adverts, :name, :string, limit: 255
527
- rename_table :advertisements, :adverts
528
- add_index :adverts, [:id], unique: true, name: 'PRIMARY_KEY'
529
- EOS
588
+
589
+ expect(Generators::DeclareSchema::Migration::Migrator.run("adverts" => "advertisements")).to(
590
+ migrate_up(<<~EOS.strip)
591
+ rename_table :adverts, :advertisements
592
+
593
+ add_column :advertisements, :title, :string, limit: 255
594
+ add_column :advertisements, :body, :text
595
+ remove_column :advertisements, :name
596
+
597
+ add_index :advertisements, [:id], unique: true, name: 'PRIMARY'
598
+ EOS
599
+ .and migrate_down(<<~EOS.strip)
600
+ remove_column :advertisements, :title
601
+ remove_column :advertisements, :body
602
+ add_column :adverts, :name, :string, limit: 255
603
+
604
+ rename_table :advertisements, :adverts
605
+
606
+ add_index :adverts, [:id], unique: true, name: 'PRIMARY'
607
+ EOS
608
+ )
530
609
 
531
610
  ### Drop a table
532
611
 
@@ -536,9 +615,24 @@ RSpec.describe 'DeclareSchema Migration Generator' do
536
615
 
537
616
  # Dropping tables is where the automatic down-migration really comes in handy:
538
617
 
539
- up, down = Generators::DeclareSchema::Migration::Migrator.run
540
- expect(up).to eq("drop_table :adverts")
541
- expect(down.gsub(/,.*/m, '')).to eq("create_table \"adverts\"")
618
+ rails4_table_create = <<~EOS.strip
619
+ create_table "adverts", force: :cascade do |t|
620
+ t.string "name", limit: 255
621
+ end
622
+ EOS
623
+
624
+ rails5_table_create = <<~EOS.strip
625
+ create_table "adverts", id: :integer, force: :cascade do |t|
626
+ t.string "name", limit: 255
627
+ end
628
+ EOS
629
+
630
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to(
631
+ migrate_up(<<~EOS.strip)
632
+ drop_table :adverts
633
+ EOS
634
+ .and migrate_down(Rails::VERSION::MAJOR >= 5 ? rails5_table_create : rails4_table_create)
635
+ )
542
636
 
543
637
  ## STI
544
638
 
@@ -559,20 +653,26 @@ RSpec.describe 'DeclareSchema Migration Generator' do
559
653
  end
560
654
  class SuperFancyAdvert < FancyAdvert
561
655
  end
562
- up, down = Generators::DeclareSchema::Migration::Migrator.run
563
- expect(up.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
564
- add_column :adverts, :type, :string, limit: 255
565
- add_index :adverts, [:type], name: 'on_type'
566
- EOS
567
- expect(down.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
568
- remove_column :adverts, :type
569
- remove_index :adverts, name: :on_type rescue ActiveRecord::StatementInvalid
570
- EOS
656
+
657
+ up, _ = Generators::DeclareSchema::Migration::Migrator.run do |migrations|
658
+ expect(migrations).to(
659
+ migrate_up(<<~EOS.strip)
660
+ add_column :adverts, :type, :string, limit: 255
661
+
662
+ add_index :adverts, [:type], name: 'on_type'
663
+ EOS
664
+ .and migrate_down(<<~EOS.strip)
665
+ remove_column :adverts, :type
666
+
667
+ remove_index :adverts, name: :on_type rescue ActiveRecord::StatementInvalid
668
+ EOS
669
+ )
670
+ end
571
671
 
572
672
  Advert.field_specs.delete(:type)
573
673
  nuke_model_class(SuperFancyAdvert)
574
674
  nuke_model_class(FancyAdvert)
575
- Advert.index_specs.delete_if { |spec| spec.fields==["type"] }
675
+ Advert.index_definitions.delete_if { |spec| spec.fields==["type"] }
576
676
 
577
677
  ## Coping with multiple changes
578
678
 
@@ -600,16 +700,17 @@ RSpec.describe 'DeclareSchema Migration Generator' do
600
700
  body :text, null: true
601
701
  end
602
702
  end
603
- up, down = Generators::DeclareSchema::Migration::Migrator.run(adverts: { title: :name })
604
- expect(up).to eq(<<~EOS.strip)
605
- rename_column :adverts, :title, :name
606
- change_column :adverts, :name, :string, limit: 255, default: \"No Name\"
607
- EOS
608
703
 
609
- expect(down).to eq(<<~EOS.strip)
610
- rename_column :adverts, :name, :title
611
- change_column :adverts, :title, :string, limit: 255, default: \"Untitled\"
612
- EOS
704
+ expect(Generators::DeclareSchema::Migration::Migrator.run(adverts: { title: :name })).to(
705
+ migrate_up(<<~EOS.strip)
706
+ rename_column :adverts, :title, :name
707
+ change_column :adverts, :name, :string, limit: 255, default: "No Name"
708
+ EOS
709
+ .and migrate_down(<<~EOS.strip)
710
+ rename_column :adverts, :name, :title
711
+ change_column :adverts, :title, :string, limit: 255, default: "Untitled"
712
+ EOS
713
+ )
613
714
 
614
715
  ### Rename a table and add a column
615
716
 
@@ -621,13 +722,17 @@ RSpec.describe 'DeclareSchema Migration Generator' do
621
722
  created_at :datetime
622
723
  end
623
724
  end
624
- up = Generators::DeclareSchema::Migration::Migrator.run(adverts: :ads).first
625
- expect(up.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
626
- rename_table :adverts, :ads
627
- add_column :ads, :created_at, :datetime, null: false
628
- change_column :ads, :title, :string, limit: 255, null: false, default: \"Untitled\"
629
- add_index :ads, [:id], unique: true, name: 'PRIMARY_KEY'
630
- EOS
725
+
726
+ expect(Generators::DeclareSchema::Migration::Migrator.run(adverts: :ads)).to(
727
+ migrate_up(<<~EOS.strip)
728
+ rename_table :adverts, :ads
729
+
730
+ add_column :ads, :created_at, :datetime, null: false
731
+ change_column :ads, :title, :string, limit: 255, null: false, default: \"Untitled\"
732
+
733
+ add_index :ads, [:id], unique: true, name: 'PRIMARY'
734
+ EOS
735
+ )
631
736
 
632
737
  class Advert < ActiveRecord::Base
633
738
  fields do
@@ -648,11 +753,14 @@ RSpec.describe 'DeclareSchema Migration Generator' do
648
753
  end
649
754
  self.primary_key = "advert_id"
650
755
  end
651
- up, _down = Generators::DeclareSchema::Migration::Migrator.run(adverts: { id: :advert_id })
652
- expect(up.gsub(/\n+/, "\n")).to eq(<<~EOS.strip)
653
- rename_column :adverts, :id, :advert_id
654
- add_index :adverts, [:advert_id], unique: true, name: 'PRIMARY_KEY'
655
- EOS
756
+
757
+ expect(Generators::DeclareSchema::Migration::Migrator.run(adverts: { id: :advert_id })).to(
758
+ migrate_up(<<~EOS.strip)
759
+ rename_column :adverts, :id, :advert_id
760
+
761
+ add_index :adverts, [:advert_id], unique: true, name: 'PRIMARY'
762
+ EOS
763
+ )
656
764
 
657
765
  nuke_model_class(Advert)
658
766
  ActiveRecord::Base.connection.execute("drop table `adverts`;")
@@ -691,7 +799,200 @@ RSpec.describe 'DeclareSchema Migration Generator' do
691
799
  expect(Ad.field_specs['company'].options[:validates].inspect).to eq("{:presence=>true, :uniqueness=>{:case_sensitive=>false}}")
692
800
  end
693
801
 
694
- if Rails::VERSION::MAJOR >= 5
802
+ describe 'serialize' do
803
+ before do
804
+ class Ad < ActiveRecord::Base
805
+ @serialize_args = []
806
+
807
+ class << self
808
+ attr_reader :serialize_args
809
+
810
+ def serialize(*args)
811
+ @serialize_args << args
812
+ end
813
+ end
814
+ end
815
+ end
816
+
817
+ describe 'untyped' do
818
+ it 'allows serialize: true' do
819
+ class Ad < ActiveRecord::Base
820
+ fields do
821
+ allow_list :text, limit: 0xFFFF, serialize: true
822
+ end
823
+ end
824
+
825
+ expect(Ad.serialize_args).to eq([[:allow_list]])
826
+ end
827
+
828
+ it 'converts defaults with .to_yaml' do
829
+ class Ad < ActiveRecord::Base
830
+ fields do
831
+ allow_list :string, limit: 255, serialize: true, null: true, default: []
832
+ allow_hash :string, limit: 255, serialize: true, null: true, default: {}
833
+ allow_string :string, limit: 255, serialize: true, null: true, default: ['abc']
834
+ allow_null :string, limit: 255, serialize: true, null: true, default: nil
835
+ end
836
+ end
837
+
838
+ expect(Ad.field_specs['allow_list'].default).to eq("--- []\n")
839
+ expect(Ad.field_specs['allow_hash'].default).to eq("--- {}\n")
840
+ expect(Ad.field_specs['allow_string'].default).to eq("---\n- abc\n")
841
+ expect(Ad.field_specs['allow_null'].default).to eq(nil)
842
+ end
843
+ end
844
+
845
+ describe 'Array' do
846
+ it 'allows serialize: Array' do
847
+ class Ad < ActiveRecord::Base
848
+ fields do
849
+ allow_list :string, limit: 255, serialize: Array, null: true
850
+ end
851
+ end
852
+
853
+ expect(Ad.serialize_args).to eq([[:allow_list, Array]])
854
+ end
855
+
856
+ it 'allows Array defaults' do
857
+ class Ad < ActiveRecord::Base
858
+ fields do
859
+ allow_list :string, limit: 255, serialize: Array, null: true, default: [2]
860
+ allow_string :string, limit: 255, serialize: Array, null: true, default: ['abc']
861
+ allow_empty :string, limit: 255, serialize: Array, null: true, default: []
862
+ allow_null :string, limit: 255, serialize: Array, null: true, default: nil
863
+ end
864
+ end
865
+
866
+ expect(Ad.field_specs['allow_list'].default).to eq("---\n- 2\n")
867
+ expect(Ad.field_specs['allow_string'].default).to eq("---\n- abc\n")
868
+ expect(Ad.field_specs['allow_empty'].default).to eq(nil)
869
+ expect(Ad.field_specs['allow_null'].default).to eq(nil)
870
+ end
871
+ end
872
+
873
+ describe 'Hash' do
874
+ it 'allows serialize: Hash' do
875
+ class Ad < ActiveRecord::Base
876
+ fields do
877
+ allow_list :string, limit: 255, serialize: Hash, null: true
878
+ end
879
+ end
880
+
881
+ expect(Ad.serialize_args).to eq([[:allow_list, Hash]])
882
+ end
883
+
884
+ it 'allows Hash defaults' do
885
+ class Ad < ActiveRecord::Base
886
+ fields do
887
+ allow_loc :string, limit: 255, serialize: Hash, null: true, default: { 'state' => 'CA' }
888
+ allow_hash :string, limit: 255, serialize: Hash, null: true, default: {}
889
+ allow_null :string, limit: 255, serialize: Hash, null: true, default: nil
890
+ end
891
+ end
892
+
893
+ expect(Ad.field_specs['allow_loc'].default).to eq("---\nstate: CA\n")
894
+ expect(Ad.field_specs['allow_hash'].default).to eq(nil)
895
+ expect(Ad.field_specs['allow_null'].default).to eq(nil)
896
+ end
897
+ end
898
+
899
+ describe 'JSON' do
900
+ it 'allows serialize: JSON' do
901
+ class Ad < ActiveRecord::Base
902
+ fields do
903
+ allow_list :string, limit: 255, serialize: JSON
904
+ end
905
+ end
906
+
907
+ expect(Ad.serialize_args).to eq([[:allow_list, JSON]])
908
+ end
909
+
910
+ it 'allows JSON defaults' do
911
+ class Ad < ActiveRecord::Base
912
+ fields do
913
+ allow_hash :string, limit: 255, serialize: JSON, null: true, default: { 'state' => 'CA' }
914
+ allow_empty_array :string, limit: 255, serialize: JSON, null: true, default: []
915
+ allow_empty_hash :string, limit: 255, serialize: JSON, null: true, default: {}
916
+ allow_null :string, limit: 255, serialize: JSON, null: true, default: nil
917
+ end
918
+ end
919
+
920
+ expect(Ad.field_specs['allow_hash'].default).to eq("{\"state\":\"CA\"}")
921
+ expect(Ad.field_specs['allow_empty_array'].default).to eq("[]")
922
+ expect(Ad.field_specs['allow_empty_hash'].default).to eq("{}")
923
+ expect(Ad.field_specs['allow_null'].default).to eq(nil)
924
+ end
925
+ end
926
+
927
+ class ValueClass
928
+ delegate :present?, :inspect, to: :@value
929
+
930
+ def initialize(value)
931
+ @value = value
932
+ end
933
+
934
+ class << self
935
+ def dump(object)
936
+ if object&.present?
937
+ object.inspect
938
+ end
939
+ end
940
+
941
+ def load(serialized)
942
+ if serialized
943
+ raise 'not used ???'
944
+ end
945
+ end
946
+ end
947
+ end
948
+
949
+ describe 'custom coder' do
950
+ it 'allows serialize: ValueClass' do
951
+ class Ad < ActiveRecord::Base
952
+ fields do
953
+ allow_list :string, limit: 255, serialize: ValueClass
954
+ end
955
+ end
956
+
957
+ expect(Ad.serialize_args).to eq([[:allow_list, ValueClass]])
958
+ end
959
+
960
+ it 'allows ValueClass defaults' do
961
+ class Ad < ActiveRecord::Base
962
+ fields do
963
+ allow_hash :string, limit: 255, serialize: ValueClass, null: true, default: ValueClass.new([2])
964
+ allow_empty_array :string, limit: 255, serialize: ValueClass, null: true, default: ValueClass.new([])
965
+ allow_null :string, limit: 255, serialize: ValueClass, null: true, default: nil
966
+ end
967
+ end
968
+
969
+ expect(Ad.field_specs['allow_hash'].default).to eq("[2]")
970
+ expect(Ad.field_specs['allow_empty_array'].default).to eq(nil)
971
+ expect(Ad.field_specs['allow_null'].default).to eq(nil)
972
+ end
973
+ end
974
+
975
+ it 'disallows serialize: with a non-string column type' do
976
+ expect do
977
+ class Ad < ActiveRecord::Base
978
+ fields do
979
+ allow_list :integer, limit: 8, serialize: true
980
+ end
981
+ end
982
+ end.to raise_exception(ArgumentError, /must be :string or :text/)
983
+ end
984
+ end
985
+
986
+ context "for Rails #{Rails::VERSION::MAJOR}" do
987
+ if Rails::VERSION::MAJOR >= 5
988
+ let(:optional_true) { { optional: true } }
989
+ let(:optional_false) { { optional: false } }
990
+ else
991
+ let(:optional_true) { {} }
992
+ let(:optional_false) { {} }
993
+ end
994
+ let(:optional_flag) { { false => optional_false, true => optional_true } }
995
+
695
996
  describe 'belongs_to' do
696
997
  before do
697
998
  unless defined?(AdCategory)
@@ -718,10 +1019,10 @@ RSpec.describe 'DeclareSchema Migration Generator' do
718
1019
  reset_column_information
719
1020
  belongs_to :ad_category, optional: true
720
1021
  end
721
- expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional: true)
1022
+ expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional_true)
722
1023
  end
723
1024
 
724
- describe 'contradictory settings' do # contradictory settings are ok during migration
1025
+ describe 'contradictory settings' do # contradictory settings are ok--for example, during migration
725
1026
  it 'passes through optional: true, null: false' do
726
1027
  class AdvertBelongsTo < ActiveRecord::Base
727
1028
  self.table_name = 'adverts'
@@ -729,7 +1030,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
729
1030
  reset_column_information
730
1031
  belongs_to :ad_category, optional: true, null: false
731
1032
  end
732
- expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional: true)
1033
+ expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional_true)
733
1034
  expect(AdvertBelongsTo.field_specs['ad_category_id'].options&.[](:null)).to eq(false)
734
1035
  end
735
1036
 
@@ -740,7 +1041,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
740
1041
  reset_column_information
741
1042
  belongs_to :ad_category, optional: false, null: true
742
1043
  end
743
- expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional: false)
1044
+ expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional_false)
744
1045
  expect(AdvertBelongsTo.field_specs['ad_category_id'].options&.[](:null)).to eq(true)
745
1046
  end
746
1047
  end
@@ -754,7 +1055,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
754
1055
  belongs_to :ad_category, null: #{nullable}
755
1056
  end
756
1057
  EOS
757
- expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional: nullable)
1058
+ expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional_flag[nullable])
758
1059
  expect(AdvertBelongsTo.field_specs['ad_category_id'].options&.[](:null)).to eq(nullable)
759
1060
  end
760
1061
 
@@ -765,7 +1066,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
765
1066
  belongs_to :ad_category, optional: #{nullable}
766
1067
  end
767
1068
  EOS
768
- expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional: nullable)
1069
+ expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional_flag[nullable])
769
1070
  expect(AdvertBelongsTo.field_specs['ad_category_id'].options&.[](:null)).to eq(nullable)
770
1071
  end
771
1072
  end
@@ -781,7 +1082,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
781
1082
  end
782
1083
  end
783
1084
 
784
- Rails::Generators.invoke('declare_schema:migration', %w[-n -m])
1085
+ generate_migrations '-n', '-m'
785
1086
 
786
1087
  migrations = Dir.glob('db/migrate/*declare_schema_migration*.rb')
787
1088
  expect(migrations.size).to eq(1), migrations.inspect