datagrid 1.8.1 → 2.0.0.pre.alpha
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/CHANGELOG.md +31 -7
- data/{Readme.markdown → README.md} +46 -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 -5
- 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 -8
- data/lib/datagrid/active_model.rb +9 -17
- data/lib/datagrid/base.rb +39 -0
- data/lib/datagrid/column_names_attribute.rb +12 -12
- data/lib/datagrid/columns/column.rb +155 -133
- data/lib/datagrid/columns.rb +495 -282
- data/lib/datagrid/configuration.rb +23 -10
- data/lib/datagrid/core.rb +184 -150
- data/lib/datagrid/deprecated_object.rb +20 -0
- data/lib/datagrid/drivers/abstract_driver.rb +13 -25
- data/lib/datagrid/drivers/active_record.rb +24 -26
- data/lib/datagrid/drivers/array.rb +26 -17
- data/lib/datagrid/drivers/mongo_mapper.rb +15 -14
- data/lib/datagrid/drivers/mongoid.rb +16 -18
- 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 -142
- 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 -27
- data/lib/datagrid/filters/float_filter.rb +16 -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 +234 -106
- data/lib/datagrid/form_builder.rb +116 -128
- data/lib/datagrid/generators/scaffold.rb +185 -0
- data/lib/datagrid/generators/views.rb +20 -0
- data/lib/datagrid/helper.rb +397 -22
- data/lib/datagrid/ordering.rb +81 -87
- data/lib/datagrid/rspec.rb +8 -12
- data/lib/datagrid/utils.rb +42 -38
- data/lib/datagrid/version.rb +3 -1
- data/lib/datagrid.rb +18 -28
- data/templates/base.rb.erb +33 -7
- data/templates/grid.rb.erb +1 -1
- metadata +18 -19
- 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,57 +1,66 @@
|
|
1
|
-
|
2
|
-
def select(object)
|
3
|
-
select = self.options[:select]
|
4
|
-
if select.is_a?(Symbol)
|
5
|
-
object.send(select)
|
6
|
-
elsif select.respond_to?(:call)
|
7
|
-
Datagrid::Utils.apply_args(object, &select)
|
8
|
-
else
|
9
|
-
select
|
10
|
-
end
|
11
|
-
end
|
1
|
+
# frozen_string_literal: true
|
12
2
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
3
|
+
module Datagrid
|
4
|
+
module Filters
|
5
|
+
module SelectOptions
|
6
|
+
def select(object)
|
7
|
+
select = options[:select]
|
8
|
+
if select.is_a?(Symbol)
|
9
|
+
object.send(select)
|
10
|
+
elsif select.respond_to?(:call)
|
11
|
+
Datagrid::Utils.apply_args(object, &select)
|
12
|
+
else
|
13
|
+
select
|
14
|
+
end
|
21
15
|
end
|
22
|
-
end.map(&:last)
|
23
|
-
end
|
24
16
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
17
|
+
def select_values(object)
|
18
|
+
options = select(object)
|
19
|
+
groups_used = grouped_choices?(options)
|
20
|
+
options.map do |option|
|
21
|
+
if groups_used
|
22
|
+
option[1].map { |o| option_text_and_value(o) }
|
23
|
+
else
|
24
|
+
option_text_and_value(option)
|
25
|
+
end
|
26
|
+
end.map(&:last)
|
27
|
+
end
|
31
28
|
|
32
|
-
|
33
|
-
|
34
|
-
end
|
29
|
+
def include_blank
|
30
|
+
return if prompt
|
35
31
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
end
|
49
|
-
end
|
32
|
+
if options.key?(:include_blank)
|
33
|
+
Datagrid::Utils.callable(options[:include_blank])
|
34
|
+
else
|
35
|
+
!multiple?
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def prompt
|
40
|
+
options.key?(:prompt) ? Datagrid::Utils.callable(options[:prompt]) : false
|
41
|
+
end
|
42
|
+
|
43
|
+
protected
|
50
44
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
45
|
+
# Rails built-in method:
|
46
|
+
# https://github.com/rails/rails/blob/94e80269e36caf7b2d22a7ab68e6898d3a824122/actionview/lib/action_view/helpers/form_options_helper.rb#L789
|
47
|
+
# Code reuse is difficult, so it is easier to duplicate it
|
48
|
+
def option_text_and_value(option)
|
49
|
+
# Options are [text, value] pairs or strings used for both.
|
50
|
+
if !option.is_a?(String) && option.respond_to?(:first) && option.respond_to?(:last)
|
51
|
+
option = option.reject { |e| e.is_a?(Hash) } if option.is_a?(Array)
|
52
|
+
[option.first, option.last]
|
53
|
+
else
|
54
|
+
[option, option]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Rails built-in method:
|
59
|
+
# https://github.com/rails/rails/blob/f95c0b7e96eb36bc3efc0c5beffbb9e84ea664e4/actionview/lib/action_view/helpers/tags/select.rb#L36
|
60
|
+
# Code reuse is difficult, so it is easier to duplicate it
|
61
|
+
def grouped_choices?(choices)
|
62
|
+
!choices.blank? && choices.first.respond_to?(:last) && choices.first.last.is_a?(Array)
|
63
|
+
end
|
64
|
+
end
|
56
65
|
end
|
57
66
|
end
|
@@ -1,8 +1,13 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
module Datagrid
|
4
|
+
module Filters
|
5
|
+
class StringFilter < Datagrid::Filters::BaseFilter
|
6
|
+
include Datagrid::Filters::RangedFilter
|
4
7
|
|
5
|
-
|
6
|
-
|
8
|
+
def parse(value)
|
9
|
+
value&.to_s
|
10
|
+
end
|
11
|
+
end
|
7
12
|
end
|
8
13
|
end
|
data/lib/datagrid/filters.rb
CHANGED
@@ -1,8 +1,135 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/class/attribute"
|
2
4
|
|
3
5
|
module Datagrid
|
6
|
+
# Defines the accessible attribute that is used to filter
|
7
|
+
# the scope by the specified value with specified code.
|
8
|
+
#
|
9
|
+
# class UserGrid < ApplicationGrid
|
10
|
+
# scope do
|
11
|
+
# User
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# filter(:name)
|
15
|
+
# filter(:posts_count, :integer) do |value|
|
16
|
+
# self.where(["posts_count >= ?", value])
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# Each filter becomes a grid attribute.
|
21
|
+
#
|
22
|
+
# To create a grid displaying all users with the name 'John' who have more than zero posts:
|
23
|
+
#
|
24
|
+
# grid = UserGrid.new(posts_count: 1, name: "John")
|
25
|
+
# grid.assets # SELECT * FROM users WHERE users.posts_count > 1 AND name = 'John'
|
26
|
+
#
|
27
|
+
# # Filter Block
|
28
|
+
#
|
29
|
+
# Filter blocks should always return a chainable ORM object (e.g., `ActiveRecord::Relation`) rather than an `Array`.
|
30
|
+
#
|
31
|
+
# Filter blocks should have at least one argument representing the value assigned to the grid object attribute:
|
32
|
+
#
|
33
|
+
# filter(:name, :string) # { |value| where(name: value) }
|
34
|
+
#
|
35
|
+
# You can pass additional arguments:
|
36
|
+
#
|
37
|
+
# filter(:name, :string) { |value, scope| scope.where("name ilike ?", "%#{value}%") }
|
38
|
+
# filter(:name, :string) do |value, scope, grid|
|
39
|
+
# scope.where("name #{grid.predicate} ?", "%#{value}%")
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# # Filter Types
|
43
|
+
#
|
44
|
+
# Filters perform automatic type conversion. Supported filter types include:
|
45
|
+
#
|
46
|
+
# - `default`
|
47
|
+
# - `date`
|
48
|
+
# - `datetime`
|
49
|
+
# - `enum`
|
50
|
+
# - `boolean`
|
51
|
+
# - `xboolean`
|
52
|
+
# - `integer`
|
53
|
+
# - `float`
|
54
|
+
# - `string`
|
55
|
+
# - `dynamic`
|
56
|
+
#
|
57
|
+
# ## Default
|
58
|
+
#
|
59
|
+
# `:default` - Leaves the value as is.
|
60
|
+
#
|
61
|
+
# ## Date
|
62
|
+
#
|
63
|
+
# `:date` - Converts value to a date. Supports the `:range` option to accept date ranges.
|
64
|
+
#
|
65
|
+
# filter(:created_at, :date, range: true, default: proc { 1.month.ago.to_date..Date.today })
|
66
|
+
#
|
67
|
+
# ## Datetime
|
68
|
+
#
|
69
|
+
# `:datetime` - Converts value to a timestamp. Supports the `:range` option to accept time ranges.
|
70
|
+
#
|
71
|
+
# filter(:created_at, :datetime, range: true, default: proc { 1.hour.ago..Time.now })
|
72
|
+
#
|
73
|
+
# ## Enum
|
74
|
+
#
|
75
|
+
# `:enum` - For collection selection with options like `:select` and `:multiple`.
|
76
|
+
#
|
77
|
+
# filter(:user_type, :enum, select: ['Admin', 'Customer', 'Manager'])
|
78
|
+
# filter(:category_id, :enum, select: proc { Category.all.map { |c| [c.name, c.id] } }, multiple: true)
|
79
|
+
#
|
80
|
+
# ## Boolean
|
81
|
+
#
|
82
|
+
# `:boolean` - Converts value to `true` or `false`.
|
83
|
+
#
|
84
|
+
# ## Xboolean
|
85
|
+
#
|
86
|
+
# `:xboolean` - Subtype of `enum` filter that provides "Yes", "No", and "Any" options.
|
87
|
+
#
|
88
|
+
# filter(:active, :xboolean)
|
89
|
+
#
|
90
|
+
# ## Integer
|
91
|
+
#
|
92
|
+
# `:integer` - Converts value to an integer. Supports the `:range` option.
|
93
|
+
#
|
94
|
+
# filter(:posts_count, :integer, range: true, default: (1..nil))
|
95
|
+
#
|
96
|
+
# ## String
|
97
|
+
#
|
98
|
+
# `:string` - Converts value to a string.
|
99
|
+
#
|
100
|
+
# filter(:email, :string)
|
101
|
+
#
|
102
|
+
# ## Dynamic
|
103
|
+
#
|
104
|
+
# Provides a builder for dynamic SQL conditions.
|
105
|
+
#
|
106
|
+
# filter(:condition1, :dynamic)
|
107
|
+
# filter(:condition2, :dynamic)
|
108
|
+
# UsersGrid.new(condition1: [:name, "=~", "John"], condition2: [:posts_count, ">=", 1])
|
109
|
+
# UsersGrid.assets # SELECT * FROM users WHERE name like '%John%' and posts_count >= 1
|
110
|
+
#
|
111
|
+
# # Filter Options
|
112
|
+
#
|
113
|
+
# Options that can be passed to any filter:
|
114
|
+
#
|
115
|
+
# - `:header` - Human-readable filter name (default: generated from the filter name).
|
116
|
+
# - `:default` - Default filter value (default: `nil`).
|
117
|
+
# - `:multiple` - Allows multiple values (default: `false`).
|
118
|
+
# - `:allow_nil` - Whether to apply the filter when the value is `nil` (default: `false`).
|
119
|
+
# - `:allow_blank` - Whether to apply the filter when the value is blank (default: `false`).
|
120
|
+
#
|
121
|
+
# Example:
|
122
|
+
#
|
123
|
+
# filter(:id, :integer, header: "Identifier")
|
124
|
+
# filter(:created_at, :date, range: true, default: proc { 1.month.ago.to_date..Date.today })
|
125
|
+
#
|
126
|
+
# # Localization
|
127
|
+
#
|
128
|
+
# Filter labels can be localized or specified via the `:header` option:
|
129
|
+
#
|
130
|
+
# filter(:created_at, :date, header: "Creation date")
|
131
|
+
# filter(:created_at, :date, header: proc { I18n.t("creation_date") })
|
4
132
|
module Filters
|
5
|
-
|
6
133
|
require "datagrid/filters/base_filter"
|
7
134
|
require "datagrid/filters/enum_filter"
|
8
135
|
require "datagrid/filters/extended_boolean_filter"
|
@@ -11,51 +138,47 @@ module Datagrid
|
|
11
138
|
require "datagrid/filters/date_time_filter"
|
12
139
|
require "datagrid/filters/default_filter"
|
13
140
|
require "datagrid/filters/integer_filter"
|
14
|
-
require "datagrid/filters/composite_filters"
|
15
141
|
require "datagrid/filters/string_filter"
|
16
142
|
require "datagrid/filters/float_filter"
|
17
143
|
require "datagrid/filters/dynamic_filter"
|
18
144
|
|
145
|
+
# @!visibility private
|
19
146
|
FILTER_TYPES = {
|
20
147
|
date: Filters::DateFilter,
|
21
148
|
datetime: Filters::DateTimeFilter,
|
22
149
|
string: Filters::StringFilter,
|
23
150
|
default: Filters::DefaultFilter,
|
24
|
-
xboolean: Filters::ExtendedBooleanFilter
|
25
|
-
boolean: Filters::BooleanFilter
|
151
|
+
xboolean: Filters::ExtendedBooleanFilter,
|
152
|
+
boolean: Filters::BooleanFilter,
|
26
153
|
integer: Filters::IntegerFilter,
|
27
154
|
enum: Filters::EnumFilter,
|
28
155
|
float: Filters::FloatFilter,
|
29
|
-
dynamic: Filters::DynamicFilter
|
30
|
-
}
|
31
|
-
|
32
|
-
DEFAULT_FILTER_BLOCK = Object.new
|
156
|
+
dynamic: Filters::DynamicFilter,
|
157
|
+
}.freeze
|
33
158
|
|
34
159
|
# @!visibility private
|
35
|
-
|
36
|
-
base.extend ClassMethods
|
37
|
-
base.class_eval do
|
160
|
+
DEFAULT_FILTER_BLOCK = Object.new
|
38
161
|
|
39
|
-
|
40
|
-
include Datagrid::Filters::CompositeFilters
|
41
|
-
class_attribute :filters_array
|
42
|
-
self.filters_array = []
|
162
|
+
extend ActiveSupport::Concern
|
43
163
|
|
44
|
-
|
45
|
-
|
164
|
+
# @!visibility private
|
165
|
+
included do
|
166
|
+
include Datagrid::Core
|
167
|
+
class_attribute :filters_array, default: []
|
46
168
|
end
|
47
169
|
|
170
|
+
# Grid class methods related to filters
|
48
171
|
module ClassMethods
|
49
|
-
|
50
|
-
# Returns filter definition object by name
|
172
|
+
# @return [Datagrid::Filters::BaseFilter, nil] filter definition object by name
|
51
173
|
def filter_by_name(attribute)
|
52
174
|
if attribute.is_a?(Datagrid::Filters::BaseFilter)
|
53
175
|
unless ancestors.include?(attribute.grid_class)
|
54
|
-
raise "#{attribute.grid_class}##{attribute.name} filter doen't belong to #{self.class}"
|
176
|
+
raise ArgumentError, "#{attribute.grid_class}##{attribute.name} filter doen't belong to #{self.class}"
|
55
177
|
end
|
178
|
+
|
56
179
|
return attribute
|
57
180
|
end
|
58
|
-
|
181
|
+
filters.find do |filter|
|
59
182
|
filter.name == attribute.to_sym
|
60
183
|
end
|
61
184
|
end
|
@@ -64,18 +187,20 @@ module Datagrid
|
|
64
187
|
# This method automatically generates <tt>attr_accessor</tt> for filter name
|
65
188
|
# and adds it to the list of datagrid attributes.
|
66
189
|
#
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
190
|
+
# @param [Symbol] name filter name
|
191
|
+
# @param [Symbol] type filter type that defines type case and GUI representation of a filter
|
192
|
+
# @param [Hash] options hash of options
|
193
|
+
# @param [Proc] block proc to apply the filter
|
194
|
+
# @return [Datagrid::Filters::BaseFilter] Filter definition object
|
195
|
+
# @see https://github.com/bogdan/datagrid/wiki/Filters
|
73
196
|
#
|
74
197
|
# Available options:
|
75
198
|
#
|
76
199
|
# * <tt>:header</tt> - determines the header of the filter
|
77
|
-
# * <tt>:default</tt> - the default filter value.
|
78
|
-
#
|
200
|
+
# * <tt>:default</tt> - the default filter value.
|
201
|
+
# Can be a <tt>Proc</tt> in case default should be recalculated.
|
202
|
+
# * <tt>:range</tt> - if true, filter can accept two values that are treated
|
203
|
+
# as a range that will be used for filtering.
|
79
204
|
# Not all of the filter types support this option. Here are the list of types that do:
|
80
205
|
# <tt>:integer</tt>, <tt>:float</tt>, <tt>:date</tt>, <tt>:datetime</tt>, <tt>:string</tt>
|
81
206
|
# * <tt>:multiple</tt> - if true multiple values can be assigned to this filter.
|
@@ -84,9 +209,9 @@ module Datagrid
|
|
84
209
|
# * <tt>:allow_nil</tt> - determines if the value can be nil
|
85
210
|
# * <tt>:allow_blank</tt> - determines if the value can be blank
|
86
211
|
# * <tt>:before</tt> - determines the position of this filter,
|
87
|
-
# by adding it before the filter passed here (when using
|
212
|
+
# by adding it before the filter passed here (when using datagrid_form_with helper)
|
88
213
|
# * <tt>:after</tt> - determines the position of this filter,
|
89
|
-
# by adding it after the filter passed here (when using
|
214
|
+
# by adding it after the filter passed here (when using datagrid_form_with helper)
|
90
215
|
# * <tt>:dummy</tt> - if true, this filter will not be applied automatically
|
91
216
|
# and will be just displayed in form. In case you may want to apply it manually.
|
92
217
|
# * <tt>:if</tt> - specify the condition when the filter can be dislayed and used.
|
@@ -96,29 +221,31 @@ module Datagrid
|
|
96
221
|
# * <tt>:input_options</tt> - options passed when rendering html input tag attributes.
|
97
222
|
# Use <tt>input_options.type</tt> to control input type including <tt>textarea</tt>.
|
98
223
|
# * <tt>:label_options</tt> - options passed when rendering html label tag attributes
|
99
|
-
#
|
100
|
-
# See: https://github.com/bogdan/datagrid/wiki/Filters for examples
|
101
224
|
def filter(name, type = :default, **options, &block)
|
102
225
|
klass = type.is_a?(Class) ? type : FILTER_TYPES[type]
|
103
226
|
raise ConfigurationError, "filter class #{type.inspect} not found" unless klass
|
104
227
|
|
105
228
|
position = Datagrid::Utils.extract_position_from_options(filters_array, options)
|
106
|
-
filter = klass.new(self, name, options, &block)
|
229
|
+
filter = klass.new(self, name, **options, &block)
|
107
230
|
filters_array.insert(position, filter)
|
108
231
|
|
109
232
|
datagrid_attribute(name) do |value|
|
110
233
|
filter.parse_values(value)
|
111
234
|
end
|
235
|
+
filter
|
112
236
|
end
|
113
237
|
|
238
|
+
# @!visibility private
|
114
239
|
def default_filter
|
115
240
|
DEFAULT_FILTER_BLOCK
|
116
241
|
end
|
117
242
|
|
243
|
+
# @!visibility private
|
118
244
|
def inspect
|
119
245
|
"#{super}(#{filters_inspection})"
|
120
246
|
end
|
121
247
|
|
248
|
+
# @return [Array<Datagrid::Filters::BaseFilter>] all defined filters
|
122
249
|
def filters
|
123
250
|
filters_array
|
124
251
|
end
|
@@ -126,106 +253,107 @@ module Datagrid
|
|
126
253
|
protected
|
127
254
|
|
128
255
|
def inherited(child_class)
|
129
|
-
super
|
130
|
-
child_class.filters_array =
|
256
|
+
super
|
257
|
+
child_class.filters_array = filters_array.clone
|
131
258
|
end
|
132
259
|
|
133
260
|
def filters_inspection
|
134
261
|
return "no filters" if filters.empty?
|
262
|
+
|
135
263
|
filters.map do |filter|
|
136
264
|
"#{filter.name}: #{filter.type}"
|
137
265
|
end.join(", ")
|
138
266
|
end
|
139
267
|
end
|
140
268
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
self.
|
147
|
-
self[filter.name] = filter.default(self)
|
148
|
-
end
|
149
|
-
super(*args, &block)
|
269
|
+
# @!visibility private
|
270
|
+
def initialize(...)
|
271
|
+
self.filters_array = self.class.filters_array.clone
|
272
|
+
filters_array.each do |filter|
|
273
|
+
value = filter.default(self)
|
274
|
+
self[filter.name] = value unless value.nil?
|
150
275
|
end
|
276
|
+
super
|
277
|
+
end
|
151
278
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
279
|
+
# @!visibility private
|
280
|
+
def assets
|
281
|
+
apply_filters(super, filters)
|
282
|
+
end
|
156
283
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
284
|
+
# @return [Object] filter value for given filter definition
|
285
|
+
def filter_value(filter)
|
286
|
+
self[filter.name]
|
287
|
+
end
|
161
288
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
end
|
289
|
+
# @return [String] string representation of filter value
|
290
|
+
def filter_value_as_string(name)
|
291
|
+
filter = filter_by_name(name)
|
292
|
+
value = filter_value(filter)
|
293
|
+
if value.is_a?(Array)
|
294
|
+
value.map { |v| filter.format(v) }.join(filter.separator)
|
295
|
+
else
|
296
|
+
filter.format(value)
|
171
297
|
end
|
298
|
+
end
|
172
299
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
300
|
+
# @return [Datagrid::Filters::BaseFilter, nil] filter object with the given name
|
301
|
+
def filter_by_name(name)
|
302
|
+
self.class.filter_by_name(name)
|
303
|
+
end
|
177
304
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
end
|
305
|
+
# @return [Array<Object>] assets filtered only by specified filters
|
306
|
+
def filter_by(*filters)
|
307
|
+
apply_filters(scope, filters.map { |f| filter_by_name(f) })
|
308
|
+
end
|
183
309
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
310
|
+
# @return [Array] the select options for the filter
|
311
|
+
# @raise [ArgumentError] if the filter doesn't support select options
|
312
|
+
def select_options(filter)
|
313
|
+
find_select_filter(filter).select(self)
|
314
|
+
end
|
189
315
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
316
|
+
# @return [void] sets all options as selected for a filter that has options
|
317
|
+
def select_all(filter)
|
318
|
+
filter = find_select_filter(filter)
|
319
|
+
self[filter.name] = select_values(filter)
|
320
|
+
end
|
195
321
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
322
|
+
# @return [Array] all possible values for the filter
|
323
|
+
def select_values(filter)
|
324
|
+
find_select_filter(filter).select_values(self)
|
325
|
+
end
|
200
326
|
|
201
|
-
|
202
|
-
|
327
|
+
# @return [Array<Datagrid::Filters::BaseFilter>] all currently enabled filters
|
328
|
+
def filters
|
329
|
+
self.class.filters.select do |filter|
|
330
|
+
filter.enabled?(self)
|
203
331
|
end
|
332
|
+
end
|
204
333
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
end
|
210
|
-
end
|
334
|
+
# @!visibility private
|
335
|
+
def default_filter
|
336
|
+
self.class.default_filter
|
337
|
+
end
|
211
338
|
|
212
|
-
|
339
|
+
protected
|
213
340
|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
341
|
+
def find_select_filter(filter)
|
342
|
+
filter = filter_by_name(filter)
|
343
|
+
unless filter.class.included_modules.include?(::Datagrid::Filters::SelectOptions)
|
344
|
+
type = FILTER_TYPES.invert[filter.class].inspect
|
345
|
+
raise(
|
346
|
+
::Datagrid::ArgumentError,
|
347
|
+
"#{self.class.name}##{filter.name} with type #{type} can not have select options",
|
348
|
+
)
|
221
349
|
end
|
350
|
+
filter
|
351
|
+
end
|
222
352
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
end
|
353
|
+
def apply_filters(current_scope, filters)
|
354
|
+
filters.inject(current_scope) do |result, filter|
|
355
|
+
filter.apply(self, result, filter_value(filter))
|
227
356
|
end
|
228
357
|
end
|
229
|
-
|
230
358
|
end
|
231
359
|
end
|