declare_schema 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|