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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -7
  3. data/{Readme.markdown → README.md} +46 -29
  4. data/app/assets/stylesheets/datagrid.css +145 -0
  5. data/app/views/datagrid/_enum_checkboxes.html.erb +5 -3
  6. data/app/views/datagrid/_form.html.erb +4 -5
  7. data/app/views/datagrid/_head.html.erb +26 -3
  8. data/app/views/datagrid/_range_filter.html.erb +5 -3
  9. data/app/views/datagrid/_row.html.erb +12 -1
  10. data/app/views/datagrid/_table.html.erb +4 -4
  11. data/datagrid.gemspec +8 -8
  12. data/lib/datagrid/active_model.rb +9 -17
  13. data/lib/datagrid/base.rb +39 -0
  14. data/lib/datagrid/column_names_attribute.rb +12 -12
  15. data/lib/datagrid/columns/column.rb +155 -133
  16. data/lib/datagrid/columns.rb +495 -282
  17. data/lib/datagrid/configuration.rb +23 -10
  18. data/lib/datagrid/core.rb +184 -150
  19. data/lib/datagrid/deprecated_object.rb +20 -0
  20. data/lib/datagrid/drivers/abstract_driver.rb +13 -25
  21. data/lib/datagrid/drivers/active_record.rb +24 -26
  22. data/lib/datagrid/drivers/array.rb +26 -17
  23. data/lib/datagrid/drivers/mongo_mapper.rb +15 -14
  24. data/lib/datagrid/drivers/mongoid.rb +16 -18
  25. data/lib/datagrid/drivers/sequel.rb +14 -19
  26. data/lib/datagrid/drivers.rb +2 -1
  27. data/lib/datagrid/engine.rb +11 -3
  28. data/lib/datagrid/filters/base_filter.rb +166 -142
  29. data/lib/datagrid/filters/boolean_filter.rb +19 -5
  30. data/lib/datagrid/filters/date_filter.rb +33 -35
  31. data/lib/datagrid/filters/date_time_filter.rb +24 -16
  32. data/lib/datagrid/filters/default_filter.rb +9 -3
  33. data/lib/datagrid/filters/dynamic_filter.rb +151 -105
  34. data/lib/datagrid/filters/enum_filter.rb +43 -19
  35. data/lib/datagrid/filters/extended_boolean_filter.rb +39 -27
  36. data/lib/datagrid/filters/float_filter.rb +16 -5
  37. data/lib/datagrid/filters/integer_filter.rb +21 -10
  38. data/lib/datagrid/filters/ranged_filter.rb +66 -45
  39. data/lib/datagrid/filters/select_options.rb +58 -49
  40. data/lib/datagrid/filters/string_filter.rb +9 -4
  41. data/lib/datagrid/filters.rb +234 -106
  42. data/lib/datagrid/form_builder.rb +116 -128
  43. data/lib/datagrid/generators/scaffold.rb +185 -0
  44. data/lib/datagrid/generators/views.rb +20 -0
  45. data/lib/datagrid/helper.rb +397 -22
  46. data/lib/datagrid/ordering.rb +81 -87
  47. data/lib/datagrid/rspec.rb +8 -12
  48. data/lib/datagrid/utils.rb +42 -38
  49. data/lib/datagrid/version.rb +3 -1
  50. data/lib/datagrid.rb +18 -28
  51. data/templates/base.rb.erb +33 -7
  52. data/templates/grid.rb.erb +1 -1
  53. metadata +18 -19
  54. data/app/assets/stylesheets/datagrid.sass +0 -134
  55. data/lib/datagrid/filters/composite_filters.rb +0 -49
  56. data/lib/datagrid/renderer.rb +0 -157
  57. data/lib/datagrid/scaffold.rb +0 -129
  58. data/lib/tasks/datagrid_tasks.rake +0 -15
  59. data/templates/controller.rb.erb +0 -6
  60. data/templates/index.html.erb +0 -5
@@ -1,184 +1,208 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # An error raise when datagrid filter is defined incorrectly and
2
4
  # causes filtering chain to be broken
3
- class Datagrid::FilteringError < StandardError
5
+ module Datagrid
6
+ class FilteringError < StandardError
7
+ end
4
8
  end
5
9
 
6
10
  # @!visibility private
7
- class Datagrid::Filters::BaseFilter
11
+ module Datagrid
12
+ module Filters
13
+ class BaseFilter
14
+ attr_accessor :grid_class, :options, :block, :name
15
+
16
+ def initialize(grid_class, name, **options, &block)
17
+ self.grid_class = grid_class
18
+ self.name = name.to_sym
19
+ self.options = options
20
+ self.block = block
21
+ end
8
22
 
9
- class_attribute :input_helper_name, instance_writer: false
10
- attr_accessor :grid_class, :options, :block, :name
23
+ def parse(value)
24
+ raise NotImplementedError, "#parse(value) suppose to be overwritten"
25
+ end
11
26
 
12
- def initialize(grid_class, name, options = {}, &block)
13
- self.grid_class = grid_class
14
- self.name = name.to_sym
15
- self.options = options
16
- self.block = block || default_filter_block
17
- end
27
+ def default_input_options
28
+ { type: "text" }
29
+ end
18
30
 
19
- def parse(value)
20
- raise NotImplementedError, "#parse(value) suppose to be overwritten"
21
- end
31
+ def unapplicable_value?(value)
32
+ value.nil? ? !allow_nil? : value.blank? && !allow_blank?
33
+ end
22
34
 
23
- def unapplicable_value?(value)
24
- value.nil? ? !allow_nil? : value.blank? && !allow_blank?
25
- end
35
+ def apply(grid_object, scope, value)
36
+ return scope if unapplicable_value?(value)
26
37
 
27
- def apply(grid_object, scope, value)
28
- return scope if unapplicable_value?(value)
38
+ result = execute(value, scope, grid_object)
29
39
 
30
- result = execute(value, scope, grid_object)
40
+ return scope unless result
31
41
 
32
- return scope unless result
33
- if result == Datagrid::Filters::DEFAULT_FILTER_BLOCK
34
- result = default_filter(value, scope, grid_object)
35
- end
36
- unless grid_object.driver.match?(result)
37
- raise Datagrid::FilteringError, "Can not apply #{name.inspect} filter: result #{result.inspect} no longer match #{grid_object.driver.class}."
38
- end
42
+ result = default_filter(value, scope) if result == Datagrid::Filters::DEFAULT_FILTER_BLOCK
43
+ unless grid_object.driver.match?(result)
44
+ raise(
45
+ Datagrid::FilteringError,
46
+ "Filter #{name.inspect} unapplicable: result no longer match #{grid_object.driver.class}.",
47
+ )
48
+ end
39
49
 
40
- result
41
- end
50
+ result
51
+ end
42
52
 
43
- def parse_values(value)
44
- if multiple?
45
- return nil if value.nil?
46
- normalize_multiple_value(value).map do |v|
47
- parse(v)
53
+ def parse_values(value)
54
+ if multiple?
55
+ return nil if value.nil?
56
+
57
+ return normalize_multiple_value(value).map do |v|
58
+ parse(v)
59
+ end
60
+ end
61
+
62
+ case value
63
+ when Array
64
+ raise Datagrid::ArgumentError,
65
+ "#{grid_class}##{name} filter can not accept Array argument. Use :multiple option."
66
+ when Range
67
+ raise Datagrid::ArgumentError,
68
+ "#{grid_class}##{name} filter can not accept Range argument. Use :range option."
69
+ else
70
+ parse(value)
71
+ end
48
72
  end
49
- elsif value.is_a?(Array)
50
- raise Datagrid::ArgumentError, "#{grid_class}##{name} filter can not accept Array argument. Use :multiple option."
51
- else
52
- parse(value)
53
- end
54
- end
55
73
 
56
- def separator
57
- options[:multiple].is_a?(String) ? options[:multiple] : default_separator
58
- end
74
+ def separator
75
+ options[:multiple].is_a?(String) ? options[:multiple] : default_separator
76
+ end
59
77
 
60
- def header
61
- if header = options[:header]
62
- Datagrid::Utils.callable(header)
63
- else
64
- Datagrid::Utils.translate_from_namespace(:filters, grid_class, name)
65
- end
66
- end
78
+ def header
79
+ if (header = options[:header])
80
+ Datagrid::Utils.callable(header)
81
+ else
82
+ Datagrid::Utils.translate_from_namespace(:filters, grid_class, name)
83
+ end
84
+ end
67
85
 
68
- def default(object)
69
- default = self.options[:default]
70
- if default.is_a?(Symbol)
71
- object.send(default)
72
- elsif default.respond_to?(:call)
73
- Datagrid::Utils.apply_args(object, &default)
74
- else
75
- default
76
- end
77
- end
86
+ def default(object)
87
+ default = options[:default]
88
+ if default.is_a?(Symbol)
89
+ object.send(default)
90
+ elsif default.respond_to?(:call)
91
+ Datagrid::Utils.apply_args(object, &default)
92
+ else
93
+ default
94
+ end
95
+ end
78
96
 
79
- def multiple?
80
- self.options[:multiple]
81
- end
97
+ def multiple?
98
+ options[:multiple]
99
+ end
82
100
 
83
- def allow_nil?
84
- options.has_key?(:allow_nil) ? options[:allow_nil] : options[:allow_blank]
85
- end
101
+ def range?
102
+ false
103
+ end
86
104
 
87
- def allow_blank?
88
- options[:allow_blank]
89
- end
105
+ def allow_nil?
106
+ options.key?(:allow_nil) ? options[:allow_nil] : options[:allow_blank]
107
+ end
90
108
 
91
- def input_options
92
- options[:input_options] || {}
93
- end
109
+ def allow_blank?
110
+ options[:allow_blank]
111
+ end
94
112
 
95
- def label_options
96
- options[:label_options] || {}
97
- end
113
+ def input_options
114
+ options[:input_options] || {}
115
+ end
98
116
 
99
- def form_builder_helper_name
100
- self.class.form_builder_helper_name
101
- end
117
+ def label_options
118
+ options[:label_options] || {}
119
+ end
102
120
 
103
- def self.form_builder_helper_name
104
- :"datagrid_#{self.to_s.demodulize.underscore}"
105
- end
121
+ def form_builder_helper_name
122
+ self.class.form_builder_helper_name
123
+ end
106
124
 
107
- def default_filter_block
108
- filter = self
109
- lambda do |value, scope, grid|
110
- filter.default_filter(value, scope, grid)
111
- end
112
- end
125
+ def self.form_builder_helper_name
126
+ :"datagrid_#{to_s.demodulize.underscore}"
127
+ end
113
128
 
114
- def supports_range?
115
- self.class.ancestors.include?(::Datagrid::Filters::RangedFilter)
116
- end
129
+ def supports_range?
130
+ self.class.ancestors.include?(::Datagrid::Filters::RangedFilter)
131
+ end
117
132
 
118
- def format(value)
119
- value.nil? ? nil : value.to_s
120
- end
133
+ def format(value)
134
+ value&.to_s
135
+ end
121
136
 
122
- def dummy?
123
- options[:dummy]
124
- end
137
+ def dummy?
138
+ options[:dummy]
139
+ end
125
140
 
126
- def type
127
- Datagrid::Filters::FILTER_TYPES.each do |type, klass|
128
- if is_a?(klass)
129
- return type
141
+ def type
142
+ Datagrid::Filters::FILTER_TYPES.each do |type, klass|
143
+ return type if is_a?(klass)
144
+ end
145
+ raise "wtf is #{inspect}"
130
146
  end
131
- end
132
- raise "wtf is #{inspect}"
133
- end
134
147
 
135
- def enabled?(grid)
136
- ::Datagrid::Utils.process_availability(grid, options[:if], options[:unless])
137
- end
148
+ def enabled?(grid)
149
+ ::Datagrid::Utils.process_availability(grid, options[:if], options[:unless])
150
+ end
138
151
 
139
- protected
152
+ def enum_checkboxes?
153
+ false
154
+ end
140
155
 
141
- def default_filter_where(scope, value)
142
- driver.where(scope, name, value)
143
- end
156
+ def default_scope?
157
+ !block
158
+ end
144
159
 
145
- def execute(value, scope, grid_object)
146
- if block.arity == 1
147
- scope.instance_exec(value, &block)
148
- else
149
- Datagrid::Utils.apply_args(value, scope, grid_object, &block)
150
- end
151
- end
160
+ protected
152
161
 
153
- def normalize_multiple_value(value)
154
- case value
155
- when String
156
- value.split(separator)
157
- when Range
158
- [value.first, value.last]
159
- when Array
160
- value
161
- else
162
- Array.wrap(value)
163
- end
164
- end
162
+ def default_filter_where(scope, value)
163
+ driver.where(scope, name, value)
164
+ end
165
165
 
166
- def default_separator
167
- ','
168
- end
166
+ def execute(value, scope, grid_object)
167
+ if block&.arity == 1
168
+ scope.instance_exec(value, &block)
169
+ elsif block
170
+ Datagrid::Utils.apply_args(value, scope, grid_object, &block)
171
+ else
172
+ default_filter(value, scope)
173
+ end
174
+ end
169
175
 
170
- def driver
171
- grid_class.driver
172
- end
176
+ def normalize_multiple_value(value)
177
+ case value
178
+ when String
179
+ value.split(separator)
180
+ when Range
181
+ [value.begin, value.end]
182
+ when Array
183
+ value
184
+ else
185
+ Array.wrap(value)
186
+ end
187
+ end
173
188
 
174
- def default_filter(value, scope, grid)
175
- return nil if dummy?
176
- if !driver.has_column?(scope, name) && scope.respond_to?(name)
177
- scope.send(name, value)
178
- else
179
- default_filter_where(scope, value)
189
+ def default_separator
190
+ ","
191
+ end
192
+
193
+ def driver
194
+ grid_class.driver
195
+ end
196
+
197
+ def default_filter(value, scope)
198
+ return nil if dummy?
199
+
200
+ if !driver.scope_has_column?(scope, name) && scope.respond_to?(name, true)
201
+ scope.public_send(name, value)
202
+ else
203
+ default_filter_where(scope, value)
204
+ end
205
+ end
180
206
  end
181
207
  end
182
-
183
208
  end
184
-
@@ -1,9 +1,23 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "datagrid/utils"
2
- # @!visibility private
3
- class Datagrid::Filters::BooleanFilter < Datagrid::Filters::BaseFilter
4
4
 
5
- def parse(value)
6
- Datagrid::Utils.booleanize(value)
7
- end
5
+ module Datagrid
6
+ module Filters
7
+ class BooleanFilter < Datagrid::Filters::BaseFilter
8
+ # @!visibility private
9
+ def initialize(grid, name, **opts)
10
+ super
11
+ options[:default] ||= false
12
+ end
8
13
 
14
+ def default_input_options
15
+ { **super, type: "checkbox" }
16
+ end
17
+
18
+ def parse(value)
19
+ Datagrid::Utils.booleanize(value)
20
+ end
21
+ end
22
+ end
9
23
  end
@@ -1,40 +1,38 @@
1
- require "datagrid/filters/ranged_filter"
2
-
3
- class Datagrid::Filters::DateFilter < Datagrid::Filters::BaseFilter
4
-
5
- include Datagrid::Filters::RangedFilter
6
-
7
- def apply(grid_object, scope, value)
8
- if value.is_a?(Range)
9
- value = value.first.beginning_of_day..value.last.end_of_day
10
- end
11
- super(grid_object, scope, value)
12
- end
13
-
14
- def parse(value)
15
- Datagrid::Utils.parse_date(value)
16
- end
1
+ # frozen_string_literal: true
17
2
 
3
+ require "datagrid/filters/ranged_filter"
18
4
 
19
- def format(value)
20
- if formats.any? && value
21
- value.strftime(formats.first)
22
- else
23
- super
24
- end
25
- end
26
-
27
- def default_filter_where(scope, value)
28
- if driver.is_timestamp?(scope, name)
29
- value = Datagrid::Utils.format_date_as_timestamp(value)
5
+ module Datagrid
6
+ module Filters
7
+ class DateFilter < Datagrid::Filters::BaseFilter
8
+ include Datagrid::Filters::RangedFilter
9
+
10
+ def default_input_options
11
+ { **super, type: "date" }
12
+ end
13
+
14
+ def apply(grid_object, scope, value)
15
+ value = Datagrid::Utils.format_date_as_timestamp(value) if grid_object.driver.timestamp_column?(scope, name)
16
+ super
17
+ end
18
+
19
+ def parse(value)
20
+ Datagrid::Utils.parse_date(value)
21
+ end
22
+
23
+ def format(value)
24
+ if formats.any? && value
25
+ value.strftime(formats.first)
26
+ else
27
+ super
28
+ end
29
+ end
30
+
31
+ protected
32
+
33
+ def formats
34
+ Array(Datagrid.configuration.date_formats)
35
+ end
30
36
  end
31
- super(scope, value)
32
- end
33
-
34
- protected
35
-
36
- def formats
37
- Array(Datagrid.configuration.date_formats)
38
37
  end
39
38
  end
40
-
@@ -1,25 +1,33 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "datagrid/filters/ranged_filter"
2
4
 
3
- class Datagrid::Filters::DateTimeFilter < Datagrid::Filters::BaseFilter
5
+ module Datagrid
6
+ module Filters
7
+ class DateTimeFilter < Datagrid::Filters::BaseFilter
8
+ include Datagrid::Filters::RangedFilter
4
9
 
5
- include Datagrid::Filters::RangedFilter
10
+ def default_input_options
11
+ { **super, type: "datetime-local" }
12
+ end
6
13
 
7
- def parse(value)
8
- Datagrid::Utils.parse_datetime(value)
9
- end
14
+ def parse(value)
15
+ Datagrid::Utils.parse_datetime(value)
16
+ end
10
17
 
11
- def format(value)
12
- if formats.any? && value
13
- value.strftime(formats.first)
14
- else
15
- super
16
- end
17
- end
18
+ def format(value)
19
+ if formats.any? && value
20
+ value.strftime(formats.first)
21
+ else
22
+ super
23
+ end
24
+ end
18
25
 
19
- protected
26
+ protected
20
27
 
21
- def formats
22
- Array(Datagrid.configuration.datetime_formats)
28
+ def formats
29
+ Array(Datagrid.configuration.datetime_formats)
30
+ end
31
+ end
23
32
  end
24
33
  end
25
-
@@ -1,5 +1,11 @@
1
- class Datagrid::Filters::DefaultFilter < Datagrid::Filters::BaseFilter
2
- def parse(value)
3
- value
1
+ # frozen_string_literal: true
2
+
3
+ module Datagrid
4
+ module Filters
5
+ class DefaultFilter < Datagrid::Filters::BaseFilter
6
+ def parse(value)
7
+ value
8
+ end
9
+ end
4
10
  end
5
11
  end