declare_schema 0.6.1 → 0.7.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/CHANGELOG.md +38 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +58 -54
- data/lib/declare_schema/field_declaration_dsl.rb +3 -4
- data/lib/declare_schema/model.rb +1 -2
- data/lib/declare_schema/model/column.rb +167 -0
- data/lib/declare_schema/model/field_spec.rb +59 -143
- data/lib/declare_schema/model/foreign_key_definition.rb +36 -25
- data/lib/declare_schema/version.rb +1 -1
- data/lib/generators/declare_schema/migration/migration_generator.rb +1 -1
- data/lib/generators/declare_schema/migration/migrator.rb +111 -133
- data/spec/lib/declare_schema/field_declaration_dsl_spec.rb +1 -1
- data/spec/lib/declare_schema/field_spec_spec.rb +142 -38
- data/spec/lib/declare_schema/migration_generator_spec.rb +73 -69
- data/spec/lib/declare_schema/model/column_spec.rb +141 -0
- data/spec/lib/declare_schema/model/foreign_key_definition_spec.rb +93 -0
- data/spec/lib/generators/declare_schema/migration/migrator_spec.rb +2 -11
- metadata +5 -2
@@ -0,0 +1,141 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'mysql2'
|
7
|
+
rescue LoadError
|
8
|
+
end
|
9
|
+
|
10
|
+
require_relative '../../../../lib/declare_schema/model/column'
|
11
|
+
|
12
|
+
RSpec.describe DeclareSchema::Model::Column do
|
13
|
+
before do
|
14
|
+
load File.expand_path('../prepare_testapp.rb', __dir__)
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'class methods' do
|
18
|
+
describe '.native_type?' do
|
19
|
+
if Rails::VERSION::MAJOR >= 5
|
20
|
+
let(:native_types) { [:string, :text, :integer, :float, :decimal, :datetime, :time, :date, :binary, :boolean, :json] }
|
21
|
+
else
|
22
|
+
let(:native_types) { [:string, :text, :integer, :float, :decimal, :datetime, :time, :date, :binary, :boolean] }
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'is falsey for :primary_key' do
|
26
|
+
expect(described_class.native_type?(:primary_key)).to be_falsey
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'is truthy for native types' do
|
30
|
+
native_types.each do |type|
|
31
|
+
expect(described_class.native_type?(type)).to be_truthy, type.inspect
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'is falsey for other types' do
|
36
|
+
[:email, :url].each do |type|
|
37
|
+
expect(described_class.native_type?(type)).to be_falsey
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '.native_types' do
|
43
|
+
subject { described_class.native_types }
|
44
|
+
|
45
|
+
it 'returns the native type for :primary_key' do
|
46
|
+
expect(subject[:primary_key]).to match(/auto_increment PRIMARY KEY|PRIMARY KEY AUTOINCREMENT NOT NULL/)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'returns the native type for :string' do
|
50
|
+
expect(subject.dig(:string, :name)).to eq('varchar')
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'returns the native type for :integer' do
|
54
|
+
expect(subject.dig(:integer, :name)).to match(/int/)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'returns the native type for :datetime' do
|
58
|
+
expect(subject.dig(:datetime, :name)).to eq('datetime')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '.sql_type' do
|
63
|
+
it 'returns the sql type for :string' do
|
64
|
+
expect(described_class.sql_type(:string)).to eq(:string)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'returns the sql type for :integer' do
|
68
|
+
expect(described_class.sql_type(:integer)).to match(:integer)
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'returns the sql type for :datetime' do
|
72
|
+
expect(described_class.sql_type(:datetime)).to eq(:datetime)
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'raises UnknownSqlType' do
|
76
|
+
expect do
|
77
|
+
described_class.sql_type(:email)
|
78
|
+
end.to raise_exception(::DeclareSchema::UnknownSqlTypeError, /:email for type :email/)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe '.deserialize_default_value' do
|
83
|
+
require 'rails'
|
84
|
+
|
85
|
+
if ::Rails::VERSION::MAJOR >= 5
|
86
|
+
it 'deserializes :boolean' do
|
87
|
+
expect(described_class.deserialize_default_value(nil, :boolean, 'true')).to eq(true)
|
88
|
+
expect(described_class.deserialize_default_value(nil, :boolean, 'false')).to eq(false)
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'deserializes :integer' do
|
92
|
+
expect(described_class.deserialize_default_value(nil, :integer, '12')).to eq(12)
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'deserializes :json' do
|
96
|
+
expect(described_class.deserialize_default_value(nil, :json, '{}')).to eq({})
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe 'instance methods' do
|
103
|
+
before do
|
104
|
+
class ColumnTestModel < ActiveRecord::Base
|
105
|
+
fields do
|
106
|
+
title :string, limit: 127, null: false
|
107
|
+
count :integer, null: false
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
let(:model) { ColumnTestModel }
|
112
|
+
let(:current_table_name) { model.table_name }
|
113
|
+
let(:column) { double("ActiveRecord Column",
|
114
|
+
name: 'count',
|
115
|
+
type: :integer,
|
116
|
+
limit: nil,
|
117
|
+
precision: nil,
|
118
|
+
scale: nil,
|
119
|
+
type_cast_from_database: nil,
|
120
|
+
null: false,
|
121
|
+
default: nil,
|
122
|
+
sql_type_metadata: {}) }
|
123
|
+
subject { described_class.new(model, current_table_name, column) }
|
124
|
+
|
125
|
+
describe '#sql_type' do
|
126
|
+
it 'returns sql type' do
|
127
|
+
expect(subject.sql_type).to match(/int/)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe '#schema_attributes' do
|
132
|
+
it 'returns a hash with relevant key/values' do
|
133
|
+
if defined?(Mysql2)
|
134
|
+
expect(subject.schema_attributes).to eq(type: :integer, null: false, limit: 4)
|
135
|
+
else
|
136
|
+
expect(subject.schema_attributes).to eq(type: :integer, null: false)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../../../lib/declare_schema/model/foreign_key_definition'
|
4
|
+
|
5
|
+
RSpec.describe DeclareSchema::Model::ForeignKeyDefinition do
|
6
|
+
before do
|
7
|
+
load File.expand_path('../prepare_testapp.rb', __dir__)
|
8
|
+
|
9
|
+
class Network < ActiveRecord::Base
|
10
|
+
fields do
|
11
|
+
name :string, limit: 127, index: true
|
12
|
+
|
13
|
+
timestamps
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:model_class) { Network }
|
19
|
+
|
20
|
+
describe 'instance methods' do
|
21
|
+
let(:connection) { instance_double(ActiveRecord::Base.connection.class) }
|
22
|
+
let(:model) { instance_double('Model', table_name: 'models', connection: connection) }
|
23
|
+
let(:foreign_key) { :network_id }
|
24
|
+
let(:options) { {} }
|
25
|
+
subject { described_class.new(model, foreign_key, options)}
|
26
|
+
|
27
|
+
before do
|
28
|
+
allow(connection).to receive(:index_name).with('models', column: 'network_id') { 'on_network_id' }
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#initialize' do
|
32
|
+
it 'normalizes symbols to strings' do
|
33
|
+
expect(subject.foreign_key).to eq('network_id')
|
34
|
+
expect(subject.parent_table_name).to eq('networks')
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'when most options passed' do
|
38
|
+
let(:options) { { parent_table: :networks, foreign_key: :the_network_id, index_name: :index_on_network_id } }
|
39
|
+
|
40
|
+
it 'normalizes symbols to strings' do
|
41
|
+
expect(subject.foreign_key).to eq('network_id')
|
42
|
+
expect(subject.foreign_key_name).to eq('the_network_id')
|
43
|
+
expect(subject.parent_table_name).to eq('networks')
|
44
|
+
expect(subject.foreign_key).to eq('network_id')
|
45
|
+
expect(subject.constraint_name).to eq('index_on_network_id')
|
46
|
+
expect(subject.on_delete_cascade).to be_falsey
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'when all options passed' do
|
51
|
+
let(:foreign_key) { nil }
|
52
|
+
let(:options) { { parent_table: :networks, foreign_key: :the_network_id, index_name: :index_on_network_id,
|
53
|
+
constraint_name: :constraint_1, dependent: :delete } }
|
54
|
+
|
55
|
+
it 'normalizes symbols to strings' do
|
56
|
+
expect(subject.foreign_key).to be_nil
|
57
|
+
expect(subject.foreign_key_name).to eq('the_network_id')
|
58
|
+
expect(subject.parent_table_name).to eq('networks')
|
59
|
+
expect(subject.constraint_name).to eq('constraint_1')
|
60
|
+
expect(subject.on_delete_cascade).to be_truthy
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe '#to_add_statement' do
|
66
|
+
it 'returns add_foreign_key command' do
|
67
|
+
expect(subject.to_add_statement).to eq('add_foreign_key("models", "networks", column: "network_id", name: "on_network_id")')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe 'class << self' do
|
73
|
+
let(:connection) { instance_double(ActiveRecord::Base.connection.class) }
|
74
|
+
let(:model) { instance_double('Model', table_name: 'models', connection: connection) }
|
75
|
+
let(:old_table_name) { 'networks' }
|
76
|
+
before do
|
77
|
+
allow(connection).to receive(:quote_table_name).with('networks') { 'networks' }
|
78
|
+
allow(connection).to receive(:select_rows) { [['CONSTRAINT `constraint` FOREIGN KEY (`network_id`) REFERENCES `networks` (`id`)']] }
|
79
|
+
allow(connection).to receive(:index_name).with('models', column: 'network_id') { }
|
80
|
+
end
|
81
|
+
|
82
|
+
describe '.for_model' do
|
83
|
+
subject { described_class.for_model(model, old_table_name) }
|
84
|
+
|
85
|
+
it 'returns new object' do
|
86
|
+
expect(subject.size).to eq(1), subject.inspect
|
87
|
+
expect(subject.first).to be_kind_of(described_class)
|
88
|
+
expect(subject.first.foreign_key).to eq('network_id')
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
# TODO: fill out remaining tests
|
93
|
+
end
|
@@ -18,17 +18,8 @@ module Generators
|
|
18
18
|
subject { described_class.new }
|
19
19
|
|
20
20
|
describe 'format_options' do
|
21
|
-
|
22
|
-
|
23
|
-
if defined?(Mysql2)
|
24
|
-
["limit: #{mysql_longtext_limit}"]
|
25
|
-
else
|
26
|
-
[]
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'returns text limits if supported' do
|
31
|
-
expect(subject.format_options({ limit: mysql_longtext_limit }, :text)).to eq(limit_option)
|
21
|
+
it 'returns an array of option .inspect strings, with symbols using the modern : hash notation' do
|
22
|
+
expect(subject.format_options({ limit: 4, 'key' => 'value "quoted"' })).to eq(["limit: 4", '"key" => "value \"quoted\""'])
|
32
23
|
end
|
33
24
|
end
|
34
25
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: declare_schema
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Invoca Development adapted from hobo_fields by Tom Locke
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-02-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -61,6 +61,7 @@ files:
|
|
61
61
|
- lib/declare_schema/extensions/module.rb
|
62
62
|
- lib/declare_schema/field_declaration_dsl.rb
|
63
63
|
- lib/declare_schema/model.rb
|
64
|
+
- lib/declare_schema/model/column.rb
|
64
65
|
- lib/declare_schema/model/field_spec.rb
|
65
66
|
- lib/declare_schema/model/foreign_key_definition.rb
|
66
67
|
- lib/declare_schema/model/index_definition.rb
|
@@ -82,6 +83,8 @@ files:
|
|
82
83
|
- spec/lib/declare_schema/generator_spec.rb
|
83
84
|
- spec/lib/declare_schema/interactive_primary_key_spec.rb
|
84
85
|
- spec/lib/declare_schema/migration_generator_spec.rb
|
86
|
+
- spec/lib/declare_schema/model/column_spec.rb
|
87
|
+
- spec/lib/declare_schema/model/foreign_key_definition_spec.rb
|
85
88
|
- spec/lib/declare_schema/model/index_definition_spec.rb
|
86
89
|
- spec/lib/declare_schema/model/table_options_definition_spec.rb
|
87
90
|
- spec/lib/declare_schema/prepare_testapp.rb
|