historiographer 1.1.0 → 1.2.0

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: 433e733811c7f23a3044282b54c87832abc944e3f46817d16036c87778f938ff
4
- data.tar.gz: 54e27e8e68ab4512bb5edf146d1c210f9072ad99346d8a1ced37e6766d014d3b
3
+ metadata.gz: e7cb91195d9d049faf9de52f631cd6c64c46c24e3e0d44fba5ea446197986d98
4
+ data.tar.gz: 0236e459a57ec0a4105f9dd9a8e933745f98e9942d2919298e97e6cf7a32c3d3
5
5
  SHA512:
6
- metadata.gz: 1abd0b29fc36c284fb6e8c5da6c884640678ce0dd9b58c089b15056897514f7cd47b8d4117e54b3549d306be6ce0a08c36f772724bc741fd09cf782a174c0415
7
- data.tar.gz: c63eecd58ea1b7ad604d3cf049735b2fed3bdd403aa2c508190a3907b6dfcaf7ecb6094b9ac14bf2fb0d5574e8277a0c2b05ef06d25a8291bfbc3306c419decb
6
+ metadata.gz: 6ddac0ce23e3b5ded4dc95a6c8d2e5b0870bc95e40e89d5d3fbf2e867511cc6320d23f4ac1562191c025d011161afca0f1c107fcb0c9a64d59799183bb31ef5a
7
+ data.tar.gz: ac97602293b1488db300d33178bf1c697f69613e3929c62aa5199c2a11a3d6ae07e4d8a1afb1198a8a41761c6ff09726c4fee5570ef17f35721ff5e8ce8756f5
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.0
1
+ 1.2.0
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: historiographer 1.1.0 ruby lib
5
+ # stub: historiographer 1.2.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "historiographer".freeze
9
- s.version = "1.1.0"
9
+ s.version = "1.2.0"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib".freeze]
13
13
  s.authors = ["brettshollenberger".freeze]
14
- s.date = "2019-10-11"
14
+ s.date = "2019-10-24"
15
15
  s.description = "Creates separate tables for each history table".freeze
16
16
  s.email = "brett.shollenberger@gmail.com".freeze
17
17
  s.extra_rdoc_files = [
@@ -47,6 +47,8 @@ Gem::Specification.new do |s|
47
47
  "spec/db/migrate/20161121212232_create_users.rb",
48
48
  "spec/db/migrate/20171011194624_create_safe_posts.rb",
49
49
  "spec/db/migrate/20171011194715_create_safe_post_histories.rb",
50
+ "spec/db/migrate/20191024142304_create_thing_with_compound_index.rb",
51
+ "spec/db/migrate/20191024142352_create_thing_with_compound_index_history.rb",
50
52
  "spec/db/schema.rb",
51
53
  "spec/examples.txt",
52
54
  "spec/historiographer_spec.rb",
@@ -16,7 +16,8 @@ module Historiographer
16
16
  # Will automatically add user_id, history_started_at,
17
17
  # and history_ended_at columns
18
18
  #
19
- def histories(except: [], only: [], no_business_columns: false)
19
+ def histories(except: [], only: [], no_business_columns: false, index_names: {})
20
+ index_names.symbolize_keys!
20
21
  original_table_name = self.name.gsub(/_histories$/) {}.pluralize
21
22
  foreign_key = original_table_name.singularize.foreign_key
22
23
 
@@ -32,7 +33,6 @@ module Historiographer
32
33
  original_columns.each do |column|
33
34
  opts = {}
34
35
  opts.merge!(column.as_json.clone)
35
- # opts.merge!(column.type.as_json.clone)
36
36
 
37
37
  send(column.type, column.name, opts.symbolize_keys!)
38
38
  end
@@ -41,38 +41,49 @@ module Historiographer
41
41
  datetime :history_ended_at
42
42
  integer :history_user_id
43
43
 
44
- index :history_started_at
45
- index :history_ended_at
46
- index :history_user_id
47
- index foreign_key
48
-
49
- indices_sql = <<-SQL
50
- SELECT
51
- a.attname AS column_name
52
- FROM
53
- pg_class t,
54
- pg_class i,
55
- pg_index ix,
56
- pg_attribute a
57
- WHERE
58
- t.oid = ix.indrelid
59
- AND i.oid = ix.indexrelid
60
- AND a.attrelid = t.oid
61
- AND a.attnum = ANY(ix.indkey)
62
- AND t.relkind = 'r'
63
- AND t.relname = ?
64
- ORDER BY
65
- t.relname,
66
- i.relname;
67
- SQL
44
+ indices_sql = %q(
45
+ SELECT
46
+ DISTINCT(
47
+ ARRAY_TO_STRING(ARRAY(
48
+ SELECT pg_get_indexdef(idx.indexrelid, k + 1, true)
49
+ FROM generate_subscripts(idx.indkey, 1) as k
50
+ ORDER BY k
51
+ ), ',')
52
+ ) as indkey_names
53
+ FROM pg_class t,
54
+ pg_class i,
55
+ pg_index idx,
56
+ pg_attribute a,
57
+ pg_am am
58
+ WHERE t.oid = idx.indrelid
59
+ AND i.oid = idx.indexrelid
60
+ AND a.attrelid = t.oid
61
+ AND a.attnum = ANY(idx.indkey)
62
+ AND t.relkind = 'r'
63
+ AND t.relname = ?;
64
+ )
68
65
 
69
66
  indices_query_array = [indices_sql, original_table_name]
70
67
  indices_sanitized_query = klass.send(:sanitize_sql_array, indices_query_array)
71
68
 
72
- klass.connection.execute(indices_sanitized_query).to_a.map(&:values).flatten.reject { |i| i == "id" }.each do |index_name|
73
- index index_name.to_sym
69
+ indexes = klass.connection.execute(indices_sanitized_query).to_a.map(&:values).flatten.reject { |i| i == "id" }.map { |i| i.split(",") }.concat([
70
+ foreign_key,
71
+ :history_started_at,
72
+ :history_ended_at,
73
+ :history_user_id
74
+ ])
75
+
76
+ indexes.each do |index_definition|
77
+ index_definition = [index_definition].flatten.map(&:to_sym)
78
+ index_name = index_definition.count == 1 ? index_definition.first : index_definition
79
+
80
+ if index_names.key?(index_name)
81
+ index index_name, name: index_names[index_name]
82
+ else
83
+ index index_name
84
+ end
74
85
  end
75
86
 
76
87
  end
77
88
  end
78
- end
89
+ end
@@ -1,27 +1,26 @@
1
- # default: &default
2
- # adapter: postgresql
3
- # prepared_statements: false
4
- # url: "postgres://localhost/historiographer_development"
5
-
6
- # development:
7
- # <<: *default
8
-
9
- # test:
10
- # adapter: postgresql
11
- # database: historiographer_test
12
-
13
- mysql_default: &mysql_default
14
- adapter: mysql2
15
- encoding: utf8
16
- username: root
17
- password:
18
- host: 127.0.0.1
19
- port: 3306
1
+ default: &default
2
+ adapter: postgresql
3
+ prepared_statements: false
4
+ url: "postgres://localhost/historiographer_development"
20
5
 
21
6
  development:
22
- <<: *mysql_default
23
- database: historiographer_development
7
+ <<: *default
24
8
 
25
9
  test:
26
- <<: *mysql_default
10
+ adapter: postgresql
27
11
  database: historiographer_test
12
+ # mysql_default: &mysql_default
13
+ # adapter: mysql2
14
+ # encoding: utf8
15
+ # username: root
16
+ # password:
17
+ # host: 127.0.0.1
18
+ # port: 3306
19
+
20
+ # development:
21
+ # <<: *mysql_default
22
+ # database: historiographer_development
23
+
24
+ # test:
25
+ # <<: *mysql_default
26
+ # database: historiographer_test
@@ -0,0 +1,10 @@
1
+ class CreateThingWithCompoundIndex < ActiveRecord::Migration[5.2]
2
+ def change
3
+ create_table :thing_with_compound_indices do |t|
4
+ t.string :key
5
+ t.string :value
6
+
7
+ t.index [:key, :value], name: "idx_key_value"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ require "historiographer/postgres_migration"
2
+ class CreateThingWithCompoundIndexHistory < ActiveRecord::Migration[5.2]
3
+ def change
4
+ create_table :thing_with_compound_index_histories do |t|
5
+ t.histories index_names: {
6
+ [:key, :value] => "idx_history_k_v",
7
+ :thing_with_compound_index_id => "idx_k_v_histories"
8
+ }
9
+ end
10
+ end
11
+ end
@@ -10,9 +10,12 @@
10
10
  #
11
11
  # It's strongly recommended that you check this file into your version control system.
12
12
 
13
- ActiveRecord::Schema.define(version: 2017_10_11_194715) do
13
+ ActiveRecord::Schema.define(version: 2019_10_24_142352) do
14
14
 
15
- create_table "author_histories", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
15
+ # These are extensions that must be enabled in order to support this database
16
+ enable_extension "plpgsql"
17
+
18
+ create_table "author_histories", force: :cascade do |t|
16
19
  t.integer "author_id", null: false
17
20
  t.string "full_name", null: false
18
21
  t.text "bio"
@@ -29,7 +32,7 @@ ActiveRecord::Schema.define(version: 2017_10_11_194715) do
29
32
  t.index ["history_user_id"], name: "index_author_histories_on_history_user_id"
30
33
  end
31
34
 
32
- create_table "authors", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
35
+ create_table "authors", force: :cascade do |t|
33
36
  t.string "full_name", null: false
34
37
  t.text "bio"
35
38
  t.datetime "deleted_at"
@@ -38,7 +41,7 @@ ActiveRecord::Schema.define(version: 2017_10_11_194715) do
38
41
  t.index ["deleted_at"], name: "index_authors_on_deleted_at"
39
42
  end
40
43
 
41
- create_table "post_histories", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
44
+ create_table "post_histories", force: :cascade do |t|
42
45
  t.integer "post_id", null: false
43
46
  t.string "title", null: false
44
47
  t.text "body", null: false
@@ -61,7 +64,7 @@ ActiveRecord::Schema.define(version: 2017_10_11_194715) do
61
64
  t.index ["post_id"], name: "index_post_histories_on_post_id"
62
65
  end
63
66
 
64
- create_table "posts", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
67
+ create_table "posts", force: :cascade do |t|
65
68
  t.string "title", null: false
66
69
  t.text "body", null: false
67
70
  t.integer "author_id", null: false
@@ -76,7 +79,7 @@ ActiveRecord::Schema.define(version: 2017_10_11_194715) do
76
79
  t.index ["live_at"], name: "index_posts_on_live_at"
77
80
  end
78
81
 
79
- create_table "safe_post_histories", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
82
+ create_table "safe_post_histories", force: :cascade do |t|
80
83
  t.integer "safe_post_id", null: false
81
84
  t.string "title", null: false
82
85
  t.text "body", null: false
@@ -99,7 +102,7 @@ ActiveRecord::Schema.define(version: 2017_10_11_194715) do
99
102
  t.index ["safe_post_id"], name: "index_safe_post_histories_on_safe_post_id"
100
103
  end
101
104
 
102
- create_table "safe_posts", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
105
+ create_table "safe_posts", force: :cascade do |t|
103
106
  t.string "title", null: false
104
107
  t.text "body", null: false
105
108
  t.integer "author_id", null: false
@@ -114,7 +117,27 @@ ActiveRecord::Schema.define(version: 2017_10_11_194715) do
114
117
  t.index ["live_at"], name: "index_safe_posts_on_live_at"
115
118
  end
116
119
 
117
- create_table "users", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
120
+ create_table "thing_with_compound_index_histories", force: :cascade do |t|
121
+ t.integer "thing_with_compound_index_id", null: false
122
+ t.string "key"
123
+ t.string "value"
124
+ t.datetime "history_started_at", null: false
125
+ t.datetime "history_ended_at"
126
+ t.integer "history_user_id"
127
+ t.index ["history_ended_at"], name: "index_thing_with_compound_index_histories_on_history_ended_at"
128
+ t.index ["history_started_at"], name: "index_thing_with_compound_index_histories_on_history_started_at"
129
+ t.index ["history_user_id"], name: "index_thing_with_compound_index_histories_on_history_user_id"
130
+ t.index ["key", "value"], name: "idx_history_k_v"
131
+ t.index ["thing_with_compound_index_id"], name: "idx_k_v_histories"
132
+ end
133
+
134
+ create_table "thing_with_compound_indices", force: :cascade do |t|
135
+ t.string "key"
136
+ t.string "value"
137
+ t.index ["key", "value"], name: "idx_key_value"
138
+ end
139
+
140
+ create_table "users", force: :cascade do |t|
118
141
  t.string "name"
119
142
  end
120
143
 
@@ -24,6 +24,13 @@ end
24
24
  class User < ActiveRecord::Base
25
25
  end
26
26
 
27
+ class ThingWithCompoundIndex < ActiveRecord::Base
28
+ include Historiographer
29
+ end
30
+
31
+ class ThingWithCompoundIndexHistory < ActiveRecord::Base
32
+ end
33
+
27
34
  describe Historiographer do
28
35
  before(:all) do
29
36
  @now = Timecop.freeze
@@ -317,6 +324,8 @@ describe Historiographer do
317
324
  body,
318
325
  post_id,
319
326
  author_id,
327
+ created_at,
328
+ updated_at,
320
329
  history_started_at,
321
330
  history_ended_at
322
331
  ) VALUES (
@@ -324,6 +333,8 @@ describe Historiographer do
324
333
  'Text',
325
334
  1,
326
335
  1,
336
+ now(),
337
+ now(),
327
338
  now() - INTERVAL '1 day',
328
339
  NULL
329
340
  ), (
@@ -331,6 +342,8 @@ describe Historiographer do
331
342
  'Different text',
332
343
  1,
333
344
  1,
345
+ now(),
346
+ now(),
334
347
  now() - INTERVAL '12 hours',
335
348
  NULL
336
349
  ), (
@@ -338,6 +351,8 @@ describe Historiographer do
338
351
  'Even more different text',
339
352
  1,
340
353
  1,
354
+ now(),
355
+ now(),
341
356
  now() - INTERVAL '12 hours',
342
357
  NULL
343
358
  )
@@ -407,4 +422,42 @@ describe Historiographer do
407
422
  expect(author.current_history.user.name).to eq username
408
423
  end
409
424
  end
425
+
426
+ describe "Migrations with compound indexes" do
427
+ it "supports renaming compound indexes and migrating them to history tables" do
428
+ indices_sql = %q(
429
+ SELECT
430
+ DISTINCT(
431
+ ARRAY_TO_STRING(ARRAY(
432
+ SELECT pg_get_indexdef(idx.indexrelid, k + 1, true)
433
+ FROM generate_subscripts(idx.indkey, 1) as k
434
+ ORDER BY k
435
+ ), ',')
436
+ ) as indkey_names
437
+ FROM pg_class t,
438
+ pg_class i,
439
+ pg_index idx,
440
+ pg_attribute a,
441
+ pg_am am
442
+ WHERE t.oid = idx.indrelid
443
+ AND i.oid = idx.indexrelid
444
+ AND a.attrelid = t.oid
445
+ AND a.attnum = ANY(idx.indkey)
446
+ AND t.relkind = 'r'
447
+ AND t.relname = ?;
448
+ )
449
+
450
+ indices_query_array = [indices_sql, :thing_with_compound_index_histories]
451
+ indices_sanitized_query = ThingWithCompoundIndexHistory.send(:sanitize_sql_array, indices_query_array)
452
+
453
+ indexes = ThingWithCompoundIndexHistory.connection.execute(indices_sanitized_query).to_a.map(&:values).flatten.map { |i| i.split(",") }
454
+
455
+ expect(indexes).to include(["history_started_at"])
456
+ expect(indexes).to include(["history_ended_at"])
457
+ expect(indexes).to include(["history_user_id"])
458
+ expect(indexes).to include(["id"])
459
+ expect(indexes).to include(["key", "value"])
460
+ expect(indexes).to include(["thing_with_compound_index_id"])
461
+ end
462
+ end
410
463
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: historiographer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - brettshollenberger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-11 00:00:00.000000000 Z
11
+ date: 2019-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -228,6 +228,8 @@ files:
228
228
  - spec/db/migrate/20161121212232_create_users.rb
229
229
  - spec/db/migrate/20171011194624_create_safe_posts.rb
230
230
  - spec/db/migrate/20171011194715_create_safe_post_histories.rb
231
+ - spec/db/migrate/20191024142304_create_thing_with_compound_index.rb
232
+ - spec/db/migrate/20191024142352_create_thing_with_compound_index_history.rb
231
233
  - spec/db/schema.rb
232
234
  - spec/examples.txt
233
235
  - spec/historiographer_spec.rb