relation_to_struct 1.10.0 → 1.11.1

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: 549ee5cb86cc57e6e4cb814297bedc09d3b3098ddb6c12d463bde197cebf5807
4
- data.tar.gz: 210c9b4e734e438cd67fa4dce3c6385751439f014c159d1e4d1520065b7bb673
3
+ metadata.gz: 1424d19f9ffa5b1ae51ec9fc827910e8ac97551d990d0d3d1050a056da2896f8
4
+ data.tar.gz: 47c097cae34a96dc068bf57f8f04c6094d2cf58c7c2f089e70bcbe8e4d8ac03f
5
5
  SHA512:
6
- metadata.gz: e7068c377384815b4bd582e66453f03b4f67145424ddba922311fb5b0596cb19976455f85e4685af2b360f6481ea5323c6fad8482a100ad312bd6db655c41aad
7
- data.tar.gz: 0d031d351e2162a06674a7d8e09e45a7d3c2ad0a0d376827fa9c4809c927e12efe52c3f1fef3ff16d28fef97d397eb95937d213241e54392abcce92c13087099
6
+ metadata.gz: 14f4a17a7b1961c8257ce9b7bdcc86f2365b58655411a3dfa550c4b3e206cf777fc43d35a21207ed0cf6cea5d3343e6b9a6583817fa2d871ea0fe278b55a565d
7
+ data.tar.gz: 6ec72d1363066eda7fbea68cc7e41ae51f5c3318b719464c8e62763485a7a5984c17f5ff38f85bf500a946a458a048b9812af25f9077fa7b4ccc675da59e428c
@@ -13,17 +13,17 @@ jobs:
13
13
  ruby:
14
14
  - "3.2"
15
15
  - "3.3"
16
+ - "3.4"
16
17
  gemfile:
17
- - rails_7_0
18
- - rails_7_1
19
18
  - rails_7_2
20
19
  - rails_8_0
20
+ - rails_8_1
21
21
  name: PostgreSQL ${{ matrix.pg }} - Ruby ${{ matrix.ruby }} - ${{ matrix.gemfile }}
22
22
  runs-on: ubuntu-latest
23
23
  env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps
24
24
  BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
25
25
  steps:
26
- - uses: actions/checkout@v3
26
+ - uses: actions/checkout@v5
27
27
  - name: Start the postgres container
28
28
  run: docker compose up -d
29
29
  env:
@@ -42,17 +42,17 @@ jobs:
42
42
  ruby:
43
43
  - "3.2"
44
44
  - "3.3"
45
+ - "3.4"
45
46
  gemfile:
46
- - rails_7_0
47
- - rails_7_1
48
47
  - rails_7_2
49
48
  - rails_8_0
49
+ - rails_8_1
50
50
  name: SQLite - Ruby ${{ matrix.ruby }} - ${{ matrix.gemfile }}
51
51
  runs-on: ubuntu-latest
52
52
  env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps
53
53
  BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
54
54
  steps:
55
- - uses: actions/checkout@v3
55
+ - uses: actions/checkout@v5
56
56
  - name: Setup Ruby using .ruby-version file
57
57
  uses: ruby/setup-ruby@v1
58
58
  with:
data/Appraisals CHANGED
@@ -1,6 +1,5 @@
1
- %w(7.0 7.1 7.2 8.0).each do |version|
1
+ %w(7.2 8.0 8.1).each do |version|
2
2
  appraise "rails-#{version.gsub(/\./, "-")}" do
3
3
  gem "rails", "~> #{version}.0"
4
- gem "sqlite3", "~> 1.4" if version == "7.0"
5
4
  end
6
5
  end
data/bin/setup CHANGED
@@ -9,4 +9,4 @@ bundle exec appraisal install
9
9
  # Do any other automated setup that you need to do here
10
10
 
11
11
  # Launch a blank postgres image
12
- docker-compose up -d
12
+ docker compose up -d
data/docker-compose.yml CHANGED
@@ -1,4 +1,3 @@
1
- version: "3.3"
2
1
  services:
3
2
  db:
4
3
  image: postgres:${PGVERSION:-16}
@@ -2,6 +2,6 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "rails", "~> 7.1.0"
5
+ gem "rails", "~> 8.1.0"
6
6
 
7
7
  gemspec path: "../"
@@ -1,7 +1,7 @@
1
1
  module RelationToStruct::ActiveRecordConnectionAdapterExtension
2
2
  def structs_from_sql(struct_class, sql, binds=[])
3
3
  sanitized_sql = ActiveRecord::Base.sanitize_sql(sql)
4
- result = ActiveRecord::Base.uncached do
4
+ result = uncached do
5
5
  select_all(sanitized_sql, "Structs SQL Load", binds)
6
6
  end
7
7
 
@@ -26,7 +26,7 @@ module RelationToStruct::ActiveRecordConnectionAdapterExtension
26
26
 
27
27
  def pluck_from_sql(sql, binds=[])
28
28
  sanitized_sql = ActiveRecord::Base.sanitize_sql(sql)
29
- result = ActiveRecord::Base.uncached do
29
+ result = uncached do
30
30
  select_all(sanitized_sql, "Pluck SQL Load", binds)
31
31
  end
32
32
  result.cast_values()
@@ -34,7 +34,7 @@ module RelationToStruct::ActiveRecordConnectionAdapterExtension
34
34
 
35
35
  def value_from_sql(sql, binds=[])
36
36
  sanitized_sql = ActiveRecord::Base.sanitize_sql(sql)
37
- result = ActiveRecord::Base.uncached do
37
+ result = uncached do
38
38
  select_all(sanitized_sql, "Value SQL Load", binds)
39
39
  end
40
40
  raise ArgumentError, 'Expected exactly one column to be selected' unless result.columns.size == 1
@@ -52,7 +52,7 @@ module RelationToStruct::ActiveRecordConnectionAdapterExtension
52
52
 
53
53
  def tuple_from_sql(sql, binds=[])
54
54
  sanitized_sql = ActiveRecord::Base.sanitize_sql(sql)
55
- result = ActiveRecord::Base.uncached do
55
+ result = uncached do
56
56
  select_all(sanitized_sql, "Value SQL Load", binds)
57
57
  end
58
58
  values = result.cast_values()
@@ -1,3 +1,3 @@
1
1
  module RelationToStruct
2
- VERSION = "1.10.0"
2
+ VERSION = "1.11.1"
3
3
  end
@@ -21,11 +21,11 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency "appraisal", ">= 2.5"
22
22
  spec.add_development_dependency "bundler", ">= 1.7"
23
23
  spec.add_development_dependency "rake", ">= 10.0"
24
- spec.add_development_dependency "sqlite3", ">= 1.4"
24
+ spec.add_development_dependency "sqlite3", ">= 2.1"
25
25
  spec.add_development_dependency "rspec", ">= 3.2"
26
26
  spec.add_development_dependency "pry-byebug"
27
27
  spec.add_development_dependency "pg"
28
28
 
29
- spec.add_dependency "activerecord", ">= 7.0", "< 8.1"
30
- spec.add_dependency "activesupport", ">= 7.0", "< 8.1"
29
+ spec.add_dependency "activerecord", ">= 7.2", "< 8.2"
30
+ spec.add_dependency "activesupport", ">= 7.2", "< 8.2"
31
31
  end
@@ -6,6 +6,69 @@ describe ActiveRecord::Base do
6
6
  EconomicSchool.delete_all
7
7
  end
8
8
 
9
+ # A secondary connection pool simulates a sharded connection — one that belongs
10
+ # to a different pool than ActiveRecord::Base. The old implementation used
11
+ # ActiveRecord::Base.uncached, which only disables the cache on ActiveRecord::Base's
12
+ # pool and has no effect on secondary pools.
13
+ describe "with a subclass using a secondary connection pool" do
14
+ let(:secondary_class) do
15
+ klass = Class.new(ActiveRecord::Base) { self.abstract_class = true }
16
+ stub_const("SecondaryTestConnection", klass)
17
+ klass.establish_connection(ActiveRecord::Base.connection_db_config)
18
+ klass
19
+ end
20
+ after(:each) { secondary_class.remove_connection if secondary_class.connected? }
21
+
22
+ it 'pluck_from_sql bypasses the cache on a subclass using a different pool than ActiveRecord::Base' do
23
+ sql = "SELECT random()"
24
+ value_1 = value_2 = nil
25
+
26
+ secondary_class.cache do
27
+ value_1 = secondary_class.pluck_from_sql(sql)
28
+ value_2 = secondary_class.pluck_from_sql(sql)
29
+ end
30
+
31
+ expect(value_1).not_to eq(value_2)
32
+ end
33
+
34
+ it 'value_from_sql bypasses the cache on a subclass using a different pool than ActiveRecord::Base' do
35
+ sql = "SELECT random()"
36
+ value_1 = value_2 = nil
37
+
38
+ secondary_class.cache do
39
+ value_1 = secondary_class.value_from_sql(sql)
40
+ value_2 = secondary_class.value_from_sql(sql)
41
+ end
42
+
43
+ expect(value_1).not_to eq(value_2)
44
+ end
45
+
46
+ it 'tuple_from_sql bypasses the cache on a subclass using a different pool than ActiveRecord::Base' do
47
+ sql = "SELECT random()"
48
+ value_1 = value_2 = nil
49
+
50
+ secondary_class.cache do
51
+ value_1 = secondary_class.tuple_from_sql(sql)
52
+ value_2 = secondary_class.tuple_from_sql(sql)
53
+ end
54
+
55
+ expect(value_1).not_to eq(value_2)
56
+ end
57
+
58
+ it 'structs_from_sql bypasses the cache on a subclass using a different pool than ActiveRecord::Base' do
59
+ test_struct = Struct.new(:r)
60
+ sql = "SELECT random() AS r"
61
+ value_1 = value_2 = nil
62
+
63
+ secondary_class.cache do
64
+ value_1 = secondary_class.structs_from_sql(test_struct, sql)
65
+ value_2 = secondary_class.structs_from_sql(test_struct, sql)
66
+ end
67
+
68
+ expect(value_1).not_to eq(value_2)
69
+ end
70
+ end
71
+
9
72
  describe "#pluck_from_sql" do
10
73
  it 'allows plucking with SQL directly' do
11
74
  sql = "SELECT 1 * 23"
@@ -8,6 +8,70 @@ describe ActiveRecord::ConnectionAdapters::AbstractAdapter do
8
8
 
9
9
  let(:connection) { ActiveRecord::Base.connection }
10
10
 
11
+ # A secondary connection pool simulates a sharded connection — one that belongs
12
+ # to a different pool than ActiveRecord::Base. The old implementation used
13
+ # ActiveRecord::Base.uncached, which only disables the cache on ActiveRecord::Base's
14
+ # pool and has no effect on secondary pools.
15
+ describe "with a secondary connection pool" do
16
+ let(:secondary_class) do
17
+ klass = Class.new(ActiveRecord::Base) { self.abstract_class = true }
18
+ stub_const("SecondaryTestConnection", klass)
19
+ klass.establish_connection(ActiveRecord::Base.connection_db_config)
20
+ klass
21
+ end
22
+ let(:secondary_connection) { secondary_class.connection }
23
+ after(:each) { secondary_class.remove_connection if secondary_class.connected? }
24
+
25
+ it 'pluck_from_sql bypasses the cache on a connection belonging to a different pool than ActiveRecord::Base' do
26
+ sql = "SELECT random()"
27
+ value_1 = value_2 = nil
28
+
29
+ secondary_class.cache do
30
+ value_1 = secondary_connection.pluck_from_sql(sql)
31
+ value_2 = secondary_connection.pluck_from_sql(sql)
32
+ end
33
+
34
+ expect(value_1).not_to eq(value_2)
35
+ end
36
+
37
+ it 'value_from_sql bypasses the cache on a connection belonging to a different pool than ActiveRecord::Base' do
38
+ sql = "SELECT random()"
39
+ value_1 = value_2 = nil
40
+
41
+ secondary_class.cache do
42
+ value_1 = secondary_connection.value_from_sql(sql)
43
+ value_2 = secondary_connection.value_from_sql(sql)
44
+ end
45
+
46
+ expect(value_1).not_to eq(value_2)
47
+ end
48
+
49
+ it 'tuple_from_sql bypasses the cache on a connection belonging to a different pool than ActiveRecord::Base' do
50
+ sql = "SELECT random()"
51
+ value_1 = value_2 = nil
52
+
53
+ secondary_class.cache do
54
+ value_1 = secondary_connection.tuple_from_sql(sql)
55
+ value_2 = secondary_connection.tuple_from_sql(sql)
56
+ end
57
+
58
+ expect(value_1).not_to eq(value_2)
59
+ end
60
+
61
+ it 'structs_from_sql bypasses the cache on a connection belonging to a different pool than ActiveRecord::Base' do
62
+ test_struct = Struct.new(:r)
63
+ sql = "SELECT random() AS r"
64
+ value_1 = value_2 = nil
65
+
66
+ secondary_class.cache do
67
+ value_1 = secondary_connection.structs_from_sql(test_struct, sql)
68
+ value_2 = secondary_connection.structs_from_sql(test_struct, sql)
69
+ end
70
+
71
+ expect(value_1).not_to eq(value_2)
72
+ end
73
+ end
74
+
11
75
  describe "#pluck_from_sql" do
12
76
  it 'allows plucking with SQL directly' do
13
77
  sql = "SELECT 1 * 23"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: relation_to_struct
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.10.0
4
+ version: 1.11.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Coleman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-11-26 00:00:00.000000000 Z
11
+ date: 2026-04-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: appraisal
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '1.4'
61
+ version: '2.1'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '1.4'
68
+ version: '2.1'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -114,40 +114,40 @@ dependencies:
114
114
  requirements:
115
115
  - - ">="
116
116
  - !ruby/object:Gem::Version
117
- version: '7.0'
117
+ version: '7.2'
118
118
  - - "<"
119
119
  - !ruby/object:Gem::Version
120
- version: '8.1'
120
+ version: '8.2'
121
121
  type: :runtime
122
122
  prerelease: false
123
123
  version_requirements: !ruby/object:Gem::Requirement
124
124
  requirements:
125
125
  - - ">="
126
126
  - !ruby/object:Gem::Version
127
- version: '7.0'
127
+ version: '7.2'
128
128
  - - "<"
129
129
  - !ruby/object:Gem::Version
130
- version: '8.1'
130
+ version: '8.2'
131
131
  - !ruby/object:Gem::Dependency
132
132
  name: activesupport
133
133
  requirement: !ruby/object:Gem::Requirement
134
134
  requirements:
135
135
  - - ">="
136
136
  - !ruby/object:Gem::Version
137
- version: '7.0'
137
+ version: '7.2'
138
138
  - - "<"
139
139
  - !ruby/object:Gem::Version
140
- version: '8.1'
140
+ version: '8.2'
141
141
  type: :runtime
142
142
  prerelease: false
143
143
  version_requirements: !ruby/object:Gem::Requirement
144
144
  requirements:
145
145
  - - ">="
146
146
  - !ruby/object:Gem::Version
147
- version: '7.0'
147
+ version: '7.2'
148
148
  - - "<"
149
149
  - !ruby/object:Gem::Version
150
- version: '8.1'
150
+ version: '8.2'
151
151
  description: ''
152
152
  email:
153
153
  - jtc331@gmail.com
@@ -168,10 +168,9 @@ files:
168
168
  - Rakefile
169
169
  - bin/setup
170
170
  - docker-compose.yml
171
- - gemfiles/rails_7_0.gemfile
172
- - gemfiles/rails_7_1.gemfile
173
171
  - gemfiles/rails_7_2.gemfile
174
172
  - gemfiles/rails_8_0.gemfile
173
+ - gemfiles/rails_8_1.gemfile
175
174
  - lib/relation_to_struct.rb
176
175
  - lib/relation_to_struct/active_record_base_extension.rb
177
176
  - lib/relation_to_struct/active_record_connection_adapter_extension.rb
@@ -1,8 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "rails", "~> 7.0.0"
6
- gem "sqlite3", "~> 1.4"
7
-
8
- gemspec path: "../"