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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1e5c665ec203dd84e445290bac1de190491560ddc409fe2bd3f5ba4831e065c5
4
- data.tar.gz: 244148b892d2de22a692c4db50b136995f97d8da38573e87a443303fdee5be7a
3
+ metadata.gz: 2e1d3c68c4e9b2f6ce739eba37ed19c5f80204495a50a9240e9f1f68a09777e3
4
+ data.tar.gz: 63e0a3205c82c2b5e6dacbfbfd10e9aa2e63eee5898d11fd5c102618e73755aa
5
5
  SHA512:
6
- metadata.gz: 44994fd571b97768ffec2c9bbce779b8beef222ba50213a425a3021c66f1dc4e4fd7a50adc95cf3d1a1116e67eaf5c47b11e635408856c726118a22c18188b98
7
- data.tar.gz: 7d3eb3be095a1dce65b6b39b35974a6c96ee940fec31dba3fddbfb528be8be3b42906ec81c6075cde5d8fa590df4afc8ca12887a956c772fc34c084791577526
6
+ metadata.gz: 34ab74d97dd53c426d3a289b622670a42846d84279c2e3967ad0663c8f4871b1470a90b309237b09b09724a7e7c2405fb0f614a00d33902f8000bb1df23459ef
7
+ data.tar.gz: 2bf6ca852f71807e362ef26b4ba14d75b8a452a6245094eb8023fa1889b94d6584cf15856962f9fb85168208e0de4dd23a7942fb18cdcc5335f7c744382ba826
@@ -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` or `serialize: <serializeable-class>`, where `<serializeable-class>`
10
- may be `Array` (`Array` stored as YAML) or `Hash` (`Hash` stored as YAML), (`Array` or `Hash` or any scalar value stored as JSON)
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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- declare_schema (0.4.0)
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.0)
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.2.1)
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 || begin
41
- cols = model.connection.columns(t)
42
- Array(
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
- raise "found primary key index on #{t}.#{primary_key_columns} but it was called #{i.name}"
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?
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DeclareSchema
4
- VERSION = "0.4.0"
4
+ VERSION = "0.4.1"
5
5
  end
@@ -39,7 +39,7 @@ RSpec.describe 'DeclareSchema API' do
39
39
 
40
40
  load_models
41
41
 
42
- unless Rails::VERSION::MAJOR >= 6
42
+ if Rails::VERSION::MAJOR == 5
43
43
  # TODO: get this to work on Travis for Rails 6
44
44
  generate_migrations '-n', '-m'
45
45
  end
@@ -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", id: false, force: :cascade do |t|
614
- t.integer "id", limit: 8
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 IndexSettingsTestModel < ActiveRecord::Base
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) { IndexSettingsTestModel }
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 index_settings_test_models (
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 index_settings_test_models_on_name ON index_settings_test_models(name)
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
- it 'returns the indexes for the model' do
71
- expect(subject.size).to eq(2), subject.inspect
72
- expect([:name, :columns, :unique].map { |attr| subject[0].send(attr) }).to eq(
73
- ['index_settings_test_models_on_name', ['name'], true]
74
- )
75
- expect([:name, :columns, :unique].map { |attr| subject[1].send(attr) }).to eq(
76
- ['PRIMARY', ['id'], true]
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.0
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-20 00:00:00.000000000 Z
11
+ date: 2020-12-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails