datagrid 1.8.1 → 2.0.0.pre.alpha

Sign up to get free protection for your applications and to get access to all the features.
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