datagrid 1.8.2 → 2.0.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/.yardopts +2 -0
- data/CHANGELOG.md +11 -1
- data/{Readme.markdown → README.md} +44 -29
- data/app/assets/stylesheets/datagrid.css +145 -0
- data/app/views/datagrid/_enum_checkboxes.html.erb +5 -3
- data/app/views/datagrid/_form.html.erb +4 -4
- data/app/views/datagrid/_head.html.erb +26 -3
- data/app/views/datagrid/_range_filter.html.erb +5 -3
- data/app/views/datagrid/_row.html.erb +12 -1
- data/app/views/datagrid/_table.html.erb +4 -4
- data/datagrid.gemspec +8 -7
- data/lib/datagrid/active_model.rb +9 -17
- data/lib/datagrid/base.rb +39 -0
- data/lib/datagrid/column_names_attribute.rb +9 -11
- data/lib/datagrid/columns/column.rb +155 -133
- data/lib/datagrid/columns.rb +325 -115
- data/lib/datagrid/configuration.rb +33 -4
- data/lib/datagrid/core.rb +89 -54
- data/lib/datagrid/deprecated_object.rb +20 -0
- data/lib/datagrid/drivers/abstract_driver.rb +12 -23
- data/lib/datagrid/drivers/active_record.rb +24 -26
- data/lib/datagrid/drivers/array.rb +22 -14
- data/lib/datagrid/drivers/mongo_mapper.rb +15 -14
- data/lib/datagrid/drivers/mongoid.rb +15 -17
- data/lib/datagrid/drivers/sequel.rb +14 -19
- data/lib/datagrid/drivers.rb +2 -1
- data/lib/datagrid/engine.rb +11 -3
- data/lib/datagrid/filters/base_filter.rb +166 -143
- data/lib/datagrid/filters/boolean_filter.rb +19 -5
- data/lib/datagrid/filters/date_filter.rb +33 -35
- data/lib/datagrid/filters/date_time_filter.rb +24 -16
- data/lib/datagrid/filters/default_filter.rb +9 -3
- data/lib/datagrid/filters/dynamic_filter.rb +151 -105
- data/lib/datagrid/filters/enum_filter.rb +43 -19
- data/lib/datagrid/filters/extended_boolean_filter.rb +39 -31
- data/lib/datagrid/filters/float_filter.rb +15 -5
- data/lib/datagrid/filters/integer_filter.rb +21 -10
- data/lib/datagrid/filters/ranged_filter.rb +66 -45
- data/lib/datagrid/filters/select_options.rb +58 -49
- data/lib/datagrid/filters/string_filter.rb +9 -4
- data/lib/datagrid/filters.rb +204 -79
- data/lib/datagrid/form_builder.rb +116 -128
- data/lib/datagrid/generators/scaffold.rb +184 -0
- data/lib/datagrid/generators/views.rb +20 -0
- data/lib/datagrid/helper.rb +436 -69
- data/lib/datagrid/ordering.rb +26 -29
- data/lib/datagrid/rspec.rb +6 -10
- data/lib/datagrid/utils.rb +37 -30
- data/lib/datagrid/version.rb +3 -1
- data/lib/datagrid.rb +8 -28
- data/templates/base.rb.erb +6 -4
- data/templates/grid.rb.erb +1 -1
- metadata +17 -17
- data/app/assets/stylesheets/datagrid.sass +0 -134
- data/lib/datagrid/filters/composite_filters.rb +0 -49
- data/lib/datagrid/renderer.rb +0 -157
- data/lib/datagrid/scaffold.rb +0 -129
- data/lib/tasks/datagrid_tasks.rake +0 -15
- data/templates/controller.rb.erb +0 -6
- data/templates/index.html.erb +0 -5
@@ -1,14 +1,43 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module Datagrid
|
4
|
+
# @return [Configuration] current Datagrid configuration
|
3
5
|
def self.configuration
|
4
6
|
@configuration ||= Configuration.new
|
5
7
|
end
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
+
# @yield block to configure
|
10
|
+
# @yieldparam [Configuration] configuration
|
11
|
+
# @yieldreturn [void]
|
12
|
+
# @return [void] configure datagrid
|
13
|
+
# @see Datagrid::Configuration
|
14
|
+
def self.configure(&block)
|
15
|
+
block.call(configuration)
|
9
16
|
end
|
10
17
|
|
11
|
-
#
|
18
|
+
# ## Configuration
|
19
|
+
#
|
20
|
+
# Datagrid provides several configuration options.
|
21
|
+
#
|
22
|
+
# Here is the API reference and a description of the available options:
|
23
|
+
#
|
24
|
+
# ``` ruby
|
25
|
+
# Datagrid.configure do |config|
|
26
|
+
# # Defines date formats that can be used to parse dates.
|
27
|
+
# # Note: Multiple formats can be specified. The first format is used to format dates as strings,
|
28
|
+
# # while other formats are used only for parsing dates
|
29
|
+
# # from strings (e.g., if your app supports multiple formats).
|
30
|
+
# config.date_formats = "%m/%d/%Y", "%Y-%m-%d"
|
31
|
+
#
|
32
|
+
# # Defines timestamp formats that can be used to parse timestamps.
|
33
|
+
# # Note: Multiple formats can be specified. The first format is used to format timestamps as strings,
|
34
|
+
# # while other formats are used only for parsing timestamps
|
35
|
+
# # from strings (e.g., if your app supports multiple formats).
|
36
|
+
# config.datetime_formats = ["%m/%d/%Y %h:%M", "%Y-%m-%d %h:%M:%s"]
|
37
|
+
# end
|
38
|
+
# ```
|
39
|
+
#
|
40
|
+
# These options can be set globally in your application to customize Datagrid’s behavior.
|
12
41
|
class Configuration
|
13
42
|
# @return [Array<String>] Date parsing formats
|
14
43
|
attr_accessor :date_formats
|
data/lib/datagrid/core.rb
CHANGED
@@ -1,8 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "datagrid/drivers"
|
2
4
|
require "active_support/core_ext/class/attribute"
|
3
5
|
require "active_model/attribute_assignment"
|
4
6
|
|
5
7
|
module Datagrid
|
8
|
+
# Simple example of using Datagrid scope as the assets source to be queried from the database.
|
9
|
+
#
|
10
|
+
# In most cases, the scope is a model class with some default ORM scopes, like `order` or `includes`:
|
11
|
+
#
|
12
|
+
# The scope is also used to:
|
13
|
+
# - Choose an ORM driver (e.g., Mongoid, ActiveRecord, etc.).
|
14
|
+
# - Association preloading
|
15
|
+
# - Columns Providing default order
|
16
|
+
#
|
17
|
+
# You can set the scope at class level or instance level.
|
18
|
+
# Both having appropriate use cases
|
19
|
+
#
|
20
|
+
# @example Defining a scope in a grid class
|
21
|
+
# class ProjectsGrid
|
22
|
+
# include Datagrid
|
23
|
+
# scope { Project.includes(:category) }
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# @example Setting a scope at the instance level
|
27
|
+
# grid = ProjectsGrid.new(grid_params) do |scope|
|
28
|
+
# scope.where(owner_id: current_user.id)
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# grid.assets # => SELECT * FROM projects WHERE projects.owner_id = ? AND [other filtering conditions]
|
32
|
+
#
|
33
|
+
# @example Retrieving and redefining the scope
|
34
|
+
# grid.scope # => SELECT * FROM projects WHERE projects.user_id = ?
|
35
|
+
# grid.redefined_scope? # => true
|
36
|
+
#
|
37
|
+
# # Reset scope to default class value
|
38
|
+
# grid.reset_scope
|
39
|
+
# grid.assets # => SELECT * FROM projects
|
40
|
+
# grid.redefined_scope? # => false
|
41
|
+
#
|
42
|
+
# # Overwriting the scope (ignoring previously defined)
|
43
|
+
# grid.scope { current_user.projects }
|
44
|
+
# grid.redefined_scope? # => true
|
6
45
|
module Core
|
7
46
|
include ::ActiveModel::AttributeAssignment
|
8
47
|
|
@@ -18,25 +57,21 @@ module Datagrid
|
|
18
57
|
end
|
19
58
|
|
20
59
|
module ClassMethods
|
21
|
-
|
22
60
|
# @!visibility private
|
23
61
|
def datagrid_attribute(name, &block)
|
24
|
-
|
25
|
-
block ||= lambda do |value|
|
26
|
-
value
|
27
|
-
end
|
28
|
-
datagrid_attributes << name
|
29
|
-
define_method name do
|
30
|
-
instance_variable_get("@#{name}")
|
31
|
-
end
|
62
|
+
return if datagrid_attributes.include?(name)
|
32
63
|
|
33
|
-
|
34
|
-
|
35
|
-
|
64
|
+
datagrid_attributes << name
|
65
|
+
define_method name do
|
66
|
+
instance_variable_get("@#{name}")
|
67
|
+
end
|
68
|
+
|
69
|
+
define_method :"#{name}=" do |value|
|
70
|
+
instance_variable_set("@#{name}", block ? instance_exec(value, &block) : value)
|
36
71
|
end
|
37
72
|
end
|
38
73
|
|
39
|
-
# Defines a scope
|
74
|
+
# Defines a relation scope of database models to be filtered
|
40
75
|
# @return [void]
|
41
76
|
# @example
|
42
77
|
# scope { User }
|
@@ -109,57 +144,57 @@ module Datagrid
|
|
109
144
|
end
|
110
145
|
end
|
111
146
|
|
112
|
-
|
113
|
-
|
147
|
+
# @!visibility private
|
114
148
|
def check_scope_defined!(message = nil)
|
115
149
|
message ||= "#{self}.scope is not defined"
|
116
150
|
raise(Datagrid::ConfigurationError, message) unless scope_value
|
117
151
|
end
|
118
152
|
|
153
|
+
protected
|
154
|
+
|
155
|
+
# @!visibility private
|
119
156
|
def inherited(child_class)
|
120
|
-
super
|
121
|
-
child_class.datagrid_attributes =
|
157
|
+
super
|
158
|
+
child_class.datagrid_attributes = datagrid_attributes.clone
|
122
159
|
end
|
123
|
-
|
124
160
|
end
|
125
161
|
|
162
|
+
# @param [Hash{String, Symbol => Object}] attributes a hash of attributes to initialize the object
|
163
|
+
# @yield [block] an optional block that is passed to the scope method for further customization
|
164
|
+
# @return [void] Initializes a new instance with optional attributes and an optional block.
|
126
165
|
def initialize(attributes = nil, &block)
|
127
166
|
super()
|
128
167
|
|
129
|
-
if attributes
|
130
|
-
self.attributes = attributes
|
131
|
-
end
|
168
|
+
self.attributes = attributes if attributes
|
132
169
|
|
133
170
|
instance_eval(&dynamic_block) if dynamic_block
|
134
|
-
|
135
|
-
self.scope(&block)
|
136
|
-
end
|
137
|
-
end
|
171
|
+
return unless block_given?
|
138
172
|
|
173
|
+
scope(&block)
|
174
|
+
end
|
139
175
|
|
140
|
-
# @return [Hash
|
176
|
+
# @return [Hash{Symbol => Object}] grid attributes including filter values and ordering values
|
177
|
+
# @example
|
178
|
+
# class UsersGrid < ApplicationGrid
|
179
|
+
# scope { User }
|
180
|
+
# filter(:first_name, :string)
|
181
|
+
# filter(:last_name, :string)
|
182
|
+
# end
|
183
|
+
#
|
184
|
+
# grid = UsersGrid.new(first_name: 'John', last_name: 'Smith')
|
185
|
+
# grid.attributes # => {first_name: 'John', last_name: 'Smith', order: nil, descending: nil}
|
141
186
|
def attributes
|
142
187
|
result = {}
|
143
|
-
|
188
|
+
datagrid_attributes.each do |name|
|
144
189
|
result[name] = self[name]
|
145
190
|
end
|
146
191
|
result
|
147
192
|
end
|
148
193
|
|
149
|
-
#
|
150
|
-
# @param attributes [Hash<Symbol, Object>]
|
151
|
-
# @example
|
152
|
-
# grid = MyGrid.new
|
153
|
-
# grid.attributes = {first_name: 'John', last_name: 'Smith'}
|
154
|
-
# grid.first_name # => 'John'
|
155
|
-
# grid.last_name # => 'Smith'
|
156
|
-
def attributes=(attributes)
|
157
|
-
super(attributes)
|
158
|
-
end
|
159
|
-
|
194
|
+
# @param [String, Symbol] attribute attribute name
|
160
195
|
# @return [Object] Any datagrid attribute value
|
161
196
|
def [](attribute)
|
162
|
-
|
197
|
+
public_send(attribute)
|
163
198
|
end
|
164
199
|
|
165
200
|
# Assigns any datagrid attribute
|
@@ -167,7 +202,7 @@ module Datagrid
|
|
167
202
|
# @param value [Object] Datagrid attribute value
|
168
203
|
# @return [void]
|
169
204
|
def []=(attribute, value)
|
170
|
-
|
205
|
+
public_send(:"#{attribute}=", value)
|
171
206
|
end
|
172
207
|
|
173
208
|
# @return [Object] a scope relation (e.g ActiveRecord::Relation) with all applied filters
|
@@ -175,7 +210,7 @@ module Datagrid
|
|
175
210
|
scope
|
176
211
|
end
|
177
212
|
|
178
|
-
#
|
213
|
+
# @return [Hash{Symbol => Object}] serializable query arguments skipping all nil values
|
179
214
|
# @example
|
180
215
|
# grid = ProductsGrid.new(category: 'dresses', available: true)
|
181
216
|
# grid.as_query # => {category: 'dresses', available: true}
|
@@ -187,7 +222,7 @@ module Datagrid
|
|
187
222
|
attributes
|
188
223
|
end
|
189
224
|
|
190
|
-
# @return [Hash
|
225
|
+
# @return [Hash{Symbol => Hash{Symbol => Object}}] query parameters to link this grid from a page
|
191
226
|
# @example
|
192
227
|
# grid = ProductsGrid.new(category: 'dresses', available: true)
|
193
228
|
# Rails.application.routes.url_helpers.products_path(grid.query_params)
|
@@ -196,7 +231,7 @@ module Datagrid
|
|
196
231
|
{ param_name.to_sym => as_query.merge(attributes) }
|
197
232
|
end
|
198
233
|
|
199
|
-
#
|
234
|
+
# @return [void] redefines scope at instance level
|
200
235
|
# @example
|
201
236
|
# class MyGrid
|
202
237
|
# scope { Article.order('created_at desc') }
|
@@ -224,12 +259,11 @@ module Datagrid
|
|
224
259
|
|
225
260
|
# @!visibility private
|
226
261
|
def original_scope
|
227
|
-
check_scope_defined!
|
262
|
+
self.class.check_scope_defined!
|
228
263
|
scope_value.call
|
229
264
|
end
|
230
265
|
|
231
|
-
# Resets current instance scope to default scope defined in a class
|
232
|
-
# @return [void]
|
266
|
+
# @return [void] Resets current instance scope to default scope defined in a class
|
233
267
|
def reset_scope
|
234
268
|
self.scope_value = self.class.scope_value
|
235
269
|
end
|
@@ -244,11 +278,6 @@ module Datagrid
|
|
244
278
|
self.class.driver
|
245
279
|
end
|
246
280
|
|
247
|
-
# @!visibility private
|
248
|
-
def check_scope_defined!(message = nil)
|
249
|
-
self.class.send :check_scope_defined!, message
|
250
|
-
end
|
251
|
-
|
252
281
|
# @return [String] a datagrid attributes and their values in inspection form
|
253
282
|
def inspect
|
254
283
|
attrs = attributes.map do |key, value|
|
@@ -263,15 +292,21 @@ module Datagrid
|
|
263
292
|
scope == other.scope
|
264
293
|
end
|
265
294
|
|
266
|
-
# Resets loaded assets and column values cache
|
267
|
-
# @return [void]
|
295
|
+
# @return [void] Resets loaded assets and column values cache
|
268
296
|
def reset
|
269
297
|
assets.reset
|
270
298
|
end
|
271
299
|
|
272
300
|
protected
|
301
|
+
|
273
302
|
def sanitize_for_mass_assignment(attributes)
|
274
|
-
forbidden_attributes_protection
|
303
|
+
if forbidden_attributes_protection
|
304
|
+
super
|
305
|
+
elsif defined?(ActionController::Parameters) && attributes.is_a?(ActionController::Parameters)
|
306
|
+
attributes.to_unsafe_h
|
307
|
+
else
|
308
|
+
attributes
|
309
|
+
end
|
275
310
|
end
|
276
311
|
end
|
277
312
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datagrid
|
4
|
+
# @!visibility private
|
5
|
+
class DeprecatedObject < BasicObject
|
6
|
+
def initialize(real_object, &block)
|
7
|
+
@real_object = real_object
|
8
|
+
@block = block
|
9
|
+
end
|
10
|
+
|
11
|
+
def method_missing(method_name, ...)
|
12
|
+
@block.call
|
13
|
+
@real_object.public_send(method_name, ...)
|
14
|
+
end
|
15
|
+
|
16
|
+
def respond_to_missing?(method_name, include_private = false)
|
17
|
+
@real_object.respond_to?(method_name, include_private)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,19 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Datagrid
|
2
4
|
module Drivers
|
3
5
|
# @!visibility private
|
4
6
|
class AbstractDriver
|
5
|
-
|
6
|
-
TIMESTAMP_CLASSES = [DateTime, Time, ActiveSupport::TimeWithZone]
|
7
|
+
TIMESTAMP_CLASSES = [DateTime, Time, ActiveSupport::TimeWithZone].freeze
|
7
8
|
|
8
9
|
class_attribute :subclasses, default: []
|
9
10
|
|
10
11
|
def self.inherited(base)
|
11
|
-
super
|
12
|
-
|
12
|
+
super
|
13
|
+
subclasses << base
|
13
14
|
end
|
14
15
|
|
15
16
|
def self.guess_driver(scope)
|
16
|
-
|
17
|
+
subclasses.find do |driver_class|
|
17
18
|
driver_class.match?(scope)
|
18
19
|
end || raise(Datagrid::ConfigurationError, "ORM Driver not found for scope: #{scope.inspect}.")
|
19
20
|
end
|
@@ -54,7 +55,7 @@ module Datagrid
|
|
54
55
|
raise NotImplementedError
|
55
56
|
end
|
56
57
|
|
57
|
-
def
|
58
|
+
def scope_has_column?(scope, column_name)
|
58
59
|
raise NotImplementedError
|
59
60
|
end
|
60
61
|
|
@@ -62,7 +63,7 @@ module Datagrid
|
|
62
63
|
raise NotImplementedError
|
63
64
|
end
|
64
65
|
|
65
|
-
def
|
66
|
+
def timestamp_column?(scope, field)
|
66
67
|
normalized_column_type(scope, field) == :timestamp
|
67
68
|
end
|
68
69
|
|
@@ -83,28 +84,15 @@ module Datagrid
|
|
83
84
|
end
|
84
85
|
|
85
86
|
def append_column_queries(assets, columns)
|
86
|
-
if columns.present?
|
87
|
-
|
88
|
-
|
89
|
-
assets
|
90
|
-
end
|
87
|
+
raise NotImplementedError if columns.present?
|
88
|
+
|
89
|
+
assets
|
91
90
|
end
|
92
91
|
|
93
92
|
def default_cache_key(asset)
|
94
93
|
raise NotImplementedError
|
95
94
|
end
|
96
95
|
|
97
|
-
def where_by_timestamp_gotcha(scope, name, value)
|
98
|
-
value = Datagrid::Utils.format_date_as_timestamp(value)
|
99
|
-
if value.first
|
100
|
-
scope = greater_equal(scope, name, value.first)
|
101
|
-
end
|
102
|
-
if value.last
|
103
|
-
scope = less_equal(scope, name, value.last)
|
104
|
-
end
|
105
|
-
scope
|
106
|
-
end
|
107
|
-
|
108
96
|
def default_preload(scope, value)
|
109
97
|
raise NotImplementedError
|
110
98
|
end
|
@@ -114,6 +102,7 @@ module Datagrid
|
|
114
102
|
end
|
115
103
|
|
116
104
|
protected
|
105
|
+
|
117
106
|
def timestamp_class?(klass)
|
118
107
|
TIMESTAMP_CLASSES.include?(klass)
|
119
108
|
end
|
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Datagrid
|
2
4
|
module Drivers
|
3
5
|
# @!visibility private
|
4
6
|
class ActiveRecord < AbstractDriver
|
5
|
-
|
6
7
|
def self.match?(scope)
|
7
8
|
return false unless defined?(::ActiveRecord)
|
9
|
+
|
8
10
|
if scope.is_a?(Class)
|
9
11
|
scope.ancestors.include?(::ActiveRecord::Base)
|
10
12
|
else
|
@@ -14,6 +16,7 @@ module Datagrid
|
|
14
16
|
|
15
17
|
def to_scope(scope)
|
16
18
|
return scope if scope.is_a?(::ActiveRecord::Relation)
|
19
|
+
|
17
20
|
# Model class or Active record association
|
18
21
|
# ActiveRecord association class hides itself under an Array
|
19
22
|
# We can only reveal it by checking if it respond to some specific
|
@@ -29,10 +32,8 @@ module Datagrid
|
|
29
32
|
|
30
33
|
def append_column_queries(assets, columns)
|
31
34
|
if columns.present?
|
32
|
-
if assets.select_values.empty?
|
33
|
-
|
34
|
-
end
|
35
|
-
columns = columns.map {|c| "#{c.query} AS #{c.name}"}
|
35
|
+
assets = assets.select(assets.klass.arel_table[Arel.star]) if assets.select_values.empty?
|
36
|
+
columns = columns.map { |c| "#{c.query} AS #{c.name}" }
|
36
37
|
assets = assets.select(*columns)
|
37
38
|
end
|
38
39
|
assets
|
@@ -61,7 +62,7 @@ module Datagrid
|
|
61
62
|
end
|
62
63
|
|
63
64
|
def default_order(scope, column_name)
|
64
|
-
|
65
|
+
scope_has_column?(scope, column_name) ? prefix_table_name(scope, column_name) : nil
|
65
66
|
end
|
66
67
|
|
67
68
|
def greater_equal(scope, field, value)
|
@@ -72,7 +73,7 @@ module Datagrid
|
|
72
73
|
scope.where(["#{prefix_table_name(scope, field)} <= ?", value])
|
73
74
|
end
|
74
75
|
|
75
|
-
def
|
76
|
+
def scope_has_column?(scope, column_name)
|
76
77
|
scope.column_names.include?(column_name.to_s)
|
77
78
|
rescue ::ActiveRecord::StatementInvalid
|
78
79
|
false
|
@@ -88,15 +89,16 @@ module Datagrid
|
|
88
89
|
end
|
89
90
|
|
90
91
|
def normalized_column_type(scope, field)
|
91
|
-
return nil unless
|
92
|
+
return nil unless scope_has_column?(scope, field)
|
93
|
+
|
92
94
|
builtin_type = scope.columns_hash[field.to_s].type
|
93
95
|
{
|
94
|
-
[
|
95
|
-
[
|
96
|
-
[
|
96
|
+
%i[string text time binary] => :string,
|
97
|
+
%i[integer primary_key] => :integer,
|
98
|
+
%i[float decimal] => :float,
|
97
99
|
[:date] => :date,
|
98
|
-
[
|
99
|
-
[:boolean] => :boolean
|
100
|
+
%i[datetime timestamp] => :timestamp,
|
101
|
+
[:boolean] => :boolean,
|
100
102
|
}.each do |keys, value|
|
101
103
|
return value if keys.include?(builtin_type)
|
102
104
|
end
|
@@ -106,6 +108,7 @@ module Datagrid
|
|
106
108
|
if scope.limit_value
|
107
109
|
raise Datagrid::ConfigurationError, "ActiveRecord can not use batches in combination with SQL limit"
|
108
110
|
end
|
111
|
+
|
109
112
|
options = batch_size ? { batch_size: batch_size } : {}
|
110
113
|
scope.find_each(**options, &block)
|
111
114
|
end
|
@@ -119,28 +122,23 @@ module Datagrid
|
|
119
122
|
end
|
120
123
|
|
121
124
|
def can_preload?(scope, association)
|
122
|
-
!!
|
125
|
+
!!scope.klass.reflect_on_association(association)
|
123
126
|
end
|
124
127
|
|
125
128
|
protected
|
126
129
|
|
127
130
|
def prefix_table_name(scope, field)
|
128
|
-
|
131
|
+
scope_has_column?(scope, field) ? [scope.table_name, field].join(".") : field
|
129
132
|
end
|
130
133
|
|
131
134
|
def contains_predicate
|
132
|
-
defined?(::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter) &&
|
133
|
-
|
134
|
-
|
135
|
+
if defined?(::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter) &&
|
136
|
+
::ActiveRecord::Base.connection.is_a?(::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
|
137
|
+
"ilike"
|
138
|
+
else
|
139
|
+
"like"
|
140
|
+
end
|
135
141
|
end
|
136
142
|
end
|
137
143
|
end
|
138
144
|
end
|
139
|
-
|
140
|
-
if defined?(ActiveRecord::Base)
|
141
|
-
ActiveRecord::Base.class_eval do
|
142
|
-
def self.datagrid_where_by_timestamp(column, value)
|
143
|
-
Datagrid::Drivers::ActiveRecord.new.where_by_timestamp_gotcha(self, column, value)
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
@@ -1,8 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Datagrid
|
2
4
|
module Drivers
|
3
5
|
# @!visibility private
|
4
6
|
class Array < AbstractDriver
|
5
|
-
|
6
7
|
def self.match?(scope)
|
7
8
|
!Datagrid::Drivers::ActiveRecord.match?(scope) && (
|
8
9
|
scope.is_a?(::Array) || scope.is_a?(Enumerator) ||
|
@@ -16,15 +17,16 @@ module Datagrid
|
|
16
17
|
|
17
18
|
def where(scope, attribute, value)
|
18
19
|
scope.select do |object|
|
19
|
-
object
|
20
|
+
get(object, attribute) == value
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|
23
24
|
def asc(scope, order)
|
24
25
|
return scope unless order
|
25
26
|
return scope if order.empty?
|
27
|
+
|
26
28
|
scope.sort_by do |object|
|
27
|
-
object
|
29
|
+
get(object, order)
|
28
30
|
end
|
29
31
|
end
|
30
32
|
|
@@ -32,7 +34,7 @@ module Datagrid
|
|
32
34
|
asc(scope, order).reverse
|
33
35
|
end
|
34
36
|
|
35
|
-
def default_order(
|
37
|
+
def default_order(_scope, column_name)
|
36
38
|
column_name
|
37
39
|
end
|
38
40
|
|
@@ -42,36 +44,36 @@ module Datagrid
|
|
42
44
|
|
43
45
|
def greater_equal(scope, field, value)
|
44
46
|
scope.select do |object|
|
45
|
-
object
|
47
|
+
get(object, field) >= value
|
46
48
|
end
|
47
49
|
end
|
48
50
|
|
49
51
|
def less_equal(scope, field, value)
|
50
52
|
scope.select do |object|
|
51
|
-
object
|
53
|
+
get(object, field) <= value
|
52
54
|
end
|
53
55
|
end
|
54
56
|
|
55
|
-
def
|
57
|
+
def scope_has_column?(scope, column_name)
|
56
58
|
scope.any? && scope.first.respond_to?(column_name)
|
57
59
|
end
|
58
60
|
|
59
|
-
def
|
60
|
-
|
61
|
-
timestamp_class?(scope.first
|
61
|
+
def timestamp_column?(scope, column_name)
|
62
|
+
scope_has_column?(scope, column_name) &&
|
63
|
+
timestamp_class?(get(scope.first, column_name).class)
|
62
64
|
end
|
63
65
|
|
64
66
|
def contains(scope, field, value)
|
65
67
|
scope.select do |object|
|
66
|
-
object
|
68
|
+
get(object, field).to_s.include?(value)
|
67
69
|
end
|
68
70
|
end
|
69
71
|
|
70
|
-
def column_names(
|
72
|
+
def column_names(_scope)
|
71
73
|
[]
|
72
74
|
end
|
73
75
|
|
74
|
-
def batch_each(scope,
|
76
|
+
def batch_each(scope, _batch_size, &block)
|
75
77
|
scope.each(&block)
|
76
78
|
end
|
77
79
|
|
@@ -79,9 +81,15 @@ module Datagrid
|
|
79
81
|
asset
|
80
82
|
end
|
81
83
|
|
82
|
-
def can_preload?(
|
84
|
+
def can_preload?(_scope, _association)
|
83
85
|
false
|
84
86
|
end
|
87
|
+
|
88
|
+
protected
|
89
|
+
|
90
|
+
def get(object, property)
|
91
|
+
object.is_a?(Hash) ? object[property] : object.public_send(property)
|
92
|
+
end
|
85
93
|
end
|
86
94
|
end
|
87
95
|
end
|