declare_schema 0.4.0 → 0.4.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 +8 -3
- data/Gemfile.lock +3 -3
- data/lib/declare_schema/model/index_definition.rb +29 -11
- data/lib/declare_schema/version.rb +1 -1
- data/spec/lib/declare_schema/api_spec.rb +1 -1
- data/spec/lib/declare_schema/migration_generator_spec.rb +8 -3
- data/spec/lib/declare_schema/model/index_definition_spec.rb +52 -12
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2e1d3c68c4e9b2f6ce739eba37ed19c5f80204495a50a9240e9f1f68a09777e3
|
4
|
+
data.tar.gz: 63e0a3205c82c2b5e6dacbfbfd10e9aa2e63eee5898d11fd5c102618e73755aa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 34ab74d97dd53c426d3a289b622670a42846d84279c2e3967ad0663c8f4871b1470a90b309237b09b09724a7e7c2405fb0f614a00d33902f8000bb1df23459ef
|
7
|
+
data.tar.gz: 2bf6ca852f71807e362ef26b4ba14d75b8a452a6245094eb8023fa1889b94d6584cf15856962f9fb85168208e0de4dd23a7942fb18cdcc5335f7c744382ba826
|
data/CHANGELOG.md
CHANGED
@@ -4,10 +4,15 @@ Inspired by [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
4
4
|
|
5
5
|
Note: this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
6
6
|
|
7
|
+
## [0.4.1] - 2020-12-04
|
8
|
+
### Fixed
|
9
|
+
- Fixed a bug detecting compound primary keys in Rails 4.
|
10
|
+
|
7
11
|
## [0.4.0] - 2020-11-20
|
8
12
|
### Added
|
9
|
-
- Fields may be declared with `serialize: true`
|
10
|
-
|
13
|
+
- Fields may be declared with `serialize: true` (any value with a valid `.to_yaml` stored as YAML),
|
14
|
+
or `serialize: <serializeable-class>`, where `<serializeable-class>`
|
15
|
+
may be `Array` (`Array` stored as YAML) or `Hash` (`Hash` stored as YAML) or `JSON` (any value with a valid `.to_json`, stored as JSON)
|
11
16
|
or any custom serializable class.
|
12
17
|
This invokes `ActiveSupport`'s `serialize` macro for that field, passing the serializable class, if given.
|
13
18
|
|
@@ -55,11 +60,11 @@ using the appropriate Rails configuration attributes.
|
|
55
60
|
### Changed
|
56
61
|
- Added travis support and created 2 specs as a starting point.
|
57
62
|
|
58
|
-
|
59
63
|
## [0.1.1] - 2020-09-24
|
60
64
|
### Added
|
61
65
|
- Initial version from https://github.com/Invoca/hobo_fields v4.1.0.
|
62
66
|
|
67
|
+
[0.4.1]: https://github.com/Invoca/declare_schema/compare/v0.4.0...v0.4.1
|
63
68
|
[0.4.0]: https://github.com/Invoca/declare_schema/compare/v0.3.1...v0.4.0
|
64
69
|
[0.3.1]: https://github.com/Invoca/declare_schema/compare/v0.3.0...v0.3.1
|
65
70
|
[0.3.0]: https://github.com/Invoca/declare_schema/compare/v0.2.0...v0.3.0
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
declare_schema (0.4.
|
4
|
+
declare_schema (0.4.1)
|
5
5
|
rails (>= 4.2)
|
6
6
|
|
7
7
|
GEM
|
@@ -54,7 +54,7 @@ GEM
|
|
54
54
|
thor (>= 0.14.0)
|
55
55
|
arel (9.0.0)
|
56
56
|
ast (2.4.1)
|
57
|
-
bootsnap (1.5.
|
57
|
+
bootsnap (1.5.1)
|
58
58
|
msgpack (~> 1.0)
|
59
59
|
builder (3.2.4)
|
60
60
|
byebug (11.1.3)
|
@@ -69,7 +69,7 @@ GEM
|
|
69
69
|
activesupport (>= 4.2.0)
|
70
70
|
i18n (1.8.5)
|
71
71
|
concurrent-ruby (~> 1.0)
|
72
|
-
listen (3.
|
72
|
+
listen (3.3.1)
|
73
73
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
74
74
|
rb-inotify (~> 0.9, >= 0.9.10)
|
75
75
|
loofah (2.7.0)
|
@@ -37,16 +37,9 @@ module DeclareSchema
|
|
37
37
|
def for_model(model, old_table_name = nil)
|
38
38
|
t = old_table_name || model.table_name
|
39
39
|
|
40
|
-
primary_key_columns = Array(model.connection.primary_key(t)).presence ||
|
41
|
-
|
42
|
-
|
43
|
-
if cols.any? { |col| col.name == 'id' }
|
44
|
-
'id'
|
45
|
-
else
|
46
|
-
cols.find { |col| col.type.to_s.include?('int') }&.name or raise "could not guess primary key for #{t} in #{cols.inspect}"
|
47
|
-
end
|
48
|
-
)
|
49
|
-
end
|
40
|
+
primary_key_columns = Array(model.connection.primary_key(t)).presence || sqlite_compound_primary_key(model, t) or
|
41
|
+
raise "could not find primary key for table #{t} in #{model.connection.columns(t).inspect}"
|
42
|
+
|
50
43
|
primary_key_found = false
|
51
44
|
index_definitions = model.connection.indexes(t).map do |i|
|
52
45
|
model.ignore_indexes.include?(i.name) and next
|
@@ -55,7 +48,8 @@ module DeclareSchema
|
|
55
48
|
raise "primary key on #{t} was not unique on #{primary_key_columns} (was unique=#{i.unique} on #{i.columns})"
|
56
49
|
primary_key_found = true
|
57
50
|
elsif i.columns == primary_key_columns && i.unique
|
58
|
-
|
51
|
+
# skip this primary key index since we'll create it below, with PRIMARY_KEY_NAME
|
52
|
+
next
|
59
53
|
end
|
60
54
|
new(model, i.columns, name: i.name, unique: i.unique, where: i.where, table_name: old_table_name)
|
61
55
|
end.compact
|
@@ -65,6 +59,30 @@ module DeclareSchema
|
|
65
59
|
end
|
66
60
|
index_definitions
|
67
61
|
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
# This is the old approach which is still needed for SQLite
|
66
|
+
def sqlite_compound_primary_key(model, table)
|
67
|
+
ActiveRecord::Base.connection.class.name.match?(/SQLite3Adapter/) or return nil
|
68
|
+
|
69
|
+
connection = model.connection.dup
|
70
|
+
|
71
|
+
class << connection # defeat Rails MySQL driver code that skips the primary key by changing its name to a symbol
|
72
|
+
def each_hash(result)
|
73
|
+
super do |hash|
|
74
|
+
if hash[:Key_name] == PRIMARY_KEY_NAME
|
75
|
+
hash[:Key_name] = PRIMARY_KEY_NAME.to_sym
|
76
|
+
end
|
77
|
+
yield hash
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
pk_index = connection.indexes(table).find { |index| index.name.to_s == PRIMARY_KEY_NAME } or return nil
|
83
|
+
|
84
|
+
Array(pk_index.columns)
|
85
|
+
end
|
68
86
|
end
|
69
87
|
|
70
88
|
def primary_key?
|
@@ -43,6 +43,12 @@ RSpec.describe 'DeclareSchema Migration Generator' do
|
|
43
43
|
ActiveRecord::Migration.class_eval(up)
|
44
44
|
expect(Advert.columns.map(&:name)).to eq(["id", "name"])
|
45
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
|
+
|
46
52
|
class Advert < ActiveRecord::Base
|
47
53
|
fields do
|
48
54
|
name :string, limit: 255, null: true
|
@@ -610,9 +616,8 @@ RSpec.describe 'DeclareSchema Migration Generator' do
|
|
610
616
|
# Dropping tables is where the automatic down-migration really comes in handy:
|
611
617
|
|
612
618
|
rails4_table_create = <<~EOS.strip
|
613
|
-
create_table "adverts",
|
614
|
-
t.
|
615
|
-
t.string "name", limit: 255
|
619
|
+
create_table "adverts", force: :cascade do |t|
|
620
|
+
t.string "name", limit: 255
|
616
621
|
end
|
617
622
|
EOS
|
618
623
|
|
@@ -13,16 +13,25 @@ RSpec.describe DeclareSchema::Model::IndexDefinition do
|
|
13
13
|
before do
|
14
14
|
load File.expand_path('../prepare_testapp.rb', __dir__)
|
15
15
|
|
16
|
-
class
|
16
|
+
class IndexDefinitionTestModel < ActiveRecord::Base
|
17
17
|
fields do
|
18
18
|
name :string, limit: 127, index: true
|
19
19
|
|
20
20
|
timestamps
|
21
21
|
end
|
22
22
|
end
|
23
|
+
|
24
|
+
class IndexDefinitionCompoundIndexModel < ActiveRecord::Base
|
25
|
+
fields do
|
26
|
+
fk1_id :integer
|
27
|
+
fk2_id :integer
|
28
|
+
|
29
|
+
timestamps
|
30
|
+
end
|
31
|
+
end
|
23
32
|
end
|
24
33
|
|
25
|
-
let(:model_class) {
|
34
|
+
let(:model_class) { IndexDefinitionTestModel }
|
26
35
|
|
27
36
|
describe 'instance methods' do
|
28
37
|
let(:model) { model_class.new }
|
@@ -53,13 +62,20 @@ RSpec.describe DeclareSchema::Model::IndexDefinition do
|
|
53
62
|
context 'with a migrated database' do
|
54
63
|
before do
|
55
64
|
ActiveRecord::Base.connection.execute <<~EOS
|
56
|
-
CREATE TABLE
|
65
|
+
CREATE TABLE index_definition_test_models (
|
57
66
|
id INTEGER NOT NULL PRIMARY KEY,
|
58
67
|
name TEXT NOT NULL
|
59
68
|
)
|
60
69
|
EOS
|
61
70
|
ActiveRecord::Base.connection.execute <<~EOS
|
62
|
-
CREATE UNIQUE INDEX
|
71
|
+
CREATE UNIQUE INDEX index_definition_test_models_on_name ON index_definition_test_models(name)
|
72
|
+
EOS
|
73
|
+
ActiveRecord::Base.connection.execute <<~EOS
|
74
|
+
CREATE TABLE index_definition_compound_index_models (
|
75
|
+
fk1_id INTEGER NULL,
|
76
|
+
fk2_id INTEGER NULL,
|
77
|
+
PRIMARY KEY (fk1_id, fk2_id)
|
78
|
+
)
|
63
79
|
EOS
|
64
80
|
ActiveRecord::Base.connection.schema_cache.clear!
|
65
81
|
end
|
@@ -67,14 +83,38 @@ RSpec.describe DeclareSchema::Model::IndexDefinition do
|
|
67
83
|
describe 'for_model' do
|
68
84
|
subject { described_class.for_model(model_class) }
|
69
85
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
[
|
74
|
-
|
75
|
-
|
76
|
-
[
|
77
|
-
|
86
|
+
context 'with single-column PK' do
|
87
|
+
it 'returns the indexes for the model' do
|
88
|
+
expect(subject.size).to eq(2), subject.inspect
|
89
|
+
expect([:name, :columns, :unique].map { |attr| subject[0].send(attr) }).to eq(
|
90
|
+
['index_definition_test_models_on_name', ['name'], true]
|
91
|
+
)
|
92
|
+
expect([:name, :columns, :unique].map { |attr| subject[1].send(attr) }).to eq(
|
93
|
+
['PRIMARY', ['id'], true]
|
94
|
+
)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'with compound-column PK' do
|
99
|
+
let(:model_class) { IndexDefinitionCompoundIndexModel }
|
100
|
+
|
101
|
+
it 'returns the indexes for the model' do
|
102
|
+
# Simulate MySQL for Rails 4 work-around
|
103
|
+
if Rails::VERSION::MAJOR < 5
|
104
|
+
expect(model_class.connection).to receive(:primary_key).with('index_definition_compound_index_models').and_return(nil)
|
105
|
+
connection_stub = instance_double(ActiveRecord::ConnectionAdapters::SQLite3Adapter, "connection")
|
106
|
+
expect(connection_stub).to receive(:indexes).
|
107
|
+
with('index_definition_compound_index_models').
|
108
|
+
and_return([DeclareSchema::Model::IndexDefinition.new(model_class, ['fk1_id', 'fk2_id'], name: 'PRIMARY')])
|
109
|
+
|
110
|
+
expect(model_class.connection).to receive(:dup).and_return(connection_stub)
|
111
|
+
end
|
112
|
+
|
113
|
+
expect(subject.size).to eq(1), subject.inspect
|
114
|
+
expect([:name, :columns, :unique].map { |attr| subject[0].send(attr) }).to eq(
|
115
|
+
['PRIMARY', ['fk1_id', 'fk2_id'], true]
|
116
|
+
)
|
117
|
+
end
|
78
118
|
end
|
79
119
|
end
|
80
120
|
end
|
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.
|
4
|
+
version: 0.4.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: 2020-
|
11
|
+
date: 2020-12-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|