temporal_tables 0.7.1 → 1.0.2
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/.github/workflows/test.yml +53 -0
- data/.rubocop.yml +158 -0
- data/.ruby-version +1 -1
- data/.travis.yml +5 -7
- data/Gemfile +2 -0
- data/README.md +15 -5
- data/Rakefile +7 -2
- data/config.ru +2 -0
- data/gemfiles/Gemfile.6.0.mysql.lock +84 -84
- data/gemfiles/Gemfile.6.0.pg.lock +103 -98
- data/gemfiles/Gemfile.6.1.mysql.lock +180 -0
- data/gemfiles/Gemfile.6.1.pg.lock +180 -0
- data/gemfiles/{Gemfile.5.1.mysql → Gemfile.7.0.mysql} +2 -2
- data/gemfiles/Gemfile.7.0.mysql.lock +173 -0
- data/gemfiles/{Gemfile.5.2.pg → Gemfile.7.0.pg} +1 -1
- data/gemfiles/Gemfile.7.0.pg.lock +173 -0
- data/lib/temporal_tables/arel_table.rb +10 -9
- data/lib/temporal_tables/association_extensions.rb +2 -0
- data/lib/temporal_tables/connection_adapters/mysql_adapter.rb +8 -3
- data/lib/temporal_tables/connection_adapters/postgresql_adapter.rb +5 -3
- data/lib/temporal_tables/history_hook.rb +8 -5
- data/lib/temporal_tables/preloader_extensions.rb +2 -0
- data/lib/temporal_tables/reflection_extensions.rb +11 -14
- data/lib/temporal_tables/relation_extensions.rb +11 -24
- data/lib/temporal_tables/temporal_adapter.rb +93 -97
- data/lib/temporal_tables/temporal_adapter_six_oh.rb +187 -0
- data/lib/temporal_tables/temporal_class.rb +29 -28
- data/lib/temporal_tables/version.rb +3 -1
- data/lib/temporal_tables/whodunnit.rb +5 -3
- data/lib/temporal_tables.rb +48 -33
- data/spec/basic_history_spec.rb +65 -35
- data/spec/internal/app/models/broom.rb +2 -0
- data/spec/internal/app/models/cat.rb +5 -0
- data/spec/internal/app/models/cat_life.rb +5 -0
- data/spec/internal/app/models/coven.rb +2 -0
- data/spec/internal/app/models/flying_machine.rb +2 -0
- data/spec/internal/app/models/person.rb +2 -0
- data/spec/internal/app/models/rocket_broom.rb +2 -0
- data/spec/internal/app/models/wart.rb +3 -1
- data/spec/internal/config/database.ci.yml +12 -0
- data/spec/internal/db/schema.rb +28 -5
- data/spec/spec_helper.rb +39 -5
- data/spec/support/database.rb +10 -6
- data/temporal_tables.gemspec +31 -18
- metadata +108 -39
- data/CHANGELOG.md +0 -73
- data/gemfiles/Gemfile.5.0.mysql +0 -16
- data/gemfiles/Gemfile.5.0.mysql.lock +0 -147
- data/gemfiles/Gemfile.5.0.pg +0 -16
- data/gemfiles/Gemfile.5.0.pg.lock +0 -147
- data/gemfiles/Gemfile.5.1.mysql.lock +0 -147
- data/gemfiles/Gemfile.5.1.pg +0 -16
- data/gemfiles/Gemfile.5.1.pg.lock +0 -147
- data/gemfiles/Gemfile.5.2.mysql +0 -16
- data/gemfiles/Gemfile.5.2.mysql.lock +0 -155
- data/gemfiles/Gemfile.5.2.pg.lock +0 -155
- data/lib/temporal_tables/join_extensions.rb +0 -20
- data/spec/extensions/combustion.rb +0 -9
- data/spec/internal/config/routes.rb +0 -3
data/lib/temporal_tables.rb
CHANGED
@@ -1,67 +1,82 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'temporal_tables/temporal_adapter'
|
4
|
+
require 'temporal_tables/temporal_adapter_six_oh'
|
5
|
+
require 'temporal_tables/connection_adapters/mysql_adapter'
|
6
|
+
require 'temporal_tables/connection_adapters/postgresql_adapter'
|
7
|
+
require 'temporal_tables/whodunnit'
|
8
|
+
require 'temporal_tables/temporal_class'
|
9
|
+
require 'temporal_tables/history_hook'
|
10
|
+
require 'temporal_tables/relation_extensions'
|
11
|
+
require 'temporal_tables/association_extensions'
|
12
|
+
require 'temporal_tables/preloader_extensions'
|
13
|
+
require 'temporal_tables/reflection_extensions'
|
14
|
+
require 'temporal_tables/arel_table'
|
15
|
+
require 'temporal_tables/version'
|
14
16
|
|
15
17
|
module TemporalTables
|
16
18
|
class Railtie < ::Rails::Railtie
|
17
|
-
initializer
|
19
|
+
initializer 'temporal_tables.load' do
|
18
20
|
# Iterating the subclasses will find any adapter implementations
|
19
21
|
# which are in use by the rails app, and mixin the temporal functionality.
|
20
22
|
# It's necessary to do this on the implementations in order for the
|
21
23
|
# alias method chain hooks to work.
|
22
24
|
ActiveRecord::ConnectionAdapters::AbstractAdapter.subclasses.each do |subclass|
|
23
|
-
|
25
|
+
if ActiveRecord.version < ::Gem::Version.new('6.1')
|
26
|
+
subclass.send :prepend, TemporalTables::TemporalAdapterSixOh
|
27
|
+
else
|
28
|
+
subclass.send :prepend, TemporalTables::TemporalAdapter
|
29
|
+
end
|
30
|
+
|
31
|
+
module_name = subclass.name.split('::').last
|
32
|
+
next unless TemporalTables::ConnectionAdapters.const_defined?(module_name)
|
24
33
|
|
25
|
-
|
26
|
-
|
34
|
+
subclass.send(
|
35
|
+
:prepend,
|
36
|
+
TemporalTables::ConnectionAdapters.const_get(module_name)
|
37
|
+
)
|
27
38
|
end
|
28
39
|
|
29
|
-
ActiveRecord::Base.
|
40
|
+
ActiveRecord::Base.include TemporalTables::Whodunnit
|
30
41
|
end
|
31
42
|
end
|
32
43
|
|
33
|
-
|
44
|
+
@create_by_default = false
|
34
45
|
def self.create_by_default
|
35
|
-
|
46
|
+
@create_by_default
|
36
47
|
end
|
48
|
+
|
37
49
|
def self.create_by_default=(default)
|
38
|
-
|
50
|
+
@create_by_default = default
|
39
51
|
end
|
40
52
|
|
41
|
-
|
53
|
+
@skipped_temporal_tables = [:schema_migrations, :sessions, :ar_internal_metadata]
|
42
54
|
def self.skip_temporal_table_for(*tables)
|
43
|
-
|
55
|
+
@skipped_temporal_tables += tables
|
44
56
|
end
|
57
|
+
|
45
58
|
def self.skipped_temporal_tables
|
46
|
-
|
59
|
+
@skipped_temporal_tables.dup
|
47
60
|
end
|
48
61
|
|
49
|
-
|
50
|
-
|
51
|
-
|
62
|
+
@add_updated_by_field = false
|
63
|
+
@updated_by_type = :string
|
64
|
+
@updated_by_proc = nil
|
52
65
|
def self.updated_by_type
|
53
|
-
|
66
|
+
@updated_by_type
|
54
67
|
end
|
68
|
+
|
55
69
|
def self.updated_by_proc
|
56
|
-
|
70
|
+
@updated_by_proc
|
57
71
|
end
|
72
|
+
|
58
73
|
def self.add_updated_by_field(type = :string, &block)
|
59
74
|
if block_given?
|
60
|
-
|
61
|
-
|
62
|
-
|
75
|
+
@add_updated_by_field = true
|
76
|
+
@updated_by_type = type
|
77
|
+
@updated_by_proc = block
|
63
78
|
end
|
64
79
|
|
65
|
-
|
80
|
+
@add_updated_by_field
|
66
81
|
end
|
67
82
|
end
|
data/spec/basic_history_spec.rb
CHANGED
@@ -1,66 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe Person do
|
4
|
-
let(:emily) { Person.create name:
|
6
|
+
let(:emily) { Person.create name: 'Emily' }
|
5
7
|
let(:historical_emily) { emily.history.last }
|
6
8
|
|
7
9
|
before do
|
8
10
|
emily
|
9
|
-
@init_time = Time.now
|
11
|
+
@init_time = Time.zone.now
|
10
12
|
sleep 0.1
|
11
13
|
end
|
12
14
|
|
13
|
-
describe
|
14
|
-
let!(:coven) { Coven.create name:
|
15
|
+
describe 'upon making significant life changes' do
|
16
|
+
let!(:coven) { Coven.create name: 'Double Double Toil & Trouble' }
|
15
17
|
let!(:wart) { Wart.create person: emily, hairiness: 3 }
|
16
18
|
|
17
19
|
before do
|
18
|
-
emily.update name:
|
20
|
+
emily.update name: 'Grunthilda', coven: coven
|
19
21
|
sleep 0.1
|
20
22
|
end
|
21
23
|
|
22
|
-
describe
|
23
|
-
it
|
24
|
-
expect(emily.name).to eq(
|
25
|
-
expect(historical_emily.name).to eq(
|
24
|
+
describe 'when affirming changes' do
|
25
|
+
it 'should have new name' do
|
26
|
+
expect(emily.name).to eq('Grunthilda')
|
27
|
+
expect(historical_emily.name).to eq('Grunthilda')
|
26
28
|
end
|
27
29
|
|
28
|
-
it
|
30
|
+
it 'should belong to coven' do
|
29
31
|
expect(emily.coven.name).to eq(coven.name)
|
30
32
|
expect(historical_emily.coven.name).to eq(coven.name)
|
31
33
|
end
|
32
34
|
|
33
|
-
it
|
35
|
+
it 'should have a wart' do
|
34
36
|
expect(emily.warts).to eq([wart])
|
35
|
-
expect(emily.history.at(Time.now).last.warts).to eq([wart.history.last])
|
37
|
+
expect(emily.history.at(Time.zone.now).last.warts).to eq([wart.history.last])
|
36
38
|
end
|
37
39
|
|
38
|
-
it
|
40
|
+
it 'should allow scopes on associations' do
|
39
41
|
expect(emily.warts.very_hairy).to eq([wart])
|
40
42
|
expect(historical_emily.warts.very_hairy).to eq([wart.history.last])
|
41
43
|
end
|
42
44
|
|
43
|
-
it
|
44
|
-
expect(Wart.history.at(Time.now).where(person: emily).count).to eq(1)
|
45
|
+
it 'should allow at value on class too' do
|
46
|
+
expect(Wart.history.at(Time.zone.now).where(person: emily).count).to eq(1)
|
45
47
|
expect(Wart.history.at(1.minute.ago).where(person: emily).count).to eq(0)
|
46
48
|
end
|
47
49
|
end
|
48
50
|
|
49
|
-
describe
|
51
|
+
describe 'when reflecting on the past' do
|
50
52
|
let(:orig_emily) { emily.history.at(@init_time).last }
|
51
53
|
|
52
|
-
it
|
53
|
-
expect(orig_emily.name).to eq(
|
54
|
+
it 'should have historical name' do
|
55
|
+
expect(orig_emily.name).to eq('Emily')
|
54
56
|
expect(orig_emily.at_value).to eq(@init_time)
|
55
57
|
end
|
56
58
|
|
57
|
-
it
|
59
|
+
it 'should not belong to a coven or have warts' do
|
58
60
|
expect(orig_emily.coven).to eq(nil)
|
59
61
|
expect(orig_emily.warts.count).to eq(0)
|
60
62
|
end
|
61
63
|
end
|
62
64
|
|
63
|
-
describe
|
65
|
+
describe 'when preloading associations' do
|
64
66
|
let(:orig_emily) { emily.history.at(@init_time).preload(:warts).first }
|
65
67
|
|
66
68
|
it 'should preload the correct time' do
|
@@ -68,7 +70,7 @@ describe Person do
|
|
68
70
|
end
|
69
71
|
end
|
70
72
|
|
71
|
-
describe
|
73
|
+
describe 'when eager_loading associations' do
|
72
74
|
let(:orig_emily) { emily.history.at(@init_time).eager_load(:warts).first }
|
73
75
|
|
74
76
|
it 'should include the correct time' do
|
@@ -76,7 +78,14 @@ describe Person do
|
|
76
78
|
end
|
77
79
|
|
78
80
|
it 'should generate sensible sql' do
|
79
|
-
sql =
|
81
|
+
sql =
|
82
|
+
emily
|
83
|
+
.history
|
84
|
+
.at(@init_time)
|
85
|
+
.eager_load(:warts)
|
86
|
+
.where(Wart.history.arel_table[:hairiness].gteq(2))
|
87
|
+
.to_sql
|
88
|
+
.split(/(FROM)|(WHERE)|(ORDER)/)
|
80
89
|
from = sql[2]
|
81
90
|
where = sql[4]
|
82
91
|
|
@@ -90,15 +99,15 @@ describe Person do
|
|
90
99
|
end
|
91
100
|
end
|
92
101
|
|
93
|
-
describe
|
94
|
-
it
|
95
|
-
expect(emily.class.name).to eq(
|
96
|
-
expect(historical_emily.class.name).to eq(
|
102
|
+
describe 'when checking simple code values' do
|
103
|
+
it 'should have correct class names' do
|
104
|
+
expect(emily.class.name).to eq('Person')
|
105
|
+
expect(historical_emily.class.name).to eq('PersonHistory')
|
97
106
|
|
98
107
|
expect(Person.history).to eq(PersonHistory)
|
99
108
|
end
|
100
109
|
|
101
|
-
it
|
110
|
+
it 'should have correct class hierarchies' do
|
102
111
|
expect(emily.is_a?(Person)).to eq(true)
|
103
112
|
expect(emily.is_a?(PersonHistory)).to eq(false)
|
104
113
|
|
@@ -107,8 +116,8 @@ describe Person do
|
|
107
116
|
end
|
108
117
|
end
|
109
118
|
|
110
|
-
describe
|
111
|
-
it
|
119
|
+
describe 'when checking current state' do
|
120
|
+
it 'should have correct information' do
|
112
121
|
# ie. we shouldn't break regular ActiveRecord behaviour
|
113
122
|
expect(Person.count).to eq(1)
|
114
123
|
expect(Wart.count).to eq(1)
|
@@ -123,20 +132,41 @@ describe Person do
|
|
123
132
|
end
|
124
133
|
end
|
125
134
|
|
126
|
-
describe
|
127
|
-
let!(:broom) { Broom.create person: emily, model:
|
135
|
+
describe 'when working with STI one level deep' do
|
136
|
+
let!(:broom) { Broom.create person: emily, model: 'Cackler 2000' }
|
128
137
|
|
129
|
-
it
|
138
|
+
it 'should initialize model correctly' do
|
130
139
|
expect(emily.history.last.flying_machines).to eq([broom.history.last])
|
131
140
|
end
|
132
141
|
end
|
133
142
|
|
134
|
-
describe
|
135
|
-
let!(:rocket_broom) { RocketBroom.create person: emily, model:
|
143
|
+
describe 'when working with STI two levels deep' do
|
144
|
+
let!(:rocket_broom) { RocketBroom.create person: emily, model: 'Pyrocackler 3000X' }
|
136
145
|
|
137
|
-
it
|
146
|
+
it 'should initialize model correctly' do
|
138
147
|
expect(emily.history.last.flying_machines).to eq([rocket_broom.history.last])
|
139
148
|
end
|
140
149
|
end
|
141
150
|
end
|
151
|
+
|
152
|
+
# The following only tests non-integer ids for postgres (see schema.rb)
|
153
|
+
describe 'when spawning and aging a creature with a non-integer id' do
|
154
|
+
let!(:cat) { Cat.create name: 'Mr. Mittens', color: 'black' }
|
155
|
+
|
156
|
+
before do
|
157
|
+
cat.lives.create started_at: 3.years.ago
|
158
|
+
@init_time = Time.zone.now
|
159
|
+
cat.update name: 'Old Mr. Mittens'
|
160
|
+
cat.lives.first.update ended_at: Time.zone.now, death_reason: 'fell into cauldron'
|
161
|
+
cat.lives.create started_at: Time.zone.now
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'shows one life at the beginning' do
|
165
|
+
expect(cat.history.at(@init_time).last.lives.size).to eq(1)
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'shows two lives at the end' do
|
169
|
+
expect(cat.history.last.lives.size).to eq(2)
|
170
|
+
end
|
171
|
+
end
|
142
172
|
end
|
data/spec/internal/db/schema.rb
CHANGED
@@ -1,22 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
begin
|
4
|
+
postgres = ActiveRecord::Base.connection.instance_of?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
|
5
|
+
rescue NameError
|
6
|
+
postgres = false
|
7
|
+
end
|
8
|
+
|
1
9
|
ActiveRecord::Schema.define do
|
2
|
-
|
3
|
-
t.belongs_to :coven
|
4
|
-
t.string :name
|
5
|
-
end
|
10
|
+
enable_extension 'pgcrypto' if postgres
|
6
11
|
|
7
12
|
create_table :covens, force: true do |t|
|
8
13
|
t.string :name
|
9
14
|
end
|
10
15
|
add_temporal_table :covens
|
11
16
|
|
17
|
+
create_table :people, temporal: true, force: true do |t|
|
18
|
+
t.belongs_to :coven
|
19
|
+
t.string :name
|
20
|
+
end
|
21
|
+
add_index :people, :name, unique: true
|
22
|
+
|
12
23
|
create_table :warts, temporal: true, force: true do |t|
|
13
24
|
t.belongs_to :person
|
14
|
-
t.integer :hairiness
|
15
25
|
end
|
26
|
+
add_column :warts, :hairiness, :integer
|
16
27
|
|
17
28
|
create_table :flying_machines, temporal: true, force: true do |t|
|
18
29
|
t.belongs_to :person
|
19
30
|
t.string :type
|
20
31
|
t.string :model
|
21
32
|
end
|
33
|
+
|
34
|
+
create_table :cats, id: (postgres ? :uuid : :integer), temporal: true, force: true do |t|
|
35
|
+
t.string :name
|
36
|
+
t.string :color
|
37
|
+
end
|
38
|
+
|
39
|
+
create_table :cat_lives, id: (postgres ? :uuid : :integer), temporal: true do |t|
|
40
|
+
t.belongs_to :cat, type: (postgres ? :uuid : :integer)
|
41
|
+
t.timestamp :started_at
|
42
|
+
t.timestamp :ended_at
|
43
|
+
t.string :death_reason
|
44
|
+
end
|
22
45
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,14 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'gemika'
|
2
4
|
require 'combustion'
|
5
|
+
require 'yaml'
|
3
6
|
|
4
|
-
Dir["#{File.dirname(__FILE__)}/extensions/*.rb"].sort.each {|f| require f}
|
5
|
-
Dir["#{File.dirname(__FILE__)}/support/*.rb"].sort.each {|f| require f}
|
7
|
+
Dir["#{File.dirname(__FILE__)}/extensions/*.rb"].sort.each { |f| require f }
|
8
|
+
Dir["#{File.dirname(__FILE__)}/support/*.rb"].sort.each { |f| require f }
|
9
|
+
READ_DATABASE_CONFIG_LOCATION = 'spec/internal/config/database.ci.yml'
|
10
|
+
WRITE_DATABASE_CONFIG_LOCATION = 'spec/internal/config/database.yml'
|
6
11
|
|
7
|
-
|
8
|
-
|
12
|
+
def adapter_name
|
13
|
+
if Gemika::Env.gem?('mysql2')
|
14
|
+
'mysql'
|
15
|
+
else
|
16
|
+
'postgresql'
|
17
|
+
end
|
9
18
|
end
|
10
19
|
|
11
|
-
|
20
|
+
def database_config_from_gems(file_location)
|
21
|
+
config = YAML.load_file(file_location)
|
22
|
+
data = config.slice(adapter_name)
|
23
|
+
{ Rails.env.to_s => data }
|
24
|
+
end
|
25
|
+
|
26
|
+
original_env = Rails.env
|
27
|
+
|
28
|
+
puts database_config_from_gems(READ_DATABASE_CONFIG_LOCATION)
|
29
|
+
File.write(
|
30
|
+
WRITE_DATABASE_CONFIG_LOCATION,
|
31
|
+
database_config_from_gems(READ_DATABASE_CONFIG_LOCATION).to_yaml
|
32
|
+
)
|
33
|
+
|
34
|
+
Rails.env = adapter_name
|
35
|
+
database = Gemika::Database.new
|
36
|
+
database.connect
|
37
|
+
|
38
|
+
Gemika::RSpec.configure_clean_database_before_example
|
39
|
+
Rails.env = original_env
|
40
|
+
|
41
|
+
begin
|
42
|
+
Combustion.initialize! :active_record
|
43
|
+
rescue ActiveRecord::RecordNotUnique
|
44
|
+
# noop
|
45
|
+
end
|
12
46
|
|
13
47
|
RSpec.configure do |config|
|
14
48
|
config.before(:each) do
|
data/spec/support/database.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TemporalTables
|
4
|
+
module DatabaseAdapter
|
5
|
+
def self.adapter_name
|
6
|
+
if Gemika::Env.gem?('pg')
|
7
|
+
'postgresql'
|
8
|
+
elsif Gemika::Env.gem?('mysql2')
|
9
|
+
'mysql'
|
10
|
+
end
|
7
11
|
end
|
8
12
|
end
|
9
13
|
end
|
data/temporal_tables.gemspec
CHANGED
@@ -1,24 +1,37 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'English'
|
4
|
+
lib = File.expand_path('lib', __dir__)
|
3
5
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
6
|
require 'temporal_tables/version'
|
5
7
|
|
6
|
-
Gem::Specification.new do |gem|
|
7
|
-
gem.name
|
8
|
-
gem.version
|
9
|
-
gem.authors
|
10
|
-
gem.email
|
11
|
-
gem.description
|
12
|
-
|
13
|
-
|
8
|
+
Gem::Specification.new do |gem| # rubocop:disable Metrics/BlockLength
|
9
|
+
gem.name = 'temporal_tables'
|
10
|
+
gem.version = TemporalTables::VERSION
|
11
|
+
gem.authors = ['Brent Kroeker']
|
12
|
+
gem.email = ['brent@bkroeker.com']
|
13
|
+
gem.description = <<-DESC
|
14
|
+
Easily recall what your data looked like at any point in the past!
|
15
|
+
TemporalTables sets up and maintains history tables to track all temporal changes to to your data.
|
16
|
+
DESC
|
17
|
+
gem.summary = 'Tracks all history of changes to a table automatically in a history table.'
|
18
|
+
gem.homepage = ''
|
14
19
|
|
15
|
-
gem.files
|
16
|
-
gem.executables
|
17
|
-
gem.test_files
|
18
|
-
gem.require_paths = [
|
20
|
+
gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
21
|
+
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
22
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
23
|
+
gem.require_paths = ['lib']
|
24
|
+
gem.required_ruby_version = '>= 2.5.0'
|
25
|
+
gem.metadata = { 'rubygems_mfa_required' => 'true' }
|
19
26
|
|
20
|
-
gem.add_dependency
|
21
|
-
gem.add_development_dependency
|
22
|
-
gem.add_development_dependency
|
23
|
-
gem.add_development_dependency
|
27
|
+
gem.add_dependency 'rails', '>= 6.0', '< 7.1'
|
28
|
+
gem.add_development_dependency 'combustion', '~> 1'
|
29
|
+
gem.add_development_dependency 'database_cleaner'
|
30
|
+
gem.add_development_dependency 'gemika', '~> 0.6'
|
31
|
+
gem.add_development_dependency 'mysql2'
|
32
|
+
gem.add_development_dependency 'pg'
|
33
|
+
gem.add_development_dependency 'pry'
|
34
|
+
gem.add_development_dependency 'rspec', '~> 3.4'
|
35
|
+
gem.add_development_dependency 'rubocop'
|
36
|
+
gem.metadata['rubygems_mfa_required'] = 'true'
|
24
37
|
end
|