occams-record 1.4.0 → 1.9.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 +4 -4
- data/README.md +101 -120
- data/lib/occams-record/batches/offset_limit/raw_query.rb +5 -1
- data/lib/occams-record/binds_converter/abstract.rb +71 -0
- data/lib/occams-record/binds_converter/named.rb +35 -0
- data/lib/occams-record/binds_converter/positional.rb +20 -0
- data/lib/occams-record/binds_converter.rb +23 -0
- data/lib/occams-record/cursor.rb +1 -2
- data/lib/occams-record/eager_loaders/ad_hoc_base.rb +27 -14
- data/lib/occams-record/eager_loaders/base.rb +36 -6
- data/lib/occams-record/eager_loaders/belongs_to.rb +0 -1
- data/lib/occams-record/eager_loaders/builder.rb +12 -4
- data/lib/occams-record/eager_loaders/context.rb +21 -9
- data/lib/occams-record/eager_loaders/eager_loaders.rb +1 -0
- data/lib/occams-record/eager_loaders/habtm.rb +5 -7
- data/lib/occams-record/eager_loaders/has_one.rb +0 -1
- data/lib/occams-record/eager_loaders/polymorphic_belongs_to.rb +36 -7
- data/lib/occams-record/eager_loaders/through.rb +32 -17
- data/lib/occams-record/eager_loaders/tracer.rb +16 -0
- data/lib/occams-record/errors.rb +6 -2
- data/lib/occams-record/merge.rb +4 -6
- data/lib/occams-record/pluck.rb +38 -0
- data/lib/occams-record/query.rb +45 -13
- data/lib/occams-record/raw_query.rb +62 -25
- data/lib/occams-record/results/results.rb +25 -30
- data/lib/occams-record/results/row.rb +33 -16
- data/lib/occams-record/type_caster.rb +62 -0
- data/lib/occams-record/version.rb +1 -1
- data/lib/occams-record.rb +7 -0
- metadata +13 -20
@@ -1,7 +1,7 @@
|
|
1
1
|
module OccamsRecord
|
2
2
|
#
|
3
3
|
# Starts building a OccamsRecord::RawQuery. Pass it a raw SQL statement, optionally followed by
|
4
|
-
# a Hash of binds. While this doesn't offer an additional performance boost, it's a nice way to
|
4
|
+
# a Hash or Array of binds. While this doesn't offer an additional performance boost, it's a nice way to
|
5
5
|
# write safe, complicated SQL by hand while also supporting eager loading.
|
6
6
|
#
|
7
7
|
# results = OccamsRecord.sql("
|
@@ -39,10 +39,10 @@ module OccamsRecord
|
|
39
39
|
# It is possible to coerce the SQLite adapter into returning native types for everything IF they're columns of a table
|
40
40
|
# that you have an AR model for. e.g. if you're selecting from the widgets, table: `OccamsRecord.sql("...").model(Widget)...`.
|
41
41
|
#
|
42
|
-
# MySQL
|
42
|
+
# MySQL Mostly native Ruby types, but more testing is needed.
|
43
43
|
#
|
44
|
-
# @param sql [String] The SELECT statement to run. Binds
|
45
|
-
# @param binds [Hash] Bind values (Symbol keys)
|
44
|
+
# @param sql [String] The SELECT statement to run. Binds may be Rails-style (?, :foo) or Ruby-style (%s, %{foo}).
|
45
|
+
# @param binds [Hash] Bind values as Hash (with Symbol keys) or an Array
|
46
46
|
# @param use [Array<Module>] optional Module to include in the result class (single or array)
|
47
47
|
# @param query_logger [Array] (optional) an array into which all queries will be inserted for logging/debug purposes
|
48
48
|
# @return [OccamsRecord::RawQuery]
|
@@ -58,10 +58,11 @@ module OccamsRecord
|
|
58
58
|
class RawQuery
|
59
59
|
# @return [String]
|
60
60
|
attr_reader :sql
|
61
|
-
# @return [Hash]
|
61
|
+
# @return [Hash|Array]
|
62
62
|
attr_reader :binds
|
63
63
|
|
64
64
|
include OccamsRecord::Batches::CursorHelpers
|
65
|
+
include OccamsRecord::Pluck
|
65
66
|
include EagerLoaders::Builder
|
66
67
|
include Enumerable
|
67
68
|
include Measureable
|
@@ -69,8 +70,8 @@ module OccamsRecord
|
|
69
70
|
#
|
70
71
|
# Initialize a new query.
|
71
72
|
#
|
72
|
-
# @param sql [String] The SELECT statement to run. Binds
|
73
|
-
# @param binds [Hash] Bind values (Symbol keys)
|
73
|
+
# @param sql [String] The SELECT statement to run. Binds may be Rails-style (?, :foo) or Ruby-style (%s, %{foo}).
|
74
|
+
# @param binds [Hash] Bind values as Hash (with Symbol keys) or an Array
|
74
75
|
# @param use [Array<Module>] optional Module to include in the result class (single or array)
|
75
76
|
# @param eager_loaders [OccamsRecord::EagerLoaders::Context]
|
76
77
|
# @param query_logger [Array] (optional) an array into which all queries will be inserted for logging/debug purposes
|
@@ -78,7 +79,7 @@ module OccamsRecord
|
|
78
79
|
# @param connection
|
79
80
|
#
|
80
81
|
def initialize(sql, binds, use: nil, eager_loaders: nil, query_logger: nil, measurements: nil, connection: nil)
|
81
|
-
@sql = sql
|
82
|
+
@sql = BindsConverter.convert(sql, binds)
|
82
83
|
@binds = binds
|
83
84
|
@use = use
|
84
85
|
@eager_loaders = eager_loaders || EagerLoaders::Context.new
|
@@ -109,15 +110,16 @@ module OccamsRecord
|
|
109
110
|
def run
|
110
111
|
_escaped_sql = escaped_sql
|
111
112
|
@query_logger << _escaped_sql if @query_logger
|
112
|
-
result =
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
113
|
+
result =
|
114
|
+
if measure?
|
115
|
+
record_start_time!
|
116
|
+
measure!(table_name, _escaped_sql) {
|
117
|
+
conn.exec_query _escaped_sql
|
118
|
+
}
|
119
|
+
else
|
120
|
+
conn.exec_query _escaped_sql
|
121
|
+
end
|
122
|
+
row_class = OccamsRecord::Results.klass(result.columns, result.column_types, @eager_loaders.names, model: @eager_loaders.model, modules: @use, tracer: @eager_loaders.tracer)
|
121
123
|
rows = result.rows.map { |row| row_class.new row }
|
122
124
|
@eager_loaders.run!(rows, query_logger: @query_logger, measurements: @measurements)
|
123
125
|
yield_measurements!
|
@@ -209,19 +211,54 @@ module OccamsRecord
|
|
209
211
|
)
|
210
212
|
end
|
211
213
|
|
214
|
+
#
|
215
|
+
# Returns the column(s) you've SELECT as an array of values.
|
216
|
+
#
|
217
|
+
# If you're selecting multiple columns, you'll get back an array of arrays.
|
218
|
+
# Otherwise you'll get an array of the single column's values.
|
219
|
+
#
|
220
|
+
# @param *args DEPRECATED
|
221
|
+
# @return [Array]
|
222
|
+
#
|
223
|
+
def pluck(*args)
|
224
|
+
$stderr.puts "OccamsRecord: passing arguments to OccamsRecord.sql(\"...\").pluck is deprecated and will be removed in a future version. Called from #{caller[0]}" if args.any?
|
225
|
+
|
226
|
+
_escaped_sql = escaped_sql
|
227
|
+
@query_logger << _escaped_sql if @query_logger
|
228
|
+
result =
|
229
|
+
if measure?
|
230
|
+
record_start_time!
|
231
|
+
measure!(table_name, _escaped_sql) {
|
232
|
+
conn.exec_query _escaped_sql
|
233
|
+
}
|
234
|
+
else
|
235
|
+
conn.exec_query _escaped_sql
|
236
|
+
end
|
237
|
+
pluck_results(result, model: @eager_loaders.model)
|
238
|
+
end
|
239
|
+
|
212
240
|
private
|
213
241
|
|
214
242
|
# Returns the SQL as a String with all variables escaped
|
215
243
|
def escaped_sql
|
216
244
|
return sql if binds.empty?
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
245
|
+
escaped_binds =
|
246
|
+
if binds.is_a? Array
|
247
|
+
binds.map { |val| quote val }
|
248
|
+
else
|
249
|
+
binds.each_with_object({}) { |(col, val), acc|
|
250
|
+
acc[col.to_sym] = quote val
|
251
|
+
}
|
252
|
+
end
|
253
|
+
sql % escaped_binds
|
254
|
+
end
|
255
|
+
|
256
|
+
def quote(val)
|
257
|
+
if val.is_a? Array
|
258
|
+
val.map { |x| conn.quote x }.join(', ')
|
259
|
+
else
|
260
|
+
conn.quote val
|
261
|
+
end
|
225
262
|
end
|
226
263
|
|
227
264
|
def table_name
|
@@ -1,13 +1,6 @@
|
|
1
1
|
module OccamsRecord
|
2
2
|
# Classes and methods for handing query results.
|
3
3
|
module Results
|
4
|
-
# ActiveRecord's internal type casting API changes from version to version.
|
5
|
-
CASTER = case ActiveRecord::VERSION::MAJOR
|
6
|
-
when 4 then :type_cast_from_database
|
7
|
-
when 5, 6, 7 then :deserialize
|
8
|
-
else raise "OccamsRecord::Results::CASTER does yet support this version of ActiveRecord"
|
9
|
-
end
|
10
|
-
|
11
4
|
#
|
12
5
|
# Dynamically build a class for a specific set of result rows. It inherits from OccamsRecord::Results::Row, and optionall prepends
|
13
6
|
# user-defined modules.
|
@@ -17,9 +10,14 @@ module OccamsRecord
|
|
17
10
|
# @param association_names [Array<String>] names of associations that will be eager loaded into the results.
|
18
11
|
# @param model [ActiveRecord::Base] the AR model representing the table (it holds column & type info).
|
19
12
|
# @param modules [Array<Module>] (optional)
|
13
|
+
# @param tracer [OccamsRecord::EagerLoaders::Tracer] the eager loaded that loaded this class of records
|
14
|
+
# @param active_record_fallback [Symbol] If passed, missing methods will be forwarded to an ActiveRecord instance. Options are :lazy (allow lazy loading in the AR record) or :strict (require strict loading)
|
20
15
|
# @return [OccamsRecord::Results::Row] a class customized for this result set
|
21
16
|
#
|
22
|
-
def self.klass(column_names, column_types, association_names = [], model: nil, modules: nil)
|
17
|
+
def self.klass(column_names, column_types, association_names = [], model: nil, modules: nil, tracer: nil, active_record_fallback: nil)
|
18
|
+
raise ArgumentError, "Invalid active_record_fallback option :#{active_record_fallback}. Valid options are :lazy, :strict" if active_record_fallback and !%i(lazy strict).include?(active_record_fallback)
|
19
|
+
raise ArgumentError, "Option active_record_fallback is not allowed when no model is present" if active_record_fallback and model.nil?
|
20
|
+
|
23
21
|
Class.new(Results::Row) do
|
24
22
|
Array(modules).each { |mod| prepend mod } if modules
|
25
23
|
|
@@ -28,36 +26,33 @@ module OccamsRecord
|
|
28
26
|
self._model = model
|
29
27
|
self.model_name = model ? model.name : nil
|
30
28
|
self.table_name = model ? model.table_name : nil
|
31
|
-
self.
|
32
|
-
|
33
|
-
|
29
|
+
self.eager_loader_trace = tracer
|
30
|
+
self.active_record_fallback = active_record_fallback
|
31
|
+
self.primary_key =
|
32
|
+
if model&.primary_key and (pkey = model.primary_key.to_s) and columns.include?(pkey)
|
33
|
+
pkey
|
34
|
+
end
|
34
35
|
|
35
36
|
# Build getters & setters for associations. (We need setters b/c they're set AFTER the row is initialized
|
36
37
|
attr_accessor(*association_names)
|
37
38
|
|
38
39
|
# Build a getter for each attribute returned by the query. The values will be type converted on demand.
|
39
|
-
|
40
|
+
casters = TypeCaster.generate(column_names, column_types, model: model)
|
40
41
|
self.columns.each_with_index do |col, idx|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
#
|
49
|
-
type = column_types[col] || model_column_types&.[](col)
|
50
|
-
case type&.type
|
51
|
-
when nil
|
52
|
-
define_method(col) { @raw_values[idx] }
|
53
|
-
when :datetime
|
54
|
-
define_method(col) { @cast_values[idx] ||= type.send(CASTER, @raw_values[idx])&.in_time_zone }
|
55
|
-
when :boolean
|
56
|
-
define_method(col) { @cast_values[idx] ||= type.send(CASTER, @raw_values[idx]) }
|
57
|
-
define_method("#{col}?") { !!send(col) }
|
42
|
+
caster = casters[col]
|
43
|
+
|
44
|
+
if caster
|
45
|
+
define_method(col) {
|
46
|
+
@cast_values[idx] = caster.(@raw_values[idx]) unless @cast_values.has_key?(idx)
|
47
|
+
@cast_values[idx]
|
48
|
+
}
|
58
49
|
else
|
59
|
-
define_method(col) {
|
50
|
+
define_method(col) {
|
51
|
+
@raw_values[idx]
|
52
|
+
}
|
60
53
|
end
|
54
|
+
|
55
|
+
define_method("#{col}?") { send(col).present? }
|
61
56
|
end
|
62
57
|
end
|
63
58
|
end
|
@@ -19,6 +19,10 @@ module OccamsRecord
|
|
19
19
|
attr_accessor :table_name
|
20
20
|
# Name of primary key column (nil if column wasn't in the SELECT)
|
21
21
|
attr_accessor :primary_key
|
22
|
+
# A trace of how this record was loaded (for debugging)
|
23
|
+
attr_accessor :eager_loader_trace
|
24
|
+
# If present, missing methods will be forwarded to the ActiveRecord model. :lazy allows lazy loading in AR, :strict doesn't
|
25
|
+
attr_accessor :active_record_fallback
|
22
26
|
end
|
23
27
|
self.columns = []
|
24
28
|
self.associations = []
|
@@ -36,7 +40,7 @@ module OccamsRecord
|
|
36
40
|
#
|
37
41
|
# Hash-like accessor for attributes and associations.
|
38
42
|
#
|
39
|
-
# @param attr [String|Symbol
|
43
|
+
# @param attr [String|Symbol]
|
40
44
|
# @return [Object]
|
41
45
|
#
|
42
46
|
def [](attr)
|
@@ -65,21 +69,20 @@ module OccamsRecord
|
|
65
69
|
# @return [Hash] a Hash with String or Symbol keys
|
66
70
|
#
|
67
71
|
def to_h(symbolize_names: false, recursive: false)
|
68
|
-
hash = self.class.columns.
|
72
|
+
hash = self.class.columns.each_with_object({}) { |col_name, acc|
|
69
73
|
key = symbolize_names ? col_name.to_sym : col_name
|
70
|
-
|
71
|
-
a
|
74
|
+
acc[key] = send col_name
|
72
75
|
}
|
73
76
|
|
74
|
-
recursive ? self.class.associations.
|
77
|
+
recursive ? self.class.associations.each_with_object(hash) { |assoc_name, acc|
|
75
78
|
key = symbolize_names ? assoc_name.to_sym : assoc_name
|
76
79
|
assoc = send assoc_name
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
80
|
+
acc[key] =
|
81
|
+
if assoc.is_a? Array
|
82
|
+
assoc.map { |x| x.to_h(symbolize_names: symbolize_names, recursive: true) }
|
83
|
+
elsif assoc
|
84
|
+
assoc.to_h(symbolize_names: symbolize_names, recursive: true)
|
85
|
+
end
|
83
86
|
} : hash
|
84
87
|
end
|
85
88
|
|
@@ -110,19 +113,24 @@ module OccamsRecord
|
|
110
113
|
IDS_SUFFIX = /_ids$/
|
111
114
|
def method_missing(name, *args, &block)
|
112
115
|
model = self.class._model
|
113
|
-
|
116
|
+
ex = NoMethodError.new("Undefined method `#{name}' for #{self.inspect}. Occams Record trace: #{self.class.eager_loader_trace}", name, args)
|
117
|
+
raise ex if model.nil?
|
114
118
|
|
115
119
|
name_str = name.to_s
|
116
120
|
assoc = name_str.sub(IDS_SUFFIX, "").pluralize
|
117
|
-
|
121
|
+
no_args = args.empty? && block.nil?
|
122
|
+
|
123
|
+
if no_args and name_str =~ IDS_SUFFIX and can_define_ids_reader? assoc
|
118
124
|
define_ids_reader! assoc
|
119
125
|
send name
|
120
|
-
elsif model.reflections.has_key? name_str
|
126
|
+
elsif no_args and model.reflections.has_key? name_str
|
121
127
|
raise MissingEagerLoadError.new(self, name)
|
122
|
-
elsif model.columns_hash.has_key? name_str
|
128
|
+
elsif no_args and model.columns_hash.has_key? name_str
|
123
129
|
raise MissingColumnError.new(self, name)
|
130
|
+
elsif self.class.active_record_fallback
|
131
|
+
active_record_fallback(name, *args, &block)
|
124
132
|
else
|
125
|
-
|
133
|
+
raise ex
|
126
134
|
end
|
127
135
|
end
|
128
136
|
|
@@ -141,6 +149,15 @@ module OccamsRecord
|
|
141
149
|
|
142
150
|
private
|
143
151
|
|
152
|
+
def active_record_fallback(name, *args, &block)
|
153
|
+
@active_record_fallback ||= Ugly::active_record(self.class._model, self).tap { |record|
|
154
|
+
record.strict_loading! if self.class.active_record_fallback == :strict
|
155
|
+
}
|
156
|
+
@active_record_fallback.send(name, *args, &block)
|
157
|
+
rescue NoMethodError => e
|
158
|
+
raise NoMethodError.new("#{e.message}. Occams Record trace: #{self.class.eager_loader_trace}.active_record_fallback(#{self.class._model.name})", name, args)
|
159
|
+
end
|
160
|
+
|
144
161
|
def can_define_ids_reader?(assoc)
|
145
162
|
model = self.class._model
|
146
163
|
self.class.associations.include?(assoc) &&
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module OccamsRecord
|
2
|
+
module TypeCaster
|
3
|
+
# @private
|
4
|
+
CASTER =
|
5
|
+
case ActiveRecord::VERSION::MAJOR
|
6
|
+
when 4 then :type_cast_from_database
|
7
|
+
when 5, 6, 7 then :deserialize
|
8
|
+
else raise "OccamsRecord::TypeCaster::CASTER does yet support this version of ActiveRecord"
|
9
|
+
end
|
10
|
+
|
11
|
+
#
|
12
|
+
# Returns a Hash containing type converters (a Proc) for each column. The Proc's accept a value and return a converted value, mapping enum values from the model if necessary.
|
13
|
+
#
|
14
|
+
# NOTE Some columns may have no Proc (particularly if you're using SQLite and running a raw SQL query).
|
15
|
+
#
|
16
|
+
# @param column_names [Array<String>] the column names in the result set (ActiveRecord::Result#columns). The order MUST match the order returned by the query.
|
17
|
+
# @param column_types [Hash] Column name => type (ActiveRecord::Result#column_types)
|
18
|
+
# @param model [ActiveRecord::Base] the AR model representing the table (it holds column & type info as well as enums).
|
19
|
+
# @return [Hash<Proc>] a Hash of casting Proc's keyed by column
|
20
|
+
#
|
21
|
+
def self.generate(column_names, column_types, model: nil)
|
22
|
+
column_names.each_with_object({}) { |col, memo|
|
23
|
+
#
|
24
|
+
# NOTE there's lots of variation between DB adapters and AR versions here. Some notes:
|
25
|
+
# * Postgres AR < 6.1 `column_types` will contain entries for every column.
|
26
|
+
# * Postgres AR >= 6.1 `column_types` only contains entries for "exotic" types. Columns with "common" types have already been converted by the PG adapter.
|
27
|
+
# * SQLite `column_types` will always be empty. Some types will have already been convered by the SQLite adapter, but others will depend on
|
28
|
+
# `model_column_types` for converstion. See test/raw_query_test.rb#test_common_types for examples.
|
29
|
+
# * MySQL ?
|
30
|
+
#
|
31
|
+
type = column_types[col] || model&.attributes_builder&.types&.[](col)
|
32
|
+
|
33
|
+
#
|
34
|
+
# NOTE is also some variation in when enum values are mapped in different AR versions.
|
35
|
+
# In >=5.0, <=7.0, ActiveRecord::Result objects *usually* contain the human-readable values. In 4.2 and
|
36
|
+
# pre-release versions of 7.1, they instead have the RAW values (e.g. integers) which we must map ourselves.
|
37
|
+
#
|
38
|
+
enum = model&.defined_enums&.[](col)
|
39
|
+
inv_enum = enum&.invert
|
40
|
+
|
41
|
+
memo[col] =
|
42
|
+
case type&.type
|
43
|
+
when nil
|
44
|
+
if enum
|
45
|
+
->(val) { enum.has_key?(val) ? val : inv_enum[val] }
|
46
|
+
end
|
47
|
+
when :datetime
|
48
|
+
->(val) { type.send(CASTER, val)&.in_time_zone }
|
49
|
+
else
|
50
|
+
if enum
|
51
|
+
->(val) {
|
52
|
+
val = type.send(CASTER, val)
|
53
|
+
enum.has_key?(val) ? val : inv_enum[val]
|
54
|
+
}
|
55
|
+
else
|
56
|
+
->(val) { type.send(CASTER, val) }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/lib/occams-record.rb
CHANGED
@@ -3,8 +3,10 @@ require 'occams-record/version'
|
|
3
3
|
require 'occams-record/merge'
|
4
4
|
require 'occams-record/measureable'
|
5
5
|
require 'occams-record/eager_loaders/eager_loaders'
|
6
|
+
require 'occams-record/type_caster'
|
6
7
|
require 'occams-record/results/results'
|
7
8
|
require 'occams-record/results/row'
|
9
|
+
require 'occams-record/pluck'
|
8
10
|
require 'occams-record/cursor'
|
9
11
|
require 'occams-record/errors'
|
10
12
|
|
@@ -12,6 +14,11 @@ require 'occams-record/batches/offset_limit/scoped'
|
|
12
14
|
require 'occams-record/batches/offset_limit/raw_query'
|
13
15
|
require 'occams-record/batches/cursor_helpers'
|
14
16
|
|
17
|
+
require 'occams-record/binds_converter'
|
18
|
+
require 'occams-record/binds_converter/abstract'
|
19
|
+
require 'occams-record/binds_converter/named'
|
20
|
+
require 'occams-record/binds_converter/positional'
|
21
|
+
|
15
22
|
require 'occams-record/query'
|
16
23
|
require 'occams-record/raw_query'
|
17
24
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: occams-record
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jordan Hollinger
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-07-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -30,20 +30,6 @@ dependencies:
|
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: '7.1'
|
33
|
-
- !ruby/object:Gem::Dependency
|
34
|
-
name: appraisal
|
35
|
-
requirement: !ruby/object:Gem::Requirement
|
36
|
-
requirements:
|
37
|
-
- - ">="
|
38
|
-
- !ruby/object:Gem::Version
|
39
|
-
version: '0'
|
40
|
-
type: :development
|
41
|
-
prerelease: false
|
42
|
-
version_requirements: !ruby/object:Gem::Requirement
|
43
|
-
requirements:
|
44
|
-
- - ">="
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
version: '0'
|
47
33
|
description: A faster, lower-memory, fuller-featured querying API for ActiveRecord
|
48
34
|
that returns results as unadorned, read-only objects.
|
49
35
|
email: jordan.hollinger@gmail.com
|
@@ -56,6 +42,10 @@ files:
|
|
56
42
|
- lib/occams-record/batches/cursor_helpers.rb
|
57
43
|
- lib/occams-record/batches/offset_limit/raw_query.rb
|
58
44
|
- lib/occams-record/batches/offset_limit/scoped.rb
|
45
|
+
- lib/occams-record/binds_converter.rb
|
46
|
+
- lib/occams-record/binds_converter/abstract.rb
|
47
|
+
- lib/occams-record/binds_converter/named.rb
|
48
|
+
- lib/occams-record/binds_converter/positional.rb
|
59
49
|
- lib/occams-record/cursor.rb
|
60
50
|
- lib/occams-record/eager_loaders/ad_hoc_base.rb
|
61
51
|
- lib/occams-record/eager_loaders/ad_hoc_many.rb
|
@@ -70,20 +60,23 @@ files:
|
|
70
60
|
- lib/occams-record/eager_loaders/has_one.rb
|
71
61
|
- lib/occams-record/eager_loaders/polymorphic_belongs_to.rb
|
72
62
|
- lib/occams-record/eager_loaders/through.rb
|
63
|
+
- lib/occams-record/eager_loaders/tracer.rb
|
73
64
|
- lib/occams-record/errors.rb
|
74
65
|
- lib/occams-record/measureable.rb
|
75
66
|
- lib/occams-record/merge.rb
|
67
|
+
- lib/occams-record/pluck.rb
|
76
68
|
- lib/occams-record/query.rb
|
77
69
|
- lib/occams-record/raw_query.rb
|
78
70
|
- lib/occams-record/results/results.rb
|
79
71
|
- lib/occams-record/results/row.rb
|
72
|
+
- lib/occams-record/type_caster.rb
|
80
73
|
- lib/occams-record/ugly.rb
|
81
74
|
- lib/occams-record/version.rb
|
82
75
|
homepage: https://jhollinger.github.io/occams-record/
|
83
76
|
licenses:
|
84
77
|
- MIT
|
85
78
|
metadata: {}
|
86
|
-
post_install_message:
|
79
|
+
post_install_message:
|
87
80
|
rdoc_options: []
|
88
81
|
require_paths:
|
89
82
|
- lib
|
@@ -98,8 +91,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
98
91
|
- !ruby/object:Gem::Version
|
99
92
|
version: '0'
|
100
93
|
requirements: []
|
101
|
-
rubygems_version: 3.
|
102
|
-
signing_key:
|
94
|
+
rubygems_version: 3.4.1
|
95
|
+
signing_key:
|
103
96
|
specification_version: 4
|
104
97
|
summary: The missing high-efficiency query API for ActiveRecord
|
105
98
|
test_files: []
|