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.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +14 -0
- data/CHANGELOG.md +36 -1
- data/Gemfile +1 -0
- data/Gemfile.lock +16 -14
- data/README.md +66 -0
- data/gemfiles/rails_4.gemfile +1 -0
- data/gemfiles/rails_5.gemfile +1 -0
- data/gemfiles/rails_6.gemfile +1 -0
- data/lib/declare_schema.rb +3 -1
- data/lib/declare_schema/extensions/active_record/fields_declaration.rb +2 -1
- data/lib/declare_schema/model.rb +59 -22
- data/lib/declare_schema/model/field_spec.rb +82 -26
- data/lib/declare_schema/model/foreign_key_definition.rb +73 -0
- data/lib/declare_schema/model/index_definition.rb +138 -0
- data/lib/declare_schema/model/table_options_definition.rb +83 -0
- data/lib/declare_schema/version.rb +1 -1
- data/lib/generators/declare_schema/migration/migrator.rb +105 -52
- data/spec/lib/declare_schema/api_spec.rb +7 -8
- data/spec/lib/declare_schema/generator_spec.rb +51 -10
- data/spec/lib/declare_schema/interactive_primary_key_spec.rb +16 -14
- data/spec/lib/declare_schema/migration_generator_spec.rb +514 -213
- data/spec/lib/declare_schema/model/index_definition_spec.rb +123 -0
- data/spec/lib/declare_schema/model/table_options_definition_spec.rb +84 -0
- data/spec/lib/generators/declare_schema/migration/migrator_spec.rb +28 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/support/acceptance_spec_helpers.rb +57 -0
- metadata +12 -7
- data/.dependabot/config.yml +0 -10
- data/lib/declare_schema/model/index_spec.rb +0 -175
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
40
|
-
|
41
|
-
$LOAD_PATH << "#{TESTAPP_PATH}/app/models"
|
40
|
+
load_models
|
42
41
|
|
43
|
-
|
42
|
+
if Rails::VERSION::MAJOR == 5
|
44
43
|
# TODO: get this to work on Travis for Rails 6
|
45
|
-
|
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
|
-
|
9
|
+
generate_model 'alpha/beta', 'one:string', 'two:integer'
|
10
10
|
|
11
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
42
|
-
|
43
|
-
|
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
|
-
|
46
|
+
### ensure it doesn't cause further migrations
|
46
47
|
|
47
|
-
|
48
|
-
|
49
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
-
|
57
|
-
|
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(
|
61
|
-
|
62
|
-
|
63
|
-
|
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
|
-
|
74
|
-
|
75
|
-
|
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
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
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
|
-
|
110
|
-
|
111
|
-
|
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
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
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.
|
135
|
-
|
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
|
-
|
147
|
-
|
148
|
-
|
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
|
-
|
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
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
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
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
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
|
-
|
243
|
-
|
244
|
-
|
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
|
-
|
258
|
-
|
259
|
-
|
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
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
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.
|
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
|
-
|
310
|
-
expect(
|
311
|
-
|
312
|
-
|
313
|
-
|
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.
|
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
|
-
|
326
|
-
expect(
|
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.
|
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
|
-
|
339
|
-
expect(
|
340
|
-
|
341
|
-
|
342
|
-
|
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.
|
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
|
-
|
359
|
-
expect(
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
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
|
-
|
516
|
-
expect(
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
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
|
-
|
540
|
-
|
541
|
-
|
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
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
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.
|
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(
|
610
|
-
|
611
|
-
|
612
|
-
|
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
|
-
|
625
|
-
expect(
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
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
|
-
|
652
|
-
expect(
|
653
|
-
|
654
|
-
|
655
|
-
|
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
|
-
|
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(
|
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(
|
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(
|
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(
|
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(
|
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
|
-
|
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
|