relation_to_struct 1.5.1 → 1.6.0
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 +5 -5
- data/README.md +2 -0
- data/lib/relation_to_struct.rb +1 -0
- data/lib/relation_to_struct/active_record_base_extension.rb +9 -79
- data/lib/relation_to_struct/active_record_connection_adapter_extension.rb +80 -0
- data/lib/relation_to_struct/active_record_relation_extension.rb +1 -3
- data/lib/relation_to_struct/version.rb +1 -1
- data/spec/active_record_connection_adapter_spec.rb +270 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d1ffdbfc2950c798cd223660370ca62ee6a8128b
|
4
|
+
data.tar.gz: 246947abe7a8f85d6c2558a3b33a0b027547ada4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 25ef491ea1f470beea129c8e1d5f92308773092ef470afaadedd56ec9046ad1950d4192e1e61efa816966ecf0dc5eafe40c23bc33ed0572424d0c82368d6cbdf
|
7
|
+
data.tar.gz: 8a8f2eebe3192ae4d3947a309adfd476e903af1bc754496d1f53f03d8040afb8ad12f12f640a4f69dcc54179b015b02399a19b2d712420b0dabed21fff561c2a
|
data/README.md
CHANGED
@@ -36,6 +36,8 @@ relation.to_structs(UserPostsSummary) # => array of structs
|
|
36
36
|
|
37
37
|
### From raw SQL
|
38
38
|
|
39
|
+
Note: In order to provide a consistent user experience regardless of the abstraction level used by your code, all of the following methods are available on both `ActiveRecord::Base` and `ActiveRecord::Base.connection`.
|
40
|
+
|
39
41
|
```
|
40
42
|
UserPostsSummary = Struct.new(:user_name, :post_count)
|
41
43
|
sql = <<-eos
|
data/lib/relation_to_struct.rb
CHANGED
@@ -1,88 +1,18 @@
|
|
1
1
|
module RelationToStruct::ActiveRecordBaseExtension
|
2
|
-
extend ::ActiveSupport::Concern
|
3
|
-
|
4
2
|
module ClassMethods
|
5
3
|
def _sanitize_sql_for_relation_to_struct(sql)
|
6
4
|
sanitized_sql = ActiveRecord::VERSION::MAJOR >= 5 ? sanitize_sql(sql) : sanitize_sql(sql, nil)
|
7
5
|
end
|
8
6
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
18
|
-
|
19
|
-
if result.columns != struct_class.members.collect(&:to_s)
|
20
|
-
raise ArgumentError, 'Expected column names (and their order) to match struct attribute names'
|
21
|
-
end
|
22
|
-
|
23
|
-
if result.columns.size == 1
|
24
|
-
result.cast_values().map do |tuple|
|
25
|
-
struct_class.new(tuple)
|
26
|
-
end
|
27
|
-
else
|
28
|
-
result.cast_values().map do |tuple|
|
29
|
-
struct_class.new(*tuple)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def pluck_from_sql(sql, binds=[])
|
35
|
-
sanitized_sql = _sanitize_sql_for_relation_to_struct(sql)
|
36
|
-
result = ActiveRecord::Base.uncached do
|
37
|
-
connection.select_all(sanitized_sql, "Pluck SQL Load", binds)
|
38
|
-
end
|
39
|
-
result.cast_values()
|
40
|
-
end
|
41
|
-
|
42
|
-
def value_from_sql(sql, binds=[])
|
43
|
-
sanitized_sql = _sanitize_sql_for_relation_to_struct(sql)
|
44
|
-
result = ActiveRecord::Base.uncached do
|
45
|
-
connection.select_all(sanitized_sql, "Value SQL Load", binds)
|
46
|
-
end
|
47
|
-
raise ArgumentError, 'Expected exactly one column to be selected' unless result.columns.size == 1
|
48
|
-
|
49
|
-
values = result.cast_values()
|
50
|
-
case values.size
|
51
|
-
when 0
|
52
|
-
nil
|
53
|
-
when 1
|
54
|
-
values[0]
|
55
|
-
else
|
56
|
-
raise ArgumentError, 'Expected only a single result to be returned'
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def tuple_from_sql(sql, binds=[])
|
61
|
-
sanitized_sql = _sanitize_sql_for_relation_to_struct(sql)
|
62
|
-
result = ActiveRecord::Base.uncached do
|
63
|
-
connection.select_all(sanitized_sql, "Value SQL Load", binds)
|
64
|
-
end
|
65
|
-
values = result.cast_values()
|
66
|
-
|
67
|
-
case values.size
|
68
|
-
when 0
|
69
|
-
nil
|
70
|
-
when 1
|
71
|
-
result.columns.size == 1 ? values : values[0]
|
72
|
-
else
|
73
|
-
raise ArgumentError, 'Expected only a single result to be returned'
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def run_sql(sql, binds=[])
|
78
|
-
sanitized_sql = _sanitize_sql_for_relation_to_struct(sql)
|
79
|
-
# We don't need to build a result set unnecessarily; using
|
80
|
-
# interface this also ensures we're clearing the result set
|
81
|
-
# for manually memory managed object (e.g., when using the
|
82
|
-
# PostgreSQL adaptor).
|
83
|
-
connection.exec_update(sanitized_sql, "Run SQL", binds)
|
84
|
-
end
|
7
|
+
delegate(
|
8
|
+
:structs_from_sql,
|
9
|
+
:pluck_from_sql,
|
10
|
+
:value_from_sql,
|
11
|
+
:tuple_from_sql,
|
12
|
+
:run_sql,
|
13
|
+
:to => :connection
|
14
|
+
)
|
85
15
|
end
|
86
16
|
end
|
87
17
|
|
88
|
-
::ActiveRecord::Base.send(:
|
18
|
+
::ActiveRecord::Base.singleton_class.send(:prepend, RelationToStruct::ActiveRecordBaseExtension::ClassMethods)
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module RelationToStruct::ActiveRecordConnectionAdapterExtension
|
2
|
+
def structs_from_sql(struct_class, sql, binds=[])
|
3
|
+
sanitized_sql = ActiveRecord::Base._sanitize_sql_for_relation_to_struct(sql)
|
4
|
+
result = ActiveRecord::Base.uncached do
|
5
|
+
select_all(sanitized_sql, "Structs SQL Load", binds)
|
6
|
+
end
|
7
|
+
|
8
|
+
if result.columns.size != result.columns.uniq.size
|
9
|
+
raise ArgumentError, 'Expected column names to be unique'
|
10
|
+
end
|
11
|
+
|
12
|
+
if result.columns != struct_class.members.collect(&:to_s)
|
13
|
+
raise ArgumentError, 'Expected column names (and their order) to match struct attribute names'
|
14
|
+
end
|
15
|
+
|
16
|
+
if result.columns.size == 1
|
17
|
+
result.cast_values().map do |tuple|
|
18
|
+
struct_class.new(tuple)
|
19
|
+
end
|
20
|
+
else
|
21
|
+
result.cast_values().map do |tuple|
|
22
|
+
struct_class.new(*tuple)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def pluck_from_sql(sql, binds=[])
|
28
|
+
sanitized_sql = ActiveRecord::Base._sanitize_sql_for_relation_to_struct(sql)
|
29
|
+
result = ActiveRecord::Base.uncached do
|
30
|
+
select_all(sanitized_sql, "Pluck SQL Load", binds)
|
31
|
+
end
|
32
|
+
result.cast_values()
|
33
|
+
end
|
34
|
+
|
35
|
+
def value_from_sql(sql, binds=[])
|
36
|
+
sanitized_sql = ActiveRecord::Base._sanitize_sql_for_relation_to_struct(sql)
|
37
|
+
result = ActiveRecord::Base.uncached do
|
38
|
+
select_all(sanitized_sql, "Value SQL Load", binds)
|
39
|
+
end
|
40
|
+
raise ArgumentError, 'Expected exactly one column to be selected' unless result.columns.size == 1
|
41
|
+
|
42
|
+
values = result.cast_values()
|
43
|
+
case values.size
|
44
|
+
when 0
|
45
|
+
nil
|
46
|
+
when 1
|
47
|
+
values[0]
|
48
|
+
else
|
49
|
+
raise ArgumentError, 'Expected only a single result to be returned'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def tuple_from_sql(sql, binds=[])
|
54
|
+
sanitized_sql = ActiveRecord::Base._sanitize_sql_for_relation_to_struct(sql)
|
55
|
+
result = ActiveRecord::Base.uncached do
|
56
|
+
select_all(sanitized_sql, "Value SQL Load", binds)
|
57
|
+
end
|
58
|
+
values = result.cast_values()
|
59
|
+
|
60
|
+
case values.size
|
61
|
+
when 0
|
62
|
+
nil
|
63
|
+
when 1
|
64
|
+
result.columns.size == 1 ? values : values[0]
|
65
|
+
else
|
66
|
+
raise ArgumentError, 'Expected only a single result to be returned'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def run_sql(sql, binds=[])
|
71
|
+
sanitized_sql = ActiveRecord::Base._sanitize_sql_for_relation_to_struct(sql)
|
72
|
+
# We don't need to build a result set unnecessarily; using
|
73
|
+
# interface this also ensures we're clearing the result set
|
74
|
+
# for manually memory managed object (e.g., when using the
|
75
|
+
# PostgreSQL adaptor).
|
76
|
+
exec_update(sanitized_sql, "Run SQL", binds)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
::ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:prepend, RelationToStruct::ActiveRecordConnectionAdapterExtension)
|
@@ -1,6 +1,4 @@
|
|
1
1
|
module RelationToStruct::ActiveRecordRelationExtension
|
2
|
-
extend ::ActiveSupport::Concern
|
3
|
-
|
4
2
|
def to_structs(struct_class)
|
5
3
|
raise ArgumentError, 'Expected select_values to be present' unless self.select_values.present?
|
6
4
|
|
@@ -37,4 +35,4 @@ module RelationToStruct::ActiveRecordRelationExtension
|
|
37
35
|
end
|
38
36
|
end
|
39
37
|
|
40
|
-
::ActiveRecord::Relation.send(:
|
38
|
+
::ActiveRecord::Relation.send(:prepend, RelationToStruct::ActiveRecordRelationExtension)
|
@@ -0,0 +1,270 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveRecord::ConnectionAdapters::AbstractAdapter do
|
4
|
+
before(:each) do
|
5
|
+
Economist.delete_all
|
6
|
+
EconomicSchool.delete_all
|
7
|
+
end
|
8
|
+
|
9
|
+
let(:connection) { ActiveRecord::Base.connection }
|
10
|
+
|
11
|
+
describe "#pluck_from_sql" do
|
12
|
+
it 'allows plucking with SQL directly' do
|
13
|
+
sql = "SELECT 1 * 23"
|
14
|
+
expect(connection.pluck_from_sql(sql)).to eq([23])
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'allows plucking multiple columns with SQL directly' do
|
18
|
+
sql = "SELECT 1 * 23, 25"
|
19
|
+
expect(connection.pluck_from_sql(sql)).to eq([[23, 25]])
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'bypasses the statement cache' do
|
23
|
+
sql = "SELECT random()"
|
24
|
+
value_1 = value_2 = nil
|
25
|
+
|
26
|
+
# Simulate a standard web request in Rails, since
|
27
|
+
# Rails enabled caching by default.
|
28
|
+
ActiveRecord::Base.cache do
|
29
|
+
value_1 = connection.pluck_from_sql(sql)
|
30
|
+
value_2 = connection.pluck_from_sql(sql)
|
31
|
+
end
|
32
|
+
|
33
|
+
expect(value_1).not_to eq(value_2)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#value_from_sql" do
|
38
|
+
it 'allows selecting a value with SQL directly' do
|
39
|
+
sql = "SELECT 1 * 23"
|
40
|
+
expect(connection.value_from_sql(sql)).to eq(23)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'raises an error when multiple rows are selected' do
|
44
|
+
expect do
|
45
|
+
sql = "SELECT * FROM (VALUES (1), (2)) t"
|
46
|
+
connection.value_from_sql(sql)
|
47
|
+
end.to raise_error(ArgumentError, 'Expected only a single result to be returned')
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'raises an error when multiple columns are selected' do
|
51
|
+
expect do
|
52
|
+
sql = "SELECT 1, 2"
|
53
|
+
connection.value_from_sql(sql)
|
54
|
+
end.to raise_error(ArgumentError, 'Expected exactly one column to be selected')
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'supports binds' do
|
58
|
+
sql = ["SELECT 1 * ?", 5]
|
59
|
+
expect(connection.value_from_sql(sql)).to eq(5)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'supports arrays' do
|
63
|
+
if active_record_supports_arrays?
|
64
|
+
Economist.create!(name: 'F.A. Hayek')
|
65
|
+
Economist.create!(name: 'Ludwig von Mises')
|
66
|
+
|
67
|
+
result = connection.value_from_sql('SELECT ARRAY_AGG(name ORDER BY id) AS names FROM economists')
|
68
|
+
expect(result).to eq(['F.A. Hayek', 'Ludwig von Mises'])
|
69
|
+
else
|
70
|
+
skip "DB selection doesn't support ARRAY[]"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'bypasses the statement cache' do
|
75
|
+
sql = "SELECT random()"
|
76
|
+
value_1 = value_2 = nil
|
77
|
+
|
78
|
+
# Simulate a standard web request in Rails, since
|
79
|
+
# Rails enabled caching by default.
|
80
|
+
ActiveRecord::Base.cache do
|
81
|
+
value_1 = connection.value_from_sql(sql)
|
82
|
+
value_2 = connection.value_from_sql(sql)
|
83
|
+
end
|
84
|
+
|
85
|
+
expect(value_1).not_to eq(value_2)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "#tuple_from_sql" do
|
90
|
+
it 'allows selecting one value with SQL directly' do
|
91
|
+
sql = "SELECT 1"
|
92
|
+
expect(connection.tuple_from_sql(sql)).to eq([1])
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'allows selecting multiple values with SQL directly' do
|
96
|
+
sql = "SELECT 1, 23"
|
97
|
+
expect(connection.tuple_from_sql(sql)).to eq([1, 23])
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'raises an error when multiple rows are selected' do
|
101
|
+
expect do
|
102
|
+
sql = "SELECT * FROM (VALUES (1, 3), (2, 4)) t"
|
103
|
+
connection.tuple_from_sql(sql)
|
104
|
+
end.to raise_error(ArgumentError, 'Expected only a single result to be returned')
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'supports binds' do
|
108
|
+
sql = ["SELECT ?, ?", 5, 6]
|
109
|
+
expect(connection.tuple_from_sql(sql)).to eq([5, 6])
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'supports a single array' do
|
113
|
+
if active_record_supports_arrays?
|
114
|
+
Economist.create!(name: 'F.A. Hayek')
|
115
|
+
Economist.create!(name: 'Ludwig von Mises')
|
116
|
+
|
117
|
+
result = connection.tuple_from_sql(<<-SQL)
|
118
|
+
SELECT ARRAY_AGG(name ORDER BY id) AS names
|
119
|
+
FROM economists
|
120
|
+
SQL
|
121
|
+
expected_names = ['F.A. Hayek', 'Ludwig von Mises']
|
122
|
+
expect(result).to eq([expected_names])
|
123
|
+
else
|
124
|
+
skip "DB selection doesn't support ARRAY[]"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'supports multiple arrays' do
|
129
|
+
if active_record_supports_arrays?
|
130
|
+
Economist.create!(name: 'F.A. Hayek')
|
131
|
+
Economist.create!(name: 'Ludwig von Mises')
|
132
|
+
|
133
|
+
result = connection.tuple_from_sql(<<-SQL)
|
134
|
+
SELECT
|
135
|
+
ARRAY_AGG(name ORDER BY id) AS names,
|
136
|
+
ARRAY_AGG(CHAR_LENGTH(name) ORDER BY id) AS lengths
|
137
|
+
FROM economists
|
138
|
+
SQL
|
139
|
+
expected_names = ['F.A. Hayek', 'Ludwig von Mises']
|
140
|
+
expect(result).to eq([expected_names, expected_names.map(&:size)])
|
141
|
+
else
|
142
|
+
skip "DB selection doesn't support ARRAY[]"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'bypasses the statement cache' do
|
147
|
+
sql = "SELECT random()"
|
148
|
+
value_1 = value_2 = nil
|
149
|
+
|
150
|
+
# Simulate a standard web request in Rails, since
|
151
|
+
# Rails enabled caching by default.
|
152
|
+
ActiveRecord::Base.cache do
|
153
|
+
value_1 = connection.tuple_from_sql(sql)
|
154
|
+
value_2 = connection.tuple_from_sql(sql)
|
155
|
+
end
|
156
|
+
|
157
|
+
expect(value_1).not_to eq(value_2)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
describe "#structs_from_sql" do
|
162
|
+
it 'ActiveRecord::Base should respond to :structs_from_sql' do
|
163
|
+
expect(connection.respond_to?(:structs_from_sql)).to eq(true)
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'allows querying with SQL directly' do
|
167
|
+
test_struct = Struct.new(:number)
|
168
|
+
sql = "SELECT 1 * 23 AS number"
|
169
|
+
expect(connection.structs_from_sql(test_struct, sql)).to eq([test_struct.new(23)])
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'properly casts a single array column' do
|
173
|
+
if active_record_supports_arrays?
|
174
|
+
Economist.create!(name: 'F.A. Hayek')
|
175
|
+
Economist.create!(name: 'Ludwig von Mises')
|
176
|
+
|
177
|
+
test_struct = Struct.new(:names)
|
178
|
+
structs_results = connection.structs_from_sql(test_struct, 'SELECT ARRAY_AGG(name ORDER BY id) AS names FROM economists')
|
179
|
+
expect(structs_results.first.names).to eq(['F.A. Hayek', 'Ludwig von Mises'])
|
180
|
+
else
|
181
|
+
skip "DB selection doesn't support ARRAY[]"
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'raises an error when column count does not match struct size' do
|
186
|
+
expect do
|
187
|
+
test_struct = Struct.new(:id, :name, :extra_field)
|
188
|
+
connection.structs_from_sql(test_struct, 'SELECT id, name FROM economists')
|
189
|
+
end.to raise_error(ArgumentError, 'Expected column names (and their order) to match struct attribute names')
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'raises an error when column names are not unique' do
|
193
|
+
expect do
|
194
|
+
test_struct = Struct.new(:id, :id2)
|
195
|
+
connection.structs_from_sql(test_struct, 'SELECT id, id FROM economists')
|
196
|
+
end.to raise_error(ArgumentError, 'Expected column names to be unique')
|
197
|
+
end
|
198
|
+
|
199
|
+
it 'raises an error when the column names do not match the struct attribute names' do
|
200
|
+
Economist.create!(name: 'F.A. Hayek')
|
201
|
+
expect do
|
202
|
+
test_struct = Struct.new(:value_a, :value_b)
|
203
|
+
connection.structs_from_sql(test_struct, 'SELECT 1 AS value_a, 2 AS value_b FROM economists')
|
204
|
+
end.not_to raise_error
|
205
|
+
|
206
|
+
expect do
|
207
|
+
test_struct = Struct.new(:value_a, :value_b)
|
208
|
+
connection.structs_from_sql(test_struct, 'SELECT 1 AS value_b, 2 AS value_a FROM economists')
|
209
|
+
end.to raise_error(ArgumentError, 'Expected column names (and their order) to match struct attribute names')
|
210
|
+
|
211
|
+
expect do
|
212
|
+
test_struct = Struct.new(:value_a, :value_b)
|
213
|
+
connection.structs_from_sql(test_struct, 'SELECT 1 AS value_a, 2 AS value_c FROM economists')
|
214
|
+
end.to raise_error(ArgumentError, 'Expected column names (and their order) to match struct attribute names')
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'bypasses the statement cache' do
|
218
|
+
test_struct = Struct.new(:r)
|
219
|
+
sql = "SELECT random() AS r"
|
220
|
+
value_1 = value_2 = nil
|
221
|
+
|
222
|
+
# Simulate a standard web request in Rails, since
|
223
|
+
# Rails enabled caching by default.
|
224
|
+
ActiveRecord::Base.cache do
|
225
|
+
value_1 = connection.structs_from_sql(test_struct, sql)
|
226
|
+
value_2 = connection.structs_from_sql(test_struct, sql)
|
227
|
+
end
|
228
|
+
|
229
|
+
expect(value_1).not_to eq(value_2)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
describe "#run_sql" do
|
234
|
+
it 'executes the provided SQL' do
|
235
|
+
sql = "INSERT INTO economic_schools(name) VALUES ('Chicago')"
|
236
|
+
expect do
|
237
|
+
ActiveRecord::Base.run_sql(sql)
|
238
|
+
end.to change { connection.value_from_sql("SELECT COUNT(*) FROM economic_schools") }.by(1)
|
239
|
+
end
|
240
|
+
|
241
|
+
it 'supports binds' do
|
242
|
+
sql = ["INSERT INTO economic_schools(name) VALUES (?)", "Chicago"]
|
243
|
+
expect do
|
244
|
+
ActiveRecord::Base.run_sql(sql)
|
245
|
+
end.to change { connection.value_from_sql("SELECT COUNT(*) FROM economic_schools") }.by(1)
|
246
|
+
end
|
247
|
+
|
248
|
+
it 'uses the exec_update API to avoid turning things in an ActiveRecord::Result' do
|
249
|
+
expect(ActiveRecord::Base.connection).to receive(:exec_update).exactly(:once)
|
250
|
+
sql = "SELECT 1"
|
251
|
+
connection.run_sql(sql)
|
252
|
+
end
|
253
|
+
|
254
|
+
it 'returns the number of rows modified for an INSERT' do
|
255
|
+
sql = "INSERT INTO economic_schools(name) VALUES ('Chicago'), ('Distributism')"
|
256
|
+
expect(connection.run_sql(sql)).to eq(2)
|
257
|
+
end
|
258
|
+
|
259
|
+
it 'bypasses the statement cache' do
|
260
|
+
# Simulate a standard web request in Rails, since
|
261
|
+
# Rails enabled caching by default.
|
262
|
+
ActiveRecord::Base.cache do
|
263
|
+
expect do
|
264
|
+
connection.run_sql("INSERT INTO economic_schools(name) VALUES ('Chicago')")
|
265
|
+
connection.run_sql("INSERT INTO economic_schools(name) VALUES ('Distributism')")
|
266
|
+
end.to change { connection.value_from_sql("SELECT COUNT(*) FROM economic_schools") }.by(2)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
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.
|
4
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Coleman
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-02-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: appraisal
|
@@ -168,10 +168,12 @@ files:
|
|
168
168
|
- gemfiles/rails_6_0.gemfile
|
169
169
|
- lib/relation_to_struct.rb
|
170
170
|
- lib/relation_to_struct/active_record_base_extension.rb
|
171
|
+
- lib/relation_to_struct/active_record_connection_adapter_extension.rb
|
171
172
|
- lib/relation_to_struct/active_record_relation_extension.rb
|
172
173
|
- lib/relation_to_struct/version.rb
|
173
174
|
- relation_to_struct.gemspec
|
174
175
|
- spec/active_record_base_spec.rb
|
176
|
+
- spec/active_record_connection_adapter_spec.rb
|
175
177
|
- spec/active_record_helper/economic_school.rb
|
176
178
|
- spec/active_record_helper/economist.rb
|
177
179
|
- spec/active_record_helper/schema.rb
|
@@ -198,12 +200,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
198
200
|
- !ruby/object:Gem::Version
|
199
201
|
version: '0'
|
200
202
|
requirements: []
|
201
|
-
|
203
|
+
rubyforge_project:
|
204
|
+
rubygems_version: 2.5.2.3
|
202
205
|
signing_key:
|
203
206
|
specification_version: 4
|
204
207
|
summary: Return struct results from ActiveRecord relation queries
|
205
208
|
test_files:
|
206
209
|
- spec/active_record_base_spec.rb
|
210
|
+
- spec/active_record_connection_adapter_spec.rb
|
207
211
|
- spec/active_record_helper/economic_school.rb
|
208
212
|
- spec/active_record_helper/economist.rb
|
209
213
|
- spec/active_record_helper/schema.rb
|