declare_schema 0.6.2 → 0.8.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.
@@ -0,0 +1,122 @@
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 '.deserialize_default_value' do
63
+ require 'rails'
64
+
65
+ if ::Rails::VERSION::MAJOR >= 5
66
+ it 'deserializes :boolean' do
67
+ expect(described_class.deserialize_default_value(nil, :boolean, 'true')).to eq(true)
68
+ expect(described_class.deserialize_default_value(nil, :boolean, 'false')).to eq(false)
69
+ end
70
+
71
+ it 'deserializes :integer' do
72
+ expect(described_class.deserialize_default_value(nil, :integer, '12')).to eq(12)
73
+ end
74
+
75
+ it 'deserializes :json' do
76
+ expect(described_class.deserialize_default_value(nil, :json, '{}')).to eq({})
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ describe 'instance methods' do
83
+ before do
84
+ class ColumnTestModel < ActiveRecord::Base
85
+ fields do
86
+ title :string, limit: 127, null: false
87
+ count :integer, null: false
88
+ end
89
+ end
90
+ end
91
+ let(:model) { ColumnTestModel }
92
+ let(:type) { :integer }
93
+ let(:current_table_name) { model.table_name }
94
+ let(:column) { double("ActiveRecord Column",
95
+ name: 'count',
96
+ type: type,
97
+ limit: nil,
98
+ precision: nil,
99
+ scale: nil,
100
+ type_cast_from_database: nil,
101
+ null: false,
102
+ default: nil,
103
+ sql_type_metadata: {}) }
104
+ subject { described_class.new(model, current_table_name, column) }
105
+
106
+ describe '#type' do
107
+ it 'returns type' do
108
+ expect(subject.type).to eq(type)
109
+ end
110
+ end
111
+
112
+ describe '#schema_attributes' do
113
+ it 'returns a hash with relevant key/values' do
114
+ if defined?(Mysql2)
115
+ expect(subject.schema_attributes).to eq(type: :integer, null: false, limit: 4)
116
+ else
117
+ expect(subject.schema_attributes).to eq(type: :integer, null: false)
118
+ end
119
+ end
120
+ end
121
+ end
122
+ 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
- let(:mysql_longtext_limit) { 0xffff_ffff }
22
- let(:limit_option) do
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.6.2
4
+ version: 0.8.0.pre.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Invoca Development adapted from hobo_fields by Tom Locke
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-14 00:00:00.000000000 Z
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
@@ -93,7 +96,7 @@ homepage: https://github.com/Invoca/declare_schema
93
96
  licenses: []
94
97
  metadata:
95
98
  allowed_push_host: https://rubygems.org
96
- post_install_message:
99
+ post_install_message:
97
100
  rdoc_options: []
98
101
  require_paths:
99
102
  - lib
@@ -109,7 +112,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
109
112
  version: 1.3.6
110
113
  requirements: []
111
114
  rubygems_version: 3.0.3
112
- signing_key:
115
+ signing_key:
113
116
  specification_version: 4
114
117
  summary: Database schema declaration and migration generator for Rails
115
118
  test_files: []