declare_schema 0.9.0 → 0.11.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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/declare_schema_build.yml +1 -1
  3. data/CHANGELOG.md +32 -0
  4. data/Gemfile.lock +1 -1
  5. data/README.md +12 -2
  6. data/lib/declare_schema.rb +12 -1
  7. data/lib/declare_schema/dsl.rb +39 -0
  8. data/lib/declare_schema/extensions/active_record/fields_declaration.rb +22 -3
  9. data/lib/declare_schema/model.rb +4 -6
  10. data/lib/declare_schema/model/column.rb +1 -1
  11. data/lib/declare_schema/model/foreign_key_definition.rb +6 -11
  12. data/lib/declare_schema/model/index_definition.rb +1 -20
  13. data/lib/declare_schema/schema_change/all.rb +22 -0
  14. data/lib/declare_schema/schema_change/base.rb +45 -0
  15. data/lib/declare_schema/schema_change/column_add.rb +27 -0
  16. data/lib/declare_schema/schema_change/column_change.rb +32 -0
  17. data/lib/declare_schema/schema_change/column_remove.rb +20 -0
  18. data/lib/declare_schema/schema_change/column_rename.rb +23 -0
  19. data/lib/declare_schema/schema_change/foreign_key_add.rb +25 -0
  20. data/lib/declare_schema/schema_change/foreign_key_remove.rb +20 -0
  21. data/lib/declare_schema/schema_change/index_add.rb +33 -0
  22. data/lib/declare_schema/schema_change/index_remove.rb +20 -0
  23. data/lib/declare_schema/schema_change/primary_key_change.rb +33 -0
  24. data/lib/declare_schema/schema_change/table_add.rb +37 -0
  25. data/lib/declare_schema/schema_change/table_change.rb +36 -0
  26. data/lib/declare_schema/schema_change/table_remove.rb +22 -0
  27. data/lib/declare_schema/schema_change/table_rename.rb +22 -0
  28. data/lib/declare_schema/version.rb +1 -1
  29. data/lib/generators/declare_schema/migration/USAGE +14 -24
  30. data/lib/generators/declare_schema/migration/migration_generator.rb +40 -38
  31. data/lib/generators/declare_schema/migration/migrator.rb +175 -177
  32. data/lib/generators/declare_schema/migration/templates/migration.rb.erb +3 -3
  33. data/lib/generators/declare_schema/support/model.rb +4 -4
  34. data/spec/lib/declare_schema/api_spec.rb +8 -8
  35. data/spec/lib/declare_schema/field_declaration_dsl_spec.rb +41 -15
  36. data/spec/lib/declare_schema/field_spec_spec.rb +2 -2
  37. data/spec/lib/declare_schema/generator_spec.rb +5 -5
  38. data/spec/lib/declare_schema/interactive_primary_key_spec.rb +117 -28
  39. data/spec/lib/declare_schema/migration_generator_spec.rb +1990 -843
  40. data/spec/lib/declare_schema/model/column_spec.rb +49 -23
  41. data/spec/lib/declare_schema/model/foreign_key_definition_spec.rb +158 -57
  42. data/spec/lib/declare_schema/model/habtm_model_shim_spec.rb +0 -2
  43. data/spec/lib/declare_schema/model/index_definition_spec.rb +189 -78
  44. data/spec/lib/declare_schema/model/table_options_definition_spec.rb +75 -11
  45. data/spec/lib/declare_schema/schema_change/base_spec.rb +75 -0
  46. data/spec/lib/declare_schema/schema_change/column_add_spec.rb +30 -0
  47. data/spec/lib/declare_schema/schema_change/column_change_spec.rb +33 -0
  48. data/spec/lib/declare_schema/schema_change/column_remove_spec.rb +30 -0
  49. data/spec/lib/declare_schema/schema_change/column_rename_spec.rb +28 -0
  50. data/spec/lib/declare_schema/schema_change/foreign_key_add_spec.rb +29 -0
  51. data/spec/lib/declare_schema/schema_change/foreign_key_remove_spec.rb +29 -0
  52. data/spec/lib/declare_schema/schema_change/index_add_spec.rb +56 -0
  53. data/spec/lib/declare_schema/schema_change/index_remove_spec.rb +29 -0
  54. data/spec/lib/declare_schema/schema_change/primary_key_change_spec.rb +69 -0
  55. data/spec/lib/declare_schema/schema_change/table_add_spec.rb +50 -0
  56. data/spec/lib/declare_schema/schema_change/table_change_spec.rb +30 -0
  57. data/spec/lib/declare_schema/schema_change/table_remove_spec.rb +27 -0
  58. data/spec/lib/declare_schema/schema_change/table_rename_spec.rb +27 -0
  59. data/spec/lib/generators/declare_schema/migration/migrator_spec.rb +59 -11
  60. data/spec/spec_helper.rb +1 -1
  61. data/spec/support/acceptance_spec_helpers.rb +2 -2
  62. metadata +35 -6
  63. data/test_responses.txt +0 -2
@@ -8,19 +8,20 @@ end
8
8
  require_relative '../../../../lib/declare_schema/model/table_options_definition'
9
9
 
10
10
  RSpec.describe DeclareSchema::Model::TableOptionsDefinition do
11
- before do
12
- load File.expand_path('../prepare_testapp.rb', __dir__)
11
+ let(:model_class) { TableOptionsDefinitionTestModel }
12
+
13
+ context 'Using fields' do
14
+ before do
15
+ load File.expand_path('../prepare_testapp.rb', __dir__)
13
16
 
14
- class TableOptionsDefinitionTestModel < ActiveRecord::Base
15
- fields do
16
- name :string, limit: 127, index: true
17
+ class TableOptionsDefinitionTestModel < ActiveRecord::Base
18
+ fields do
19
+ name :string, limit: 127, index: true
20
+ end
17
21
  end
18
22
  end
19
- end
20
23
 
21
- let(:model_class) { TableOptionsDefinitionTestModel }
22
-
23
- context 'instance methods' do
24
+ context 'instance methods' do
24
25
  let(:table_options) { { charset: "utf8", collation: "utf8_general"} }
25
26
  let(:model) { described_class.new('table_options_definition_test_models', table_options) }
26
27
 
@@ -50,8 +51,7 @@ RSpec.describe DeclareSchema::Model::TableOptionsDefinition do
50
51
  end
51
52
  end
52
53
 
53
-
54
- context 'class << self' do
54
+ context 'class << self' do
55
55
  describe '#for_model' do
56
56
  context 'when database migrated' do
57
57
  let(:options) do
@@ -70,5 +70,69 @@ RSpec.describe DeclareSchema::Model::TableOptionsDefinition do
70
70
  it { should eq(described_class.new(model_class.table_name, options)) }
71
71
  end
72
72
  end
73
+ end
74
+ end
75
+
76
+ context 'Using declare_schema' do
77
+ before do
78
+ load File.expand_path('../prepare_testapp.rb', __dir__)
79
+
80
+ class TableOptionsDefinitionTestModel < ActiveRecord::Base
81
+ declare_schema do
82
+ string :name, limit: 127, index: true
83
+ end
84
+ end
85
+ end
86
+
87
+ context 'instance methods' do
88
+ let(:table_options) { { charset: "utf8", collation: "utf8_general"} }
89
+ let(:model) { described_class.new('table_options_definition_test_models', table_options) }
90
+
91
+ describe '#to_key' do
92
+ subject { model.to_key }
93
+ it { should eq(['table_options_definition_test_models', '{:charset=>"utf8", :collation=>"utf8_general"}']) }
94
+ end
95
+
96
+ describe '#settings' do
97
+ subject { model.settings }
98
+ it { should eq("CHARACTER SET utf8 COLLATE utf8_general") }
99
+ end
100
+
101
+ describe '#hash' do
102
+ subject { model.hash }
103
+ it { should eq(['table_options_definition_test_models', '{:charset=>"utf8", :collation=>"utf8_general"}'].hash) }
104
+ end
105
+
106
+ describe '#to_s' do
107
+ subject { model.to_s }
108
+ it { should eq("CHARACTER SET utf8 COLLATE utf8_general") }
109
+ end
110
+
111
+ describe '#alter_table_statement' do
112
+ subject { model.alter_table_statement }
113
+ it { should match(/execute "ALTER TABLE .*table_options_definition_test_models.* CHARACTER SET utf8 COLLATE utf8_general"/) }
114
+ end
115
+ end
116
+
117
+ context 'class << self' do
118
+ describe '#for_model' do
119
+ context 'when database migrated' do
120
+ let(:options) do
121
+ if defined?(Mysql2)
122
+ { charset: "utf8mb4", collation: "utf8mb4_bin" }
123
+ else
124
+ { }
125
+ end
126
+ end
127
+ subject { described_class.for_model(model_class) }
128
+
129
+ before do
130
+ generate_migrations '-n', '-m'
131
+ end
132
+
133
+ it { should eq(described_class.new(model_class.table_name, options)) }
134
+ end
135
+ end
136
+ end
73
137
  end
74
138
  end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../../lib/declare_schema/schema_change/base'
4
+
5
+ RSpec.describe DeclareSchema::SchemaChange::Base do
6
+ before do
7
+ load File.expand_path('../prepare_testapp.rb', __dir__)
8
+ end
9
+
10
+ before :all do
11
+ class ChangeDefault < described_class
12
+ attr_reader :up_command, :down_command
13
+
14
+ def initialize(up:, down:)
15
+ @up_command = up
16
+ @down_command = down
17
+ end
18
+ end
19
+
20
+ class ChangeOverride < described_class
21
+ attr_reader :up_command, :down_command
22
+
23
+ def initialize(up:, down:)
24
+ @up_command = up
25
+ @down_command = down
26
+ end
27
+ end
28
+ end
29
+
30
+ describe 'class methods' do
31
+ describe 'format_options' do
32
+ subject { { limit: 8, 'key' => 'value', subhash: { subkey: :subvalue } } }
33
+
34
+ it 'formats using Ruby 2.0 symbol notation' do
35
+ expect(described_class.format_options(subject)).to eq(['limit: 8', '"key" => "value"', 'subhash: { subkey: :subvalue }'])
36
+ end
37
+ end
38
+ end
39
+
40
+ describe 'instance methods' do
41
+ describe '#up/#down' do
42
+ context 'with single-line commands' do
43
+ subject { ChangeDefault.new(up: "up_command", down: "down_command" )}
44
+
45
+ describe '#up' do
46
+ it 'responds with command and single spacing' do
47
+ expect(subject.up).to eq("up_command\n")
48
+ end
49
+ end
50
+
51
+ describe '#down' do
52
+ it 'responds with command and single spacing' do
53
+ expect(subject.down).to eq("down_command\n")
54
+ end
55
+ end
56
+ end
57
+
58
+ context 'with multi-line commands' do
59
+ subject { ChangeDefault.new(up: "up_command 1\nup_command 2", down: "down_command 1\ndown_command 2" )}
60
+
61
+ describe '#up' do
62
+ it 'responds with command and double spacing' do
63
+ expect(subject.up).to eq("up_command 1\nup_command 2\n\n")
64
+ end
65
+ end
66
+
67
+ describe '#down' do
68
+ it 'responds with command and spacing' do
69
+ expect(subject.down).to eq("down_command 1\ndown_command 2\n\n")
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../../lib/declare_schema/schema_change/column_add'
4
+
5
+ RSpec.describe DeclareSchema::SchemaChange::ColumnAdd do
6
+ before do
7
+ load File.expand_path('../prepare_testapp.rb', __dir__)
8
+ end
9
+
10
+ let(:table_name) { 'networks' }
11
+ let(:column_name) { 'title' }
12
+ let(:column_type) { :integer }
13
+ let(:column_options) { { limit: 8 } }
14
+ let(:column_options_string) { "limit: 8" }
15
+ subject { described_class.new(table_name, column_name, column_type, column_options) }
16
+
17
+ describe '#up/down' do
18
+ describe '#up' do
19
+ it 'responds with command' do
20
+ expect(subject.up).to eq("add_column :#{table_name}, :#{column_name}, :#{column_type}, #{column_options_string}\n")
21
+ end
22
+ end
23
+
24
+ describe '#down' do
25
+ it 'responds with command' do
26
+ expect(subject.down).to eq("remove_column :#{table_name}, :#{column_name}\n")
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../../lib/declare_schema/schema_change/column_change'
4
+
5
+ RSpec.describe DeclareSchema::SchemaChange::ColumnChange do
6
+ before do
7
+ load File.expand_path('../prepare_testapp.rb', __dir__)
8
+ end
9
+
10
+ let(:table_name) { 'networks' }
11
+ let(:column_name) { 'title' }
12
+ let(:old_type) { :string }
13
+ let(:old_options) { { limit: 255, null: false } }
14
+ let(:old_options_string) { "limit: 255, null: false" }
15
+ let(:new_type) { :text }
16
+ let(:new_options) { { limit: 0xffff, null: true } }
17
+ let(:new_options_string) { "limit: 65535, null: true" }
18
+ subject { described_class.new(table_name, column_name, old_type: old_type, old_options: old_options, new_type: new_type, new_options: new_options) }
19
+
20
+ describe '#up/down' do
21
+ describe '#up' do
22
+ it 'responds with command' do
23
+ expect(subject.up).to eq("change_column :#{table_name}, :#{column_name}, :#{new_type}, #{new_options_string}\n")
24
+ end
25
+ end
26
+
27
+ describe '#down' do
28
+ it 'responds with command' do
29
+ expect(subject.down).to eq("change_column :#{table_name}, :#{column_name}, :#{old_type}, #{old_options_string}\n")
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../../lib/declare_schema/schema_change/column_remove'
4
+
5
+ RSpec.describe DeclareSchema::SchemaChange::ColumnRemove do
6
+ before do
7
+ load File.expand_path('../prepare_testapp.rb', __dir__)
8
+ end
9
+
10
+ let(:table_name) { 'networks' }
11
+ let(:column_name) { 'title' }
12
+ let(:column_type) { :integer }
13
+ let(:column_options) { { limit: 8 } }
14
+ let(:column_options_string) { "limit: 8" }
15
+ subject { described_class.new(table_name, column_name, column_type, column_options) }
16
+
17
+ describe '#up/down' do
18
+ describe '#up' do
19
+ it 'responds with command' do
20
+ expect(subject.up).to eq("remove_column :#{table_name}, :#{column_name}\n")
21
+ end
22
+ end
23
+
24
+ describe '#down' do
25
+ it 'responds with command' do
26
+ expect(subject.down).to eq("add_column :#{table_name}, :#{column_name}, :#{column_type}, #{column_options_string}\n")
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../../lib/declare_schema/schema_change/column_rename'
4
+
5
+ RSpec.describe DeclareSchema::SchemaChange::ColumnRename do
6
+ before do
7
+ load File.expand_path('../prepare_testapp.rb', __dir__)
8
+ end
9
+
10
+ let(:table_name) { 'networks' }
11
+ let(:old_name) { 'title' }
12
+ let(:new_name) { 'summary' }
13
+ subject { described_class.new(table_name, old_name, new_name) }
14
+
15
+ describe '#up/down' do
16
+ describe '#up' do
17
+ it 'responds with command' do
18
+ expect(subject.up).to eq("rename_column :#{table_name}, :#{old_name}, :#{new_name}\n")
19
+ end
20
+ end
21
+
22
+ describe '#down' do
23
+ it 'responds with command' do
24
+ expect(subject.down).to eq("rename_column :#{table_name}, :#{new_name}, :#{old_name}\n")
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../../lib/declare_schema/schema_change/foreign_key_add'
4
+
5
+ RSpec.describe DeclareSchema::SchemaChange::ForeignKeyAdd do
6
+ before do
7
+ load File.expand_path('../prepare_testapp.rb', __dir__)
8
+ end
9
+
10
+ let(:table_name) { 'users' }
11
+ let(:parent_table_name) { 'organization' }
12
+ let(:column_name) { :organization_id }
13
+ let(:name) { 'on_organization_id' }
14
+ subject { described_class.new(table_name, parent_table_name, column_name: column_name, name: name) }
15
+
16
+ describe '#up/down' do
17
+ describe '#up' do
18
+ it 'responds with command' do
19
+ expect(subject.up).to eq("add_foreign_key :#{table_name}, :#{parent_table_name}, column: #{column_name.to_sym.inspect}, name: #{name.to_sym.inspect}\n")
20
+ end
21
+ end
22
+
23
+ describe '#down' do
24
+ it 'responds with command' do
25
+ expect(subject.down).to eq("remove_foreign_key :#{table_name}, name: #{name.to_sym.inspect}\n")
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../../lib/declare_schema/schema_change/foreign_key_remove'
4
+
5
+ RSpec.describe DeclareSchema::SchemaChange::ForeignKeyRemove do
6
+ before do
7
+ load File.expand_path('../prepare_testapp.rb', __dir__)
8
+ end
9
+
10
+ let(:table_name) { 'users' }
11
+ let(:parent_table_name) { 'organization' }
12
+ let(:column_name) { :organization_id }
13
+ let(:name) { 'on_organization_id' }
14
+ subject { described_class.new(table_name, parent_table_name, column_name: column_name, name: name) }
15
+
16
+ describe '#up/down' do
17
+ describe '#up' do
18
+ it 'responds with command' do
19
+ expect(subject.up).to eq("remove_foreign_key :#{table_name}, name: #{name.to_sym.inspect}\n")
20
+ end
21
+ end
22
+
23
+ describe '#down' do
24
+ it 'responds with command' do
25
+ expect(subject.down).to eq("add_foreign_key :#{table_name}, :#{parent_table_name}, column: #{column_name.to_sym.inspect}, name: #{name.to_sym.inspect}\n")
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../../lib/declare_schema/schema_change/index_add'
4
+
5
+ RSpec.describe DeclareSchema::SchemaChange::IndexAdd do
6
+ before do
7
+ load File.expand_path('../prepare_testapp.rb', __dir__)
8
+ end
9
+
10
+ let(:table_name) { 'users' }
11
+ let(:column_names) { [:last_name, 'first_name'] }
12
+ let(:name) { 'on_last_name_and_first_name' }
13
+ let(:unique) { false }
14
+ subject { described_class.new(table_name, column_names, name: name, unique: unique) }
15
+
16
+ describe '#up/down' do
17
+ describe '#up' do
18
+ context 'without where:' do
19
+ it 'responds with command' do
20
+ expect(subject.up).to eq("add_index :#{table_name}, #{column_names.map(&:to_sym).inspect}, name: #{name.to_sym.inspect}\n")
21
+ end
22
+ end
23
+
24
+ context 'with empty where:' do
25
+ subject { described_class.new(table_name, column_names, name: name, unique: unique, where: nil) }
26
+
27
+ it 'responds with command' do
28
+ expect(subject.up).to eq("add_index :#{table_name}, #{column_names.map(&:to_sym).inspect}, name: #{name.to_sym.inspect}\n")
29
+ end
30
+ end
31
+
32
+ context 'with where:' do
33
+ let(:where) { "'last_name like 'A%'"}
34
+ subject { described_class.new(table_name, column_names, name: name, unique: unique, where: where) }
35
+
36
+ it 'responds with command' do
37
+ expect(subject.up).to eq("add_index :#{table_name}, #{column_names.map(&:to_sym).inspect}, name: #{name.to_sym.inspect}, where: #{where.inspect}\n")
38
+ end
39
+ end
40
+
41
+ context 'with unique: true' do
42
+ let(:unique) { true }
43
+
44
+ it 'responds with command' do
45
+ expect(subject.up).to eq("add_index :#{table_name}, #{column_names.map(&:to_sym).inspect}, name: #{name.to_sym.inspect}, unique: true\n")
46
+ end
47
+ end
48
+ end
49
+
50
+ describe '#down' do
51
+ it 'responds with command' do
52
+ expect(subject.down).to eq("remove_index :#{table_name}, name: #{name.to_sym.inspect}\n")
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../../lib/declare_schema/schema_change/index_remove'
4
+
5
+ RSpec.describe DeclareSchema::SchemaChange::IndexRemove do
6
+ before do
7
+ load File.expand_path('../prepare_testapp.rb', __dir__)
8
+ end
9
+
10
+ let(:table_name) { 'users' }
11
+ let(:column_names) { [:last_name, 'first_name'] }
12
+ let(:name) { 'on_last_name_and_first_name' }
13
+ let(:unique) { true }
14
+ subject { described_class.new(table_name, column_names, name: name, unique: unique) }
15
+
16
+ describe '#up/down' do
17
+ describe '#up' do
18
+ it 'responds with command' do
19
+ expect(subject.up).to eq("remove_index :#{table_name}, name: #{name.to_sym.inspect}\n")
20
+ end
21
+ end
22
+
23
+ describe '#down' do
24
+ it 'responds with command' do
25
+ expect(subject.down).to eq("add_index :#{table_name}, #{column_names.map(&:to_sym).inspect}, name: #{name.to_sym.inspect}, unique: #{unique}\n")
26
+ end
27
+ end
28
+ end
29
+ end