declare_schema 0.8.0.pre.5 → 0.10.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 +4 -4
- data/.github/workflows/declare_schema_build.yml +1 -1
- data/CHANGELOG.md +21 -1
- data/Gemfile.lock +1 -1
- data/README.md +91 -13
- data/lib/declare_schema.rb +46 -0
- data/lib/declare_schema/dsl.rb +39 -0
- data/lib/declare_schema/extensions/active_record/fields_declaration.rb +23 -4
- data/lib/declare_schema/model.rb +51 -59
- data/lib/declare_schema/model/column.rb +2 -0
- data/lib/declare_schema/model/field_spec.rb +11 -8
- data/lib/declare_schema/model/habtm_model_shim.rb +1 -1
- data/lib/declare_schema/version.rb +1 -1
- data/lib/generators/declare_schema/migration/migrator.rb +22 -33
- data/lib/generators/declare_schema/support/model.rb +4 -4
- data/spec/lib/declare_schema/api_spec.rb +7 -7
- data/spec/lib/declare_schema/field_declaration_dsl_spec.rb +41 -15
- data/spec/lib/declare_schema/field_spec_spec.rb +73 -22
- data/spec/lib/declare_schema/generator_spec.rb +3 -3
- data/spec/lib/declare_schema/interactive_primary_key_spec.rb +78 -26
- data/spec/lib/declare_schema/migration_generator_spec.rb +1989 -815
- data/spec/lib/declare_schema/model/column_spec.rb +47 -17
- data/spec/lib/declare_schema/model/foreign_key_definition_spec.rb +146 -57
- data/spec/lib/declare_schema/model/habtm_model_shim_spec.rb +3 -3
- data/spec/lib/declare_schema/model/index_definition_spec.rb +188 -77
- data/spec/lib/declare_schema/model/table_options_definition_spec.rb +75 -11
- data/spec/lib/declare_schema_spec.rb +101 -0
- data/spec/lib/generators/declare_schema/migration/migrator_spec.rb +12 -2
- metadata +7 -6
- data/test_responses.txt +0 -2
@@ -44,6 +44,8 @@ module DeclareSchema
|
|
44
44
|
if ActiveRecord::Base.connection.class.name.match?(/mysql/i)
|
45
45
|
types[:text][:limit] ||= 0xffff
|
46
46
|
types[:binary][:limit] ||= 0xffff
|
47
|
+
|
48
|
+
types[:varbinary] ||= { name: "varbinary" } # TODO: :varbinary is an Invoca addition to Rails; make it a configurable option
|
47
49
|
end
|
48
50
|
end
|
49
51
|
end
|
@@ -47,9 +47,9 @@ module DeclareSchema
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def initialize(model, name, type, position: 0, **options)
|
50
|
-
|
50
|
+
_defined_primary_key = model._defined_primary_key
|
51
51
|
|
52
|
-
name.to_s ==
|
52
|
+
name.to_s == _defined_primary_key and raise ArgumentError, "you may not provide a field spec for the primary key #{name.inspect}"
|
53
53
|
|
54
54
|
@model = model
|
55
55
|
@name = name.to_sym
|
@@ -58,18 +58,21 @@ module DeclareSchema
|
|
58
58
|
@position = position
|
59
59
|
@options = options.dup
|
60
60
|
|
61
|
-
@options.has_key?(:null) or @options[:null] =
|
61
|
+
@options.has_key?(:null) or @options[:null] = ::DeclareSchema.default_null
|
62
|
+
@options[:null].nil? and raise "null: must be provided for field #{model}##{@name}: #{@options.inspect} since ::DeclareSchema#default_null is set to 'nil'; do you want `null: false`?"
|
62
63
|
|
63
64
|
case @type
|
64
65
|
when :text
|
65
66
|
if self.class.mysql_text_limits?
|
66
67
|
@options[:default].nil? or raise MysqlTextMayNotHaveDefault, "when using MySQL, non-nil default may not be given for :text field #{model}##{@name}"
|
67
|
-
@options[:limit]
|
68
|
+
@options[:limit] ||= ::DeclareSchema.default_text_limit or
|
69
|
+
raise("limit: must be provided for :text field #{model}##{@name}: #{@options.inspect} since ::DeclareSchema#default_text_limit is set to 'nil'; do you want `limit: 0xffff_ffff`?")
|
70
|
+
@options[:limit] = self.class.round_up_mysql_text_limit(@options[:limit])
|
68
71
|
else
|
69
72
|
@options.delete(:limit)
|
70
73
|
end
|
71
74
|
when :string
|
72
|
-
@options[:limit] or raise "limit: must be
|
75
|
+
@options[:limit] ||= ::DeclareSchema.default_string_limit or raise "limit: must be provided for :string field #{model}##{@name}: #{@options.inspect} since ::DeclareSchema#default_string_limit is set to 'nil'; do you want `limit: 255`?"
|
73
76
|
when :bigint
|
74
77
|
@type = :integer
|
75
78
|
@options[:limit] = 8
|
@@ -96,15 +99,15 @@ module DeclareSchema
|
|
96
99
|
|
97
100
|
if @type.in?([:text, :string])
|
98
101
|
if ActiveRecord::Base.connection.class.name.match?(/mysql/i)
|
99
|
-
@options[:charset] ||= model.table_options[:charset] ||
|
100
|
-
@options[:collation] ||= model.table_options[:collation] ||
|
102
|
+
@options[:charset] ||= model.table_options[:charset] || ::DeclareSchema.default_charset
|
103
|
+
@options[:collation] ||= model.table_options[:collation] || ::DeclareSchema.default_collation
|
101
104
|
else
|
102
105
|
@options.delete(:charset)
|
103
106
|
@options.delete(:collation)
|
104
107
|
end
|
105
108
|
else
|
106
109
|
@options[:charset] and warn("charset may only given for :string and :text fields for SQL type #{@type} in field #{model}##{@name}")
|
107
|
-
@options[:collation] and
|
110
|
+
@options[:collation] and warn("collation may only given for :string and :text fields for SQL type #{@type} in field #{model}##{@name}")
|
108
111
|
end
|
109
112
|
|
110
113
|
@options = Hash[@options.sort_by { |k, _v| OPTION_INDEXES[k] || 9999 }]
|
@@ -9,29 +9,14 @@ module Generators
|
|
9
9
|
class Migrator
|
10
10
|
class Error < RuntimeError; end
|
11
11
|
|
12
|
-
DEFAULT_CHARSET = "utf8mb4"
|
13
|
-
DEFAULT_COLLATION = "utf8mb4_bin"
|
14
|
-
|
15
12
|
@ignore_models = []
|
16
13
|
@ignore_tables = []
|
17
14
|
@before_generating_migration_callback = nil
|
18
15
|
@active_record_class = ActiveRecord::Base
|
19
|
-
@default_charset = DEFAULT_CHARSET
|
20
|
-
@default_collation = DEFAULT_COLLATION
|
21
16
|
|
22
17
|
class << self
|
23
|
-
attr_accessor :ignore_models, :ignore_tables
|
24
|
-
attr_reader :active_record_class, :
|
25
|
-
|
26
|
-
def default_charset=(charset)
|
27
|
-
charset.is_a?(String) or raise ArgumentError, "charset must be a string (got #{charset.inspect})"
|
28
|
-
@default_charset = charset
|
29
|
-
end
|
30
|
-
|
31
|
-
def default_collation=(collation)
|
32
|
-
collation.is_a?(String) or raise ArgumentError, "collation must be a string (got #{collation.inspect})"
|
33
|
-
@default_collation = collation
|
34
|
-
end
|
18
|
+
attr_accessor :ignore_models, :ignore_tables
|
19
|
+
attr_reader :active_record_class, :before_generating_migration_callback
|
35
20
|
|
36
21
|
def active_record_class
|
37
22
|
@active_record_class.is_a?(Class) or @active_record_class = @active_record_class.to_s.constantize
|
@@ -58,6 +43,9 @@ module Generators
|
|
58
43
|
block or raise ArgumentError, 'A block is required when setting the before_generating_migration callback'
|
59
44
|
@before_generating_migration_callback = block
|
60
45
|
end
|
46
|
+
|
47
|
+
delegate :default_charset=, :default_collation=, :default_charset, :default_collation, to: ::DeclareSchema
|
48
|
+
deprecate :default_charset=, :default_collation=, :default_charset, :default_collation, deprecator: ActiveSupport::Deprecation.new('1.0', 'declare_schema')
|
61
49
|
end
|
62
50
|
|
63
51
|
def initialize(ambiguity_resolver = {})
|
@@ -279,18 +267,19 @@ module Generators
|
|
279
267
|
end
|
280
268
|
|
281
269
|
#{table_options_definition.alter_table_statement unless ActiveRecord::Base.connection.class.name.match?(/SQLite3Adapter/)}
|
282
|
-
#{create_indexes(model).join("\n")
|
283
|
-
#{create_constraints(model).join("\n")
|
270
|
+
#{create_indexes(model).join("\n") if ::DeclareSchema.default_generate_indexing}
|
271
|
+
#{create_constraints(model).join("\n") if ::DeclareSchema.default_generate_foreign_keys}
|
284
272
|
EOS
|
285
273
|
end
|
286
274
|
|
287
275
|
def create_table_options(model, disable_auto_increment)
|
288
|
-
|
276
|
+
primary_key = model._defined_primary_key
|
277
|
+
if primary_key.blank? || disable_auto_increment
|
289
278
|
"id: false"
|
290
|
-
elsif
|
279
|
+
elsif primary_key == "id"
|
291
280
|
"id: :bigint"
|
292
281
|
else
|
293
|
-
"primary_key: :#{
|
282
|
+
"primary_key: :#{primary_key}"
|
294
283
|
end
|
295
284
|
end
|
296
285
|
|
@@ -299,8 +288,8 @@ module Generators
|
|
299
288
|
{}
|
300
289
|
else
|
301
290
|
{
|
302
|
-
charset: model.table_options[:charset] ||
|
303
|
-
collation: model.table_options[:collation] ||
|
291
|
+
charset: model.table_options[:charset] || ::DeclareSchema.default_charset,
|
292
|
+
collation: model.table_options[:collation] || ::DeclareSchema.default_collation
|
304
293
|
}
|
305
294
|
end
|
306
295
|
end
|
@@ -323,18 +312,18 @@ module Generators
|
|
323
312
|
new_table_name = model.table_name
|
324
313
|
|
325
314
|
db_columns = model.connection.columns(current_table_name).index_by(&:name)
|
326
|
-
key_missing = db_columns[model.
|
327
|
-
if model.
|
328
|
-
db_columns.delete(model.
|
315
|
+
key_missing = db_columns[model._defined_primary_key].nil? && model._defined_primary_key.present?
|
316
|
+
if model._defined_primary_key.present?
|
317
|
+
db_columns.delete(model._defined_primary_key)
|
329
318
|
end
|
330
319
|
|
331
320
|
model_column_names = model.field_specs.keys.map(&:to_s)
|
332
321
|
db_column_names = db_columns.keys.map(&:to_s)
|
333
322
|
|
334
323
|
to_add = model_column_names - db_column_names
|
335
|
-
to_add += [model.
|
324
|
+
to_add += [model._defined_primary_key] if key_missing && model._defined_primary_key.present?
|
336
325
|
to_remove = db_column_names - model_column_names
|
337
|
-
to_remove -= [model.
|
326
|
+
to_remove -= [model._defined_primary_key.to_sym] if model._defined_primary_key.present?
|
338
327
|
|
339
328
|
to_rename = extract_column_renames!(to_add, to_remove, new_table_name)
|
340
329
|
|
@@ -414,7 +403,7 @@ module Generators
|
|
414
403
|
end
|
415
404
|
|
416
405
|
def change_indexes(model, old_table_name, to_remove)
|
417
|
-
|
406
|
+
::DeclareSchema.default_generate_indexing or return [[], []]
|
418
407
|
|
419
408
|
new_table_name = model.table_name
|
420
409
|
existing_indexes = ::DeclareSchema::Model::IndexDefinition.for_model(model, old_table_name)
|
@@ -455,7 +444,7 @@ module Generators
|
|
455
444
|
|
456
445
|
def change_foreign_key_constraints(model, old_table_name)
|
457
446
|
ActiveRecord::Base.connection.class.name.match?(/SQLite3Adapter/) and raise ArgumentError, 'SQLite does not support foreign keys'
|
458
|
-
|
447
|
+
::DeclareSchema.default_generate_foreign_keys or return [[], []]
|
459
448
|
|
460
449
|
new_table_name = model.table_name
|
461
450
|
existing_fks = ::DeclareSchema::Model::ForeignKeyDefinition.for_model(model, old_table_name)
|
@@ -584,8 +573,8 @@ module Generators
|
|
584
573
|
# TODO: rewrite this method to use charset and collation variables rather than manipulating strings. -Colin
|
585
574
|
def fix_mysql_charset_and_collation(dumped_schema)
|
586
575
|
if !dumped_schema['options: ']
|
587
|
-
dumped_schema.sub!('",', "\", options: \"DEFAULT CHARSET=#{
|
588
|
-
"COLLATE=#{
|
576
|
+
dumped_schema.sub!('",', "\", options: \"DEFAULT CHARSET=#{::DeclareSchema.default_charset} "+
|
577
|
+
"COLLATE=#{::DeclareSchema.default_collation}\",")
|
589
578
|
end
|
590
579
|
default_charset = dumped_schema[/CHARSET=(\w+)/, 1] or raise "unable to find charset in #{dumped_schema.inspect}"
|
591
580
|
default_collation = dumped_schema[/COLLATE=(\w+)/, 1] || default_collation_from_charset(default_charset) or
|
@@ -69,11 +69,11 @@ module DeclareSchema
|
|
69
69
|
def declare_model_fields_and_associations
|
70
70
|
buffer = ::DeclareSchema::Support::IndentedBuffer.new(indent: 2)
|
71
71
|
buffer.newline!
|
72
|
-
buffer << '
|
72
|
+
buffer << 'declare_schema do'
|
73
73
|
buffer.indent! do
|
74
74
|
field_attributes.each do |attribute|
|
75
|
-
decl = "%-#{max_attribute_length}s" % attribute.
|
76
|
-
attribute.
|
75
|
+
decl = "%-#{max_attribute_length}s" % attribute.type + ' ' +
|
76
|
+
attribute.name.to_sym.inspect +
|
77
77
|
case attribute.type.to_s
|
78
78
|
when 'string'
|
79
79
|
', limit: 255'
|
@@ -113,7 +113,7 @@ module DeclareSchema
|
|
113
113
|
end
|
114
114
|
|
115
115
|
def max_attribute_length
|
116
|
-
attributes.map { |attribute| attribute.
|
116
|
+
attributes.map { |attribute| attribute.type.length }.max
|
117
117
|
end
|
118
118
|
|
119
119
|
def field_attributes
|
@@ -20,9 +20,9 @@ RSpec.describe 'DeclareSchema API' do
|
|
20
20
|
expect_model_definition_to_eq('advert', <<~EOS)
|
21
21
|
class Advert < #{active_record_base_class}
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
body
|
23
|
+
declare_schema do
|
24
|
+
string :title, limit: 255
|
25
|
+
text :body
|
26
26
|
end
|
27
27
|
|
28
28
|
end
|
@@ -91,8 +91,8 @@ RSpec.describe 'DeclareSchema API' do
|
|
91
91
|
class AdvertWithRequiredTitle < ActiveRecord::Base
|
92
92
|
self.table_name = 'adverts'
|
93
93
|
|
94
|
-
|
95
|
-
|
94
|
+
declare_schema do
|
95
|
+
string :title, :required, limit: 255
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
@@ -110,8 +110,8 @@ RSpec.describe 'DeclareSchema API' do
|
|
110
110
|
class AdvertWithUniqueTitle < ActiveRecord::Base
|
111
111
|
self.table_name = 'adverts'
|
112
112
|
|
113
|
-
|
114
|
-
|
113
|
+
declare_schema do
|
114
|
+
string :title, :unique, limit: 255
|
115
115
|
end
|
116
116
|
end
|
117
117
|
|
@@ -3,29 +3,55 @@
|
|
3
3
|
require_relative '../../../lib/declare_schema/field_declaration_dsl'
|
4
4
|
|
5
5
|
RSpec.describe DeclareSchema::FieldDeclarationDsl do
|
6
|
-
|
7
|
-
|
6
|
+
let(:model) { TestModel.new }
|
7
|
+
subject { declared_class.new(model) }
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
context 'Using fields' do
|
10
|
+
before do
|
11
|
+
load File.expand_path('prepare_testapp.rb', __dir__)
|
12
12
|
|
13
|
-
|
13
|
+
class TestModel < ActiveRecord::Base
|
14
|
+
fields do
|
15
|
+
name :string, limit: 127
|
16
|
+
|
17
|
+
timestamps
|
18
|
+
end
|
14
19
|
end
|
15
20
|
end
|
16
|
-
end
|
17
21
|
|
18
|
-
|
19
|
-
|
22
|
+
it 'has fields' do
|
23
|
+
expect(TestModel.field_specs).to be_kind_of(Hash)
|
24
|
+
expect(TestModel.field_specs.keys).to eq(['name', 'created_at', 'updated_at'])
|
25
|
+
expect(TestModel.field_specs.values.map(&:type)).to eq([:string, :datetime, :datetime])
|
26
|
+
end
|
20
27
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
expect(TestModel.field_specs.values.map(&:type)).to eq([:string, :datetime, :datetime])
|
28
|
+
it 'stores limits' do
|
29
|
+
expect(TestModel.field_specs['name'].limit).to eq(127), TestModel.field_specs['name'].inspect
|
30
|
+
end
|
25
31
|
end
|
26
32
|
|
27
|
-
|
28
|
-
|
33
|
+
context 'Using declare_schema' do
|
34
|
+
before do
|
35
|
+
load File.expand_path('prepare_testapp.rb', __dir__)
|
36
|
+
|
37
|
+
class TestModel < ActiveRecord::Base
|
38
|
+
declare_schema do
|
39
|
+
string :name, limit: 127
|
40
|
+
|
41
|
+
timestamps
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'has fields' do
|
47
|
+
expect(TestModel.field_specs).to be_kind_of(Hash)
|
48
|
+
expect(TestModel.field_specs.keys).to eq(['name', 'created_at', 'updated_at'])
|
49
|
+
expect(TestModel.field_specs.values.map(&:type)).to eq([:string, :datetime, :datetime])
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'stores limits' do
|
53
|
+
expect(TestModel.field_specs['name'].limit).to eq(127), TestModel.field_specs['name'].inspect
|
54
|
+
end
|
29
55
|
end
|
30
56
|
|
31
57
|
# TODO: fill out remaining tests
|
@@ -6,7 +6,7 @@ rescue LoadError
|
|
6
6
|
end
|
7
7
|
|
8
8
|
RSpec.describe DeclareSchema::Model::FieldSpec do
|
9
|
-
let(:model) { double('model', table_options: {},
|
9
|
+
let(:model) { double('model', table_options: {}, _defined_primary_key: 'id') }
|
10
10
|
let(:col_spec) { double('col_spec', type: :string) }
|
11
11
|
|
12
12
|
before do
|
@@ -61,6 +61,15 @@ RSpec.describe DeclareSchema::Model::FieldSpec do
|
|
61
61
|
expect(subject.schema_attributes(col_spec)).to eq(type: :string, limit: 100, null: true)
|
62
62
|
end
|
63
63
|
end
|
64
|
+
|
65
|
+
it 'raises error when default_string_limit option is nil when not explicitly set in field spec' do
|
66
|
+
if defined?(Mysql2)
|
67
|
+
expect(::DeclareSchema).to receive(:default_string_limit) { nil }
|
68
|
+
expect do
|
69
|
+
described_class.new(model, :title, :string, null: true, charset: 'utf8mb4', position: 0)
|
70
|
+
end.to raise_error(/limit: must be provided for :string field/)
|
71
|
+
end
|
72
|
+
end
|
64
73
|
end
|
65
74
|
|
66
75
|
describe 'text' do
|
@@ -84,36 +93,66 @@ RSpec.describe DeclareSchema::Model::FieldSpec do
|
|
84
93
|
end
|
85
94
|
end
|
86
95
|
|
87
|
-
describe '
|
88
|
-
it '
|
89
|
-
|
90
|
-
|
96
|
+
describe 'limit' do
|
97
|
+
it 'uses default_text_limit option when not explicitly set in field spec' do
|
98
|
+
allow(::DeclareSchema).to receive(:default_text_limit) { 100 }
|
99
|
+
subject = described_class.new(model, :title, :text, null: true, charset: 'utf8mb4', position: 2)
|
100
|
+
if defined?(Mysql2)
|
101
|
+
expect(subject.schema_attributes(col_spec)).to eq(type: :text, limit: 255, null: true, charset: 'utf8mb4', collation: 'utf8mb4_bin')
|
102
|
+
else
|
103
|
+
expect(subject.schema_attributes(col_spec)).to eq(type: :text, null: true)
|
104
|
+
end
|
91
105
|
end
|
92
106
|
|
93
|
-
it '
|
94
|
-
|
95
|
-
|
107
|
+
it 'raises error when default_text_limit option is nil when not explicitly set in field spec' do
|
108
|
+
if defined?(Mysql2)
|
109
|
+
expect(::DeclareSchema).to receive(:default_text_limit) { nil }
|
110
|
+
expect do
|
111
|
+
described_class.new(model, :title, :text, null: true, charset: 'utf8mb4', position: 2)
|
112
|
+
end.to raise_error(/limit: must be provided for :text field/)
|
113
|
+
end
|
96
114
|
end
|
115
|
+
end
|
116
|
+
end
|
97
117
|
|
98
|
-
|
99
|
-
|
100
|
-
|
118
|
+
if defined?(Mysql2)
|
119
|
+
describe 'varbinary' do # TODO: :varbinary is an Invoca addition to Rails; make it a configurable option
|
120
|
+
it 'is supported' do
|
121
|
+
subject = described_class.new(model, :binary_dump, :varbinary, limit: 200, null: false, position: 2)
|
122
|
+
expect(subject.schema_attributes(col_spec)).to eq(type: :varbinary, limit: 200, null: false)
|
101
123
|
end
|
102
124
|
end
|
125
|
+
end
|
103
126
|
|
104
|
-
|
105
|
-
|
106
|
-
|
127
|
+
describe 'decimal' do
|
128
|
+
it 'allows precision: and scale:' do
|
129
|
+
subject = described_class.new(model, :quantity, :decimal, precision: 8, scale: 10, null: true, position: 3)
|
130
|
+
expect(subject.schema_attributes(col_spec)).to eq(type: :decimal, precision: 8, scale: 10, null: true)
|
131
|
+
end
|
107
132
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
133
|
+
it 'requires precision:' do
|
134
|
+
expect_any_instance_of(described_class).to receive(:warn).with(/precision: required for :decimal type/)
|
135
|
+
described_class.new(model, :quantity, :decimal, scale: 10, null: true, position: 3)
|
136
|
+
end
|
112
137
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
138
|
+
it 'requires scale:' do
|
139
|
+
expect_any_instance_of(described_class).to receive(:warn).with(/scale: required for :decimal type/)
|
140
|
+
described_class.new(model, :quantity, :decimal, precision: 8, null: true, position: 3)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
[:integer, :bigint, :string, :text, :binary, :datetime, :date, :time, (:varbinary if defined?(Mysql2))].compact.each do |t|
|
145
|
+
describe t.to_s do
|
146
|
+
let(:extra) { t == :string ? { limit: 100 } : {} }
|
147
|
+
|
148
|
+
it 'does not allow precision:' do
|
149
|
+
expect_any_instance_of(described_class).to receive(:warn).with(/precision: only allowed for :decimal type/)
|
150
|
+
described_class.new(model, :quantity, t, { precision: 8, null: true, position: 3 }.merge(extra))
|
151
|
+
end unless t == :datetime
|
152
|
+
|
153
|
+
it 'does not allow scale:' do
|
154
|
+
expect_any_instance_of(described_class).to receive(:warn).with(/scale: only allowed for :decimal type/)
|
155
|
+
described_class.new(model, :quantity, t, { scale: 10, null: true, position: 3 }.merge(extra))
|
117
156
|
end
|
118
157
|
end
|
119
158
|
end
|
@@ -175,5 +214,17 @@ RSpec.describe DeclareSchema::Model::FieldSpec do
|
|
175
214
|
it 'excludes non-sql options' do
|
176
215
|
expect(subject.sql_options).to eq(limit: 4, null: true, default: 0)
|
177
216
|
end
|
217
|
+
|
218
|
+
describe 'null' do
|
219
|
+
subject { described_class.new(model, :price, :integer, limit: 4, default: 0, position: 2, encrypt_using: ->(field) { field }) }
|
220
|
+
it 'uses default_null option when not explicitly set in field spec' do
|
221
|
+
expect(subject.sql_options).to eq(limit: 4, null: false, default: 0)
|
222
|
+
end
|
223
|
+
|
224
|
+
it 'raises error if default_null is set to nil when not explicitly set in field spec' do
|
225
|
+
expect(::DeclareSchema).to receive(:default_null) { nil }
|
226
|
+
expect { subject.sql_options }.to raise_error(/null: must be provided for field/)
|
227
|
+
end
|
228
|
+
end
|
178
229
|
end
|
179
230
|
end
|