activerecord_views 0.1.0 → 0.1.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 846f267566c95c8e6adc3a7dc503e0aaefa83d48dcd5c27b865f6ff60dc70bc0
4
- data.tar.gz: be109db5a85a682c00244c2ff52d7f29cefb72d20b54ea03431937d04355bdcb
3
+ metadata.gz: e64bd87ba9a26795e83b579cc0047078b712c46f7e63be89f9ba7a5aad7de6d7
4
+ data.tar.gz: a7039933d362f05912e01469ee20f7b66f30004d9e1b036b33e8cc73b8641ce0
5
5
  SHA512:
6
- metadata.gz: 530ed043fe22df67d38ce2a5ce63f65af5617f2ead4e0de329fe47fe6f0072c25f837861f90f222af24e084d43516785a182125becd0b06e81409d930215a0c0
7
- data.tar.gz: ea5cacee78d55faaaa1aed554c34317a43d156f71f5bc017de4a9031df8c3432b0b785da335efdc85b67ee1dcc68ce064fc1bdc707d8214912a8fd69b0281052
6
+ metadata.gz: 2fa8934e9212705d81769c05fcb6271dd42f6baa2dc7525c11a8a78166c65bfb46482fc50caa96d525c182aabf746663fab4431e57c1fb7cae2fcfa35c580fa0
7
+ data.tar.gz: f7f9b27dbe7a1b47c77592cae929f6f2b6cfa2c83cbcbd298eb84d521521eba5f0196cbdb475097fd875558747c7e05ffd77390a57efff3077fabc918cb7d8f7
data/.tool-versions CHANGED
@@ -1 +1 @@
1
- ruby 2.6.7
1
+ ruby 2.7.5
data/Appraisals CHANGED
@@ -1,17 +1,3 @@
1
- appraise 'rails4_2' do
2
- gem 'rails', '~> 4.2.0'
3
- gem "pg", "< 0.21"
4
- end
5
-
6
- appraise 'rails5_0' do
7
- gem 'rails', '~> 5.0.0'
8
- gem "pg", "< 1.0"
9
- end
10
-
11
- appraise 'rails5_1' do
12
- gem 'rails', '~> 5.1.0'
13
- end
14
-
15
1
  appraise 'rails5_2' do
16
2
  gem 'rails', '~> 5.2.0'
17
3
  end
@@ -23,3 +9,7 @@ end
23
9
  appraise 'rails6_1' do
24
10
  gem 'rails', '~> 6.1.0'
25
11
  end
12
+
13
+ appraise 'rails7_0' do
14
+ gem 'rails', '~> 7.0.0.rc1'
15
+ end
@@ -17,7 +17,7 @@ Gem::Specification.new do |gem|
17
17
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
18
  gem.require_paths = ['lib']
19
19
 
20
- gem.add_dependency 'activerecord', ['>= 4.2', '< 6.2']
20
+ gem.add_dependency 'activerecord', ['>= 5.2', '< 7.1']
21
21
 
22
22
  gem.add_development_dependency 'appraisal'
23
23
  gem.add_development_dependency 'rspec-rails', '>= 2.14'
@@ -2,6 +2,6 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "rails", "~> 5.1.0"
5
+ gem "rails", "~> 7.0.0.rc1"
6
6
 
7
7
  gemspec path: "../"
@@ -6,11 +6,7 @@ module ActiveRecordViews
6
6
  end
7
7
 
8
8
  def init_state_table!
9
- table_exists = if Rails::VERSION::MAJOR >= 5
10
- @connection.data_source_exists?('active_record_views')
11
- else
12
- @connection.table_exists?('active_record_views')
13
- end
9
+ table_exists = @connection.data_source_exists?('active_record_views')
14
10
 
15
11
  if table_exists && !@connection.column_exists?('active_record_views', 'class_name')
16
12
  @connection.begin_transaction
@@ -70,10 +70,6 @@ module ActiveRecordViews
70
70
  raise ArgumentError, 'not a materialized view'
71
71
  end
72
72
 
73
- if Rails::VERSION::MAJOR < 5
74
- value = ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.include?(value)
75
- end
76
-
77
73
  value
78
74
  end
79
75
 
@@ -8,19 +8,11 @@ module ActiveRecordViews
8
8
  end
9
9
 
10
10
  unless app.config.cache_classes
11
- if app.respond_to?(:reloader)
12
- app.reloader.before_class_unload do
13
- ActiveRecordViews.reload_stale_views!
14
- end
15
- app.executor.to_run do
16
- ActiveRecordViews.reload_stale_views!
17
- end
18
- else
19
- ActiveSupport.on_load :action_controller do
20
- ActionDispatch::Callbacks.before do
21
- ActiveRecordViews.reload_stale_views!
22
- end
23
- end
11
+ app.reloader.before_class_unload do
12
+ ActiveRecordViews.reload_stale_views!
13
+ end
14
+ app.executor.to_run do
15
+ ActiveRecordViews.reload_stale_views!
24
16
  end
25
17
  end
26
18
  end
@@ -1,3 +1,3 @@
1
1
  module ActiveRecordViews
2
- VERSION = '0.1.0'
2
+ VERSION = '0.1.4'
3
3
  end
@@ -37,24 +37,18 @@ module ActiveRecordViews
37
37
  end
38
38
 
39
39
  def self.without_transaction(connection)
40
- in_transaction = if connection.respond_to? :transaction_open?
41
- connection.transaction_open?
42
- else
43
- !connection.outside_transaction?
44
- end
45
-
46
40
  states = Thread.current[:active_record_views_without_transaction] ||= {}
47
41
 
48
42
  begin
49
43
  if states[connection]
50
44
  yield states[connection]
51
- elsif in_transaction
45
+ elsif connection.transaction_open?
52
46
  begin
53
47
  temp_connection = connection.pool.checkout
54
48
  states[temp_connection] = states[connection] = temp_connection
55
49
  yield temp_connection
56
50
  ensure
57
- connection.pool.checkin temp_connection
51
+ connection.pool.checkin temp_connection if temp_connection
58
52
  states[temp_connection] = states[connection] = nil
59
53
  end
60
54
  else
@@ -9,25 +9,20 @@ end
9
9
  schema_rake_task = Gem::Version.new(Rails.version) >= Gem::Version.new("6.1") ? 'db:schema:dump' : 'db:structure:dump'
10
10
 
11
11
  Rake::Task[schema_rake_task].enhance do
12
- table_exists = if Rails::VERSION::MAJOR >= 5
13
- ActiveRecord::Base.connection.data_source_exists?('active_record_views')
14
- else
15
- ActiveRecord::Base.connection.table_exists?('active_record_views')
16
- end
12
+ table_exists = ActiveRecord::Base.connection.data_source_exists?('active_record_views')
17
13
 
18
14
  if schema_rake_task == 'db:structure:dump'
19
15
  ActiveRecord::Base.schema_format = :sql
20
16
  end
21
17
 
22
- if table_exists && ActiveRecord::Base.schema_format == :sql
23
- tasks = ActiveRecord::Tasks::DatabaseTasks
18
+ schema_format = if ActiveRecord.respond_to?(:schema_format)
19
+ ActiveRecord.schema_format
20
+ else
21
+ ActiveRecord::Base.schema_format
22
+ end
24
23
 
25
- filename = case
26
- when tasks.respond_to?(:dump_filename)
27
- tasks.dump_filename('primary')
28
- else
29
- tasks.schema_file
30
- end
24
+ if table_exists && schema_format == :sql
25
+ tasks = ActiveRecord::Tasks::DatabaseTasks
31
26
 
32
27
  config = if ActiveRecord::Base.configurations.respond_to?(:configs_for)
33
28
  if Rails.version.start_with?('6.0.')
@@ -49,15 +44,56 @@ Rake::Task[schema_rake_task].enhance do
49
44
  config.fetch('database')
50
45
  end
51
46
 
47
+ filename = case
48
+ when tasks.respond_to?(:schema_dump_path)
49
+ tasks.schema_dump_path(config)
50
+ when tasks.respond_to?(:dump_filename)
51
+ tasks.dump_filename('primary')
52
+ else
53
+ tasks.schema_file
54
+ end
55
+
52
56
  pg_tasks = tasks.send(:class_for_adapter, adapter).new(config)
53
- pg_tasks.send(:set_psql_env)
57
+ psql_env = if pg_tasks.respond_to?(:psql_env, true)
58
+ pg_tasks.send(:psql_env)
59
+ else
60
+ pg_tasks.send(:set_psql_env)
61
+ {}
62
+ end
63
+
64
+ begin
65
+ active_record_views_dump = Tempfile.open("active_record_views_dump.sql")
66
+ require 'shellwords'
67
+ system(psql_env, "pg_dump --data-only --no-owner --table=active_record_views #{Shellwords.escape database} >> #{Shellwords.escape active_record_views_dump.path}")
68
+ raise 'active_record_views metadata dump failed' unless $?.success?
54
69
 
55
- require 'shellwords'
56
- system("pg_dump --data-only --table=active_record_views #{Shellwords.escape database} >> #{Shellwords.escape filename}")
57
- raise 'active_record_views metadata dump failed' unless $?.success?
70
+ pg_tasks.send(:remove_sql_header_comments, active_record_views_dump.path)
58
71
 
59
- File.open filename, 'a' do |io|
60
- io.puts 'UPDATE public.active_record_views SET refreshed_at = NULL WHERE refreshed_at IS NOT NULL;'
72
+ # Substitute out any timestamps that were dumped from the active_record_views table
73
+ #
74
+ # Before:
75
+ #
76
+ # COPY public.active_record_views (name, class_name, checksum, options, refreshed_at) FROM stdin;
77
+ # test_view TestView 42364a017b73ef516a0eca9827e6fa00623257ee {"dependencies":[]} 2021-10-26 02:49:12.247494
78
+ # \.
79
+ #
80
+ # After:
81
+ #
82
+ # COPY public.active_record_views (name, class_name, checksum, options, refreshed_at) FROM stdin;
83
+ # test_view TestView 42364a017b73ef516a0eca9827e6fa00623257ee {"dependencies":[]} \N
84
+ # \.
85
+ active_record_views_dump_content = active_record_views_dump.read
86
+ if active_record_views_dump_content !~ /^COPY public.active_record_views \(.+, refreshed_at\) FROM stdin;$/
87
+ raise 'refreshed_at is not final column'
88
+ end
89
+ active_record_views_dump_content.gsub!(/\t\d\d\d\d-\d\d-\d\d.*$/, "\t\\N")
90
+
91
+ File.open filename, 'a' do |io|
92
+ io.puts active_record_views_dump_content
93
+ end
94
+ ensure
95
+ active_record_views_dump.close
96
+ active_record_views_dump.unlink
61
97
  end
62
98
  end
63
99
  end
@@ -5,11 +5,7 @@ describe ActiveRecordViews::ChecksumCache do
5
5
 
6
6
  describe 'initialisation' do
7
7
  def metadata_table_exists?
8
- if Rails::VERSION::MAJOR >= 5
9
- connection.data_source_exists?('active_record_views')
10
- else
11
- connection.table_exists?('active_record_views')
12
- end
8
+ connection.data_source_exists?('active_record_views')
13
9
  end
14
10
 
15
11
  context 'no existing table' do
@@ -8,11 +8,7 @@ describe ActiveRecordViews::Extension do
8
8
 
9
9
  def view_exists?(name)
10
10
  connection = ActiveRecord::Base.connection
11
- if connection.respond_to?(:view_exists?)
12
- connection.view_exists?(name)
13
- else
14
- connection.table_exists?(name)
15
- end
11
+ connection.view_exists?(name)
16
12
  end
17
13
 
18
14
  it 'creates database views from heredocs' do
@@ -119,7 +115,7 @@ describe ActiveRecordViews::Extension do
119
115
  end
120
116
  RB
121
117
 
122
- with_reloader do
118
+ Rails.application.reloader.wrap do
123
119
  expect(DeletedFileTestModel.first.name).to eq 'delete test'
124
120
  end
125
121
 
@@ -133,11 +129,9 @@ describe ActiveRecordViews::Extension do
133
129
  .and change { view_exists?('deleted_file_test_models') }.from(true).to(false)
134
130
  test_request # second request does not `drop_view` again
135
131
 
136
- if Rails::VERSION::MAJOR >= 5
137
- expect {
138
- DeletedFileTestModel.first.name
139
- }.to raise_error NameError, 'uninitialized constant DeletedFileTestModel'
140
- end
132
+ expect {
133
+ DeletedFileTestModel.first.name
134
+ }.to raise_error NameError, 'uninitialized constant DeletedFileTestModel'
141
135
  end
142
136
 
143
137
  it 'does not create if database view is initially up to date' do
@@ -27,10 +27,6 @@ describe ActiveRecordViews do
27
27
  WHERE schemaname = 'public' AND matviewname = 'test'
28
28
  SQL
29
29
 
30
- if Rails::VERSION::MAJOR < 5
31
- value = ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.include?(value)
32
- end
33
-
34
30
  value
35
31
  end
36
32
 
@@ -333,5 +329,16 @@ describe ActiveRecordViews do
333
329
  original_connection.pool.checkin original_connection_2
334
330
  end
335
331
  end
332
+
333
+ it 'does not attempt to checkin when checkout fails' do
334
+ expect(original_connection.pool).to receive(:checkout).and_raise PG::ConnectionBad
335
+ expect(original_connection.pool).to_not receive(:checkin)
336
+
337
+ expect {
338
+ original_connection.transaction do
339
+ ActiveRecordViews.without_transaction(original_connection) { }
340
+ end
341
+ }.to raise_error PG::ConnectionBad
342
+ end
336
343
  end
337
344
  end
@@ -12,6 +12,9 @@ Combustion.initialize! :active_record, :action_controller do
12
12
  config.cache_classes = false
13
13
  config.log_level = :debug
14
14
  config.active_record.schema_format = ENV.fetch('SCHEMA_FORMAT', 'sql').to_sym
15
+ if Gem::Version.new(Rails.version) >= Gem::Version.new("6.1")
16
+ config.active_record.legacy_connection_handling = false
17
+ end
15
18
  if ENV['SKIP_MODEL_EAGER_LOAD']
16
19
  config.eager_load_paths -= Rails.application.config.paths['app/models'].to_a
17
20
  end
data/spec/spec_helper.rb CHANGED
@@ -18,6 +18,9 @@ Rails.application.config.paths['app/models'] << 'app/models_temp'
18
18
 
19
19
  Combustion.initialize! :active_record, :action_controller do
20
20
  config.cache_classes = false
21
+ if Gem::Version.new(Rails.version) >= Gem::Version.new("6.1")
22
+ config.active_record.legacy_connection_handling = false
23
+ end
21
24
  end
22
25
  require 'rspec/rails'
23
26
  require 'super_diff/rspec-rails'
@@ -50,12 +53,7 @@ RSpec.configure do |config|
50
53
  config.before do
51
54
  FileUtils.rm_rf Dir["spec/internal/app/models_temp/*"]
52
55
 
53
- if Rails::VERSION::MAJOR >= 5
54
- Rails.application.reloader.reload!
55
- else
56
- ActionDispatch::Reloader.cleanup!
57
- ActionDispatch::Reloader.prepare!
58
- end
56
+ Rails.application.reloader.reload!
59
57
 
60
58
  connection = ActiveRecord::Base.connection
61
59
 
@@ -83,16 +81,8 @@ RSpec.configure do |config|
83
81
  config.include_context 'sql_statements'
84
82
  end
85
83
 
86
- def with_reloader(&block)
87
- if Rails.application.respond_to?(:reloader)
88
- Rails.application.reloader.wrap(&block)
89
- else
90
- block.call
91
- end
92
- end
93
-
94
84
  def test_request
95
- with_reloader do
85
+ Rails.application.reloader.wrap do
96
86
  status, headers, body = Rails.application.call(
97
87
  'REQUEST_METHOD' => 'GET',
98
88
  'PATH_INFO' => '/',
@@ -1,23 +1,6 @@
1
1
  require 'warning'
2
2
  require 'rails/version'
3
3
 
4
- case Rails::VERSION::STRING
5
- when /^4\.2\./
6
- Warning.ignore(%r{lib/(active_support/core_ext|action_dispatch/middleware)/.+: warning: (method redefined|previous definition)})
7
- Warning.ignore(%r{lib/active_support/core_ext/.+: warning: BigDecimal.new is deprecated})
8
- Warning.ignore(%r{lib/arel/visitors/informix.rb:\d+: warning: assigned but unused variable})
9
- Warning.ignore(%r{lib/active_record/connection_adapters/.+: warning: deprecated Object#=~ is called on Integer})
10
- Warning.ignore(%r{Inheriting from Rack::Session::Abstract::ID is deprecated})
11
- when /^5\.0\./
12
- Warning.ignore(%r{lib/(active_support/core_ext|action_view)/.+: warning: (method redefined|previous definition)})
13
- Warning.ignore(%r{lib/arel/visitors/informix.rb:\d+: warning: assigned but unused variable})
14
- Warning.ignore(%r{lib/action_view/.+: warning: `\*' interpreted as argument prefix})
15
- when /^5\.1\./
16
- Warning.ignore(%r{lib/(active_support/core_ext)/.+: warning: (method redefined|previous definition)})
17
- Warning.ignore(%r{lib/arel/visitors/informix.rb:\d+: warning: assigned but unused variable})
18
- Warning.ignore(%r{lib/active_record/.+/schema_statements.rb:\d+: (warning: in `drop_table': the last argument was passed as a single Hash|warning: although a splat keyword arguments here)})
19
- end
20
-
21
4
  Warning.process do |_warning|
22
5
  :raise
23
6
  end
data/spec/tasks_spec.rb CHANGED
@@ -77,8 +77,27 @@ describe 'rake tasks' do
77
77
 
78
78
  expect(File.exist?('spec/internal/db/schema.rb')).to eq false
79
79
  sql = File.read('spec/internal/db/structure.sql')
80
- expect(sql).to match(/COPY public\.active_record_views.+test_view\tTestView/m)
81
- expect(sql).to match(/UPDATE public\.active_record_views SET refreshed_at = NULL/)
80
+ expect(sql).to match(/CREATE TABLE public\.schema_migrations/)
81
+ expect(sql).to match(/CREATE VIEW public\.test_view/)
82
+ expect(sql).to match(/COPY public\.active_record_views.+test_view\tTestView\t.*\t.*\t\\N$/m)
83
+ end
84
+
85
+ it 'clears refreshed_at values' do
86
+ ActiveRecord::Base.connection.execute "UPDATE active_record_views SET refreshed_at = current_timestamp AT TIME ZONE 'UTC' WHERE name = 'test_view';"
87
+
88
+ rake schema_rake_task
89
+
90
+ ActiveRecord::Base.clear_all_connections!
91
+
92
+ system 'dropdb activerecord_views_test'
93
+ raise unless $?.success?
94
+ system 'createdb activerecord_views_test'
95
+ raise unless $?.success?
96
+ system 'psql -X -q -o /dev/null -f spec/internal/db/structure.sql activerecord_views_test'
97
+ raise unless $?.success?
98
+
99
+ refreshed_ats = ActiveRecord::Base.connection.select_values("SELECT refreshed_at FROM active_record_views WHERE name = 'test_view'")
100
+ expect(refreshed_ats).to eq [nil]
82
101
  end
83
102
 
84
103
  it 'does not write structure.sql when `schema_format = :ruby`', if: schema_rake_task != 'db:structure:dump' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord_views
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Weathered
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-29 00:00:00.000000000 Z
11
+ date: 2021-12-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,20 +16,20 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '4.2'
19
+ version: '5.2'
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '6.2'
22
+ version: '7.1'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: '4.2'
29
+ version: '5.2'
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '6.2'
32
+ version: '7.1'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: appraisal
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -130,12 +130,10 @@ files:
130
130
  - README.markdown
131
131
  - Rakefile
132
132
  - activerecord_views.gemspec
133
- - gemfiles/rails4_2.gemfile
134
- - gemfiles/rails5_0.gemfile
135
- - gemfiles/rails5_1.gemfile
136
133
  - gemfiles/rails5_2.gemfile
137
134
  - gemfiles/rails6_0.gemfile
138
135
  - gemfiles/rails6_1.gemfile
136
+ - gemfiles/rails7_0.gemfile
139
137
  - lib/active_record_views.rb
140
138
  - lib/active_record_views/checksum_cache.rb
141
139
  - lib/active_record_views/database_cleaner/truncation_extension.rb
@@ -185,7 +183,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
185
183
  - !ruby/object:Gem::Version
186
184
  version: '0'
187
185
  requirements: []
188
- rubygems_version: 3.0.3.1
186
+ rubygems_version: 3.2.32
189
187
  signing_key:
190
188
  specification_version: 4
191
189
  summary: Automatic database view creation for ActiveRecord
@@ -1,8 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "rails", "~> 4.2.0"
6
- gem "pg", "< 0.21"
7
-
8
- gemspec path: "../"
@@ -1,8 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "rails", "~> 5.0.0"
6
- gem "pg", "< 1.0"
7
-
8
- gemspec path: "../"