wice_grid 3.5.0 → 3.6.0.pre1

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 (79) hide show
  1. checksums.yaml +4 -4
  2. data/.inch.yml +3 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +181 -0
  5. data/.travis.yml +22 -0
  6. data/{CHANGELOG → CHANGELOG.md} +95 -31
  7. data/Gemfile +4 -1
  8. data/README.md +1517 -0
  9. data/Rakefile +51 -7
  10. data/{SAVED_QUERIES_HOWTO.rdoc → SAVED_QUERIES_HOWTO.md} +34 -31
  11. data/TODO.md +16 -0
  12. data/lib/generators/wice_grid/add_migration_for_serialized_queries_generator.rb +4 -6
  13. data/lib/generators/wice_grid/install_generator.rb +2 -5
  14. data/lib/generators/wice_grid/templates/create_wice_grid_serialized_queries.rb +1 -0
  15. data/lib/generators/wice_grid/templates/wice_grid_config.rb +29 -34
  16. data/lib/wice/active_record_column_wrapper.rb +36 -17
  17. data/lib/wice/columns.rb +53 -52
  18. data/lib/wice/columns/column_action.rb +11 -13
  19. data/lib/wice/columns/column_boolean.rb +9 -11
  20. data/lib/wice/columns/column_bootstrap_datepicker.rb +48 -0
  21. data/lib/wice/columns/column_custom_dropdown.rb +22 -23
  22. data/lib/wice/columns/column_float.rb +2 -6
  23. data/lib/wice/columns/column_html5_datepicker.rb +31 -0
  24. data/lib/wice/columns/column_integer.rb +9 -13
  25. data/lib/wice/columns/column_jquery_datepicker.rb +49 -0
  26. data/lib/wice/columns/column_processor_index.rb +18 -13
  27. data/lib/wice/columns/column_rails_date_helper.rb +41 -0
  28. data/lib/wice/columns/column_rails_datetime_helper.rb +40 -0
  29. data/lib/wice/columns/column_range.rb +7 -11
  30. data/lib/wice/columns/column_string.rb +24 -20
  31. data/lib/wice/columns/common_date_datetime_mixin.rb +20 -0
  32. data/lib/wice/columns/common_js_date_datetime_conditions_generator_mixin.rb +39 -0
  33. data/lib/wice/columns/common_js_date_datetime_mixin.rb +15 -0
  34. data/lib/wice/columns/{column_date.rb → common_rails_date_datetime_conditions_generator_mixin.rb} +4 -22
  35. data/lib/wice/columns/common_standard_helper_date_datetime_mixin.rb +22 -0
  36. data/lib/wice/grid_output_buffer.rb +19 -10
  37. data/lib/wice/grid_renderer.rb +146 -85
  38. data/lib/wice/helpers/bs_calendar_helpers.rb +6 -7
  39. data/lib/wice/helpers/js_calendar_helpers.rb +19 -17
  40. data/lib/wice/helpers/wice_grid_misc_view_helpers.rb +18 -18
  41. data/lib/wice/helpers/wice_grid_serialized_queries_view_helpers.rb +44 -49
  42. data/lib/wice/helpers/wice_grid_view_helpers.rb +131 -134
  43. data/lib/wice/kaminari_monkey_patching.rb +3 -1
  44. data/lib/wice/table_column_matrix.rb +23 -8
  45. data/lib/wice/wice_grid_controller.rb +12 -16
  46. data/lib/wice/wice_grid_core_ext.rb +12 -20
  47. data/lib/wice/wice_grid_misc.rb +131 -53
  48. data/lib/wice/wice_grid_serialized_queries_controller.rb +10 -11
  49. data/lib/wice/wice_grid_serialized_query.rb +4 -3
  50. data/lib/wice/wice_grid_spreadsheet.rb +19 -18
  51. data/lib/wice_grid.rb +144 -135
  52. data/spec/schema.rb +9 -0
  53. data/spec/spec_helper.rb +75 -0
  54. data/spec/support/active_record.rb +11 -0
  55. data/spec/support/wice_grid_test_config.rb +172 -0
  56. data/spec/wice/grid_output_buffer_spec.rb +41 -0
  57. data/spec/wice/table_column_matrix_spec.rb +38 -0
  58. data/spec/wice/wice_grid_misc_spec.rb +159 -0
  59. data/spec/wice/wice_grid_spreadsheet_spec.rb +14 -0
  60. data/test/readme.txt +1 -1
  61. data/vendor/assets/javascripts/wice_grid_init.js.coffee +14 -8
  62. data/vendor/assets/stylesheets/wice_grid.scss +84 -0
  63. data/wice_grid.gemspec +32 -16
  64. metadata +217 -25
  65. data/README.rdoc +0 -1325
  66. data/lib/generators/wice_grid/templates/wice_grid.scss +0 -140
  67. data/lib/wice/columns/column_datetime.rb +0 -171
  68. data/vendor/assets/images/icons/grid/arrow_down.gif +0 -0
  69. data/vendor/assets/images/icons/grid/arrow_up.gif +0 -0
  70. data/vendor/assets/images/icons/grid/calendar_view_month.png +0 -0
  71. data/vendor/assets/images/icons/grid/collapse.gif +0 -0
  72. data/vendor/assets/images/icons/grid/delete.png +0 -0
  73. data/vendor/assets/images/icons/grid/expand.gif +0 -0
  74. data/vendor/assets/images/icons/grid/page_white_excel.png +0 -0
  75. data/vendor/assets/images/icons/grid/page_white_find.png +0 -0
  76. data/vendor/assets/images/icons/grid/table.png +0 -0
  77. data/vendor/assets/images/icons/grid/table_refresh.png +0 -0
  78. data/vendor/assets/images/icons/grid/tick_all.png +0 -0
  79. data/vendor/assets/images/icons/grid/untick_all.png +0 -0
@@ -0,0 +1,39 @@
1
+ # encoding: utf-8
2
+ module Wice
3
+ module Columns #:nodoc:
4
+ module CommonJsDateDatetimeConditionsGeneratorMixin #:nodoc:
5
+
6
+ def generate_conditions(table_alias, opts) #:nodoc:
7
+
8
+ datetime = @column_type == :datetime || @column_type == :timestamp
9
+
10
+ conditions = [[]]
11
+ if opts[:fr]
12
+ conditions[0] << " #{@column_wrapper.alias_or_table_name(table_alias)}.#{@column_wrapper.name} >= ? "
13
+ date = opts[:fr].to_date
14
+ if datetime
15
+ date = date.to_datetime
16
+ end
17
+ conditions << date
18
+ end
19
+
20
+ if opts[:to]
21
+ op = '<='
22
+ date = opts[:to].to_date
23
+ if datetime
24
+ date = (date + 1).to_datetime
25
+ op = '<'
26
+ end
27
+ conditions[0] << " #{@column_wrapper.alias_or_table_name(table_alias)}.#{@column_wrapper.name} #{op} ? "
28
+ conditions << date
29
+ end
30
+
31
+ return false if conditions.size == 1
32
+
33
+ conditions[0] = conditions[0].join(' and ')
34
+ conditions
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+ module Wice
3
+ module Columns #:nodoc:
4
+ module CommonJsDateDatetimeMixin #:nodoc:
5
+
6
+ def prepare #:nodoc:
7
+ query, _, @name1, @dom_id = form_parameter_name_id_and_query(fr: '')
8
+ query2, _, @name2, @dom_id2 = form_parameter_name_id_and_query(to: '')
9
+
10
+ @queris_ids = [[query, @dom_id], [query2, @dom_id2]]
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -1,24 +1,7 @@
1
+ # encoding: utf-8
1
2
  module Wice
2
-
3
3
  module Columns #:nodoc:
4
-
5
- class ViewColumnDate < ViewColumnDatetime #:nodoc:
6
-
7
- def chunk_names
8
- %w(year month day)
9
- end
10
-
11
- def render_standard_filter_internal(params) #:nodoc:
12
- '<div class="date-filter">' +
13
- select_date(params[:fr], {include_blank: true, prefix: @name1, id: @dom_id}) + '<br/>' +
14
- select_date(params[:to], {include_blank: true, prefix: @name2, id: @dom_id2}) +
15
- '</div>'
16
- end
17
-
18
- end
19
-
20
-
21
- class ConditionsGeneratorColumnDate < ConditionsGeneratorColumn #:nodoc:
4
+ module CommonJsDateDatetimeConditionsGeneratorMixin #:nodoc:
22
5
 
23
6
  def generate_conditions(table_alias, opts) #:nodoc:
24
7
  conditions = [[]]
@@ -37,8 +20,7 @@ module Wice
37
20
  conditions[0] = conditions[0].join(' and ')
38
21
  conditions
39
22
  end
40
- end
41
23
 
24
+ end
42
25
  end
43
-
44
- end
26
+ end
@@ -0,0 +1,22 @@
1
+ # encoding: utf-8
2
+ module Wice
3
+ module Columns #:nodoc:
4
+ module CommonStandardDateDatetimeMixin #:nodoc:
5
+
6
+ def prepare #:nodoc:
7
+ x = lambda do|sym|
8
+ chunk_names.map do|datetime_chunk_name|
9
+ triple = form_parameter_name_id_and_query(sym => { datetime_chunk_name => '' })
10
+ [triple[0], triple[3]]
11
+ end
12
+ end
13
+
14
+ @queris_ids = x.call(:fr) + x.call(:to)
15
+
16
+ _, _, @name1, _ = form_parameter_name_id_and_query(fr: '')
17
+ _, _, @name2, _ = form_parameter_name_id_and_query(to: '')
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -1,40 +1,49 @@
1
+ # encoding: utf-8
1
2
  module Wice
2
-
3
3
  class GridOutputBuffer < String #:nodoc:
4
4
 
5
+ # defines behavior for rendering nonexistent filters.
6
+ # If return_empty_strings_for_nonexistent_filters is true, a call to render a non existent filter will raise an exception
7
+ # If return_empty_strings_for_nonexistent_filters is false (CSV mode), no exception will be raised.
5
8
  attr_accessor :return_empty_strings_for_nonexistent_filters
6
9
 
10
+ # initializes a grid output buffer
7
11
  def initialize(*attrs)
8
12
  super(*attrs)
9
13
  @filters = HashWithIndifferentAccess.new
10
14
  end
11
15
 
16
+ # returns HTML code the grid
12
17
  def to_s
13
18
  super.html_safe
14
19
  end
15
20
 
21
+ # stores HTML code for a detached filter
16
22
  def add_filter(detach_with_id, filter_code)
17
- raise WiceGridException.new("Detached ID #{detach_with_id} is already used!") if @filters.has_key? detach_with_id
23
+ fail WiceGridException.new("Detached ID #{detach_with_id} is already used!") if @filters.key? detach_with_id
18
24
  @filters[detach_with_id] = filter_code
19
25
  end
20
26
 
21
- def filter_for detach_with_id
22
- unless @filters.has_key? detach_with_id
27
+ # returns HTML code for a detached filter
28
+ def filter_for(detach_with_id)
29
+ unless @filters.key? detach_with_id
23
30
  if @return_empty_strings_for_nonexistent_filters
24
31
  return ''
25
32
  else
26
- raise WiceGridException.new("No filter with Detached ID '#{detach_with_id}'!")
33
+ fail WiceGridException.new("No filter with Detached ID '#{detach_with_id}'!")
27
34
  end
28
35
  end
29
- if @filters[detach_with_id] == false
30
- raise WiceGridException.new("Filter with Detached ID '#{detach_with_id}' has already been requested once! There cannot be two instances of the same filter on one page")
36
+
37
+ unless @filters[detach_with_id]
38
+ fail WiceGridException.new("Filter with Detached ID '#{detach_with_id}' has already been requested once! There cannot be two instances of the same filter on one page")
31
39
  end
40
+
32
41
  res = @filters[detach_with_id]
33
42
  @filters[detach_with_id] = false
34
- return res
43
+ res
35
44
  end
36
45
 
46
+ # returns HTML code for a detached filter
37
47
  alias_method :[], :filter_for
38
-
39
48
  end
40
- end
49
+ end
@@ -1,32 +1,49 @@
1
+ # encoding: utf-8
1
2
  module Wice
2
- class GridRenderer
3
3
 
4
+ # Instance of `GridRenderer` is injected into the top level block of the `grid` helper.
5
+ # `g.column`, `g.action_column` are all examples of methods of `GridRenderer`
6
+ class GridRenderer
4
7
  include ActionView::Helpers::TagHelper
5
8
  include ActionView::Helpers::CaptureHelper
6
9
  include ActionView::Helpers::TextHelper
7
10
  include ActionView::Helpers::AssetTagHelper
8
11
  include ActionView::Helpers::JavaScriptHelper
9
12
 
10
- attr_reader :page_parameter_name
13
+ # a Proc object for the after_row block
11
14
  attr_reader :after_row_handler
15
+
16
+ # a Proc object for the before_row block
12
17
  attr_reader :before_row_handler
18
+
19
+ # a Proc object for the replace_row block
13
20
  attr_reader :replace_row_handler
21
+
22
+ # Configuration or a Proc object for the blank_slate block
14
23
  attr_reader :blank_slate_handler
24
+
25
+ # a Proc object which returns contents of the last row
15
26
  attr_reader :last_row_handler
27
+
28
+ # reference to the WiceGrid instance
16
29
  attr_reader :grid
30
+
31
+ # Contents of <caption></caption>
17
32
  attr_reader :kaption
18
33
 
19
- @@order_parameter_name = "order"
20
- @@order_direction_parameter_name = "order_direction"
21
- @@page_parameter_name = "page"
34
+ # HTTP parameter for the order field
35
+ ORDER_PARAMETER_NAME = 'order'
36
+
37
+ # HTTP parameter for the order direction (asc/desc)
38
+ ORDER_DIRECTION_PARAMETER_NAME = 'order_direction'
22
39
 
23
40
  def initialize(grid, view) #:nodoc:
24
- @grid = grid
25
- @grid.renderer = self
26
- @columns = []
27
- @columns_table = {}
41
+ @grid = grid
42
+ @grid.renderer = self
43
+ @columns = []
44
+ @columns_table = {}
28
45
  @action_column_present = false
29
- @view = view
46
+ @view = view
30
47
  end
31
48
 
32
49
  def config #:nodoc:
@@ -37,7 +54,6 @@ module Wice
37
54
  @view.controller
38
55
  end
39
56
 
40
-
41
57
  def add_column(vc) #:nodoc:
42
58
  @columns_table[vc.fully_qualified_attribute_name] = vc if vc.attribute
43
59
  @columns << vc
@@ -52,7 +68,7 @@ module Wice
52
68
  end
53
69
 
54
70
  def each_column_label(filter = nil) #:nodoc:
55
- filter_columns(filter).each{|col| yield col.name}
71
+ filter_columns(filter).each { |col| yield col.name }
56
72
  end
57
73
 
58
74
  def column_labels(filter = nil) #:nodoc:
@@ -60,12 +76,12 @@ module Wice
60
76
  end
61
77
 
62
78
  def each_column(filter = nil) #:nodoc:
63
- filter_columns(filter).each{|col| yield col}
79
+ filter_columns(filter).each { |col| yield col }
64
80
  end
65
81
 
66
82
  def each_column_aware_of_one_last_one(filter = nil) #:nodoc:
67
83
  cols = filter_columns(filter)
68
- cols[0..-2].each{|col| yield col, false}
84
+ cols[0..-2].each { |col| yield col, false }
69
85
  yield cols.last, true
70
86
  end
71
87
 
@@ -74,23 +90,24 @@ module Wice
74
90
  end
75
91
 
76
92
  def select_for(filter) #:nodoc:
77
- filter_columns(filter).select{|col| yield col}
93
+ filter_columns(filter).select { |col| yield col }
78
94
  end
79
95
 
80
96
  def find_one_for(filter) #:nodoc:
81
- filter_columns(filter).find{|col| yield col}
97
+ filter_columns(filter).find { |col| yield col }
82
98
  end
83
99
 
84
-
85
100
  def each_column_with_attribute #:nodoc:
86
- @columns.select(&:attribute).each{|col| yield col}
101
+ @columns.select(&:attribute).each { |col| yield col }
87
102
  end
88
103
 
89
104
  alias_method :each, :each_column
90
105
  include Enumerable
91
106
 
92
107
  def csv_export_icon #:nodoc:
93
- content_tag(:div, '',
108
+ content_tag(
109
+ :div,
110
+ content_tag(:i, '', class: 'fa fa-file-excel-o'),
94
111
  title: NlMessage['csv_export_tooltip'],
95
112
  class: 'clickable export-to-csv-button'
96
113
  )
@@ -99,7 +116,7 @@ module Wice
99
116
  def pagination_panel(number_of_columns, hide_csv_button) #:nodoc:
100
117
  panel = yield
101
118
 
102
- render_csv_button = @grid.export_to_csv_enabled && ! hide_csv_button
119
+ render_csv_button = @grid.export_to_csv_enabled && !hide_csv_button
103
120
 
104
121
  if panel.nil?
105
122
  if render_csv_button
@@ -116,9 +133,9 @@ module Wice
116
133
  end
117
134
  end
118
135
 
119
- # Takes one argument and adds the <caption></caption> tag to the table with the argument value as
120
- # the contents of <caption>.
121
- def caption kaption
136
+ # Takes one argument and adds the <caption></caption> tag to the table with the
137
+ # argument value as the contents of <caption>.
138
+ def caption(kaption)
122
139
  @kaption = kaption
123
140
  end
124
141
 
@@ -140,9 +157,8 @@ module Wice
140
157
  # +g.column+ definition. If the block returns +nil+ or +false+ no checkbox will be rendered.
141
158
 
142
159
  def action_column(opts = {}, &block)
143
-
144
160
  if @action_column_present
145
- raise Wice::WiceGridException.new('There can be only one action column in a WiceGrid')
161
+ fail Wice::WiceGridException.new('There can be only one action column in a WiceGrid')
146
162
  end
147
163
 
148
164
  options = {
@@ -150,7 +166,7 @@ module Wice
150
166
  html: {},
151
167
  select_all_buttons: true,
152
168
  object_property: :id,
153
- html_check_box: true,
169
+ html_check_box: true
154
170
  }
155
171
 
156
172
  opts.assert_valid_keys(options.keys)
@@ -182,7 +198,7 @@ module Wice
182
198
  # * <tt>:class</tt> - a shortcut for <tt>html: {class: 'css_class'}</tt>
183
199
  # * <tt>:attribute</tt> - name of a database column (which normally correspond to a model attribute with the
184
200
  # same name). By default the field is assumed to belong to the default table (see documentation for the
185
- # +initialize_grid+ method). Parameter <tt>:model</tt> allows to specify another table. Presence of
201
+ # +initialize_grid+ method). Parameter <tt>:assoc</tt> (association) allows to specify another joined table. Presence of
186
202
  # this parameter
187
203
  # * adds sorting capabilities by this field
188
204
  # * automatically creates a filter based on the type of the field unless parameter <tt>:filter</tt> is set to false.
@@ -202,7 +218,7 @@ module Wice
202
218
  # list of available filters.
203
219
  # * <tt>:ordering</tt> - Enable/disable ordering links in the column titles. The default is +true+
204
220
  # (i.e. if <tt>:attribute</tt> is defined, ordering is enabled)
205
- # * <tt>:model</tt> - Name of the model class to which <tt>:attribute</tt> belongs to if this is not the main table.
221
+ # * <tt>:assoc</tt> - Name of the model association. <tt>:attribute</tt> belongs to the table joined via this association.
206
222
  # * <tt>:table_alias</tt> - In case there are two joined assocations both referring to the same table, ActiveRecord
207
223
  # constructs a query where the second join provides an alias for the joined table. Setting <tt>:table_alias</tt>
208
224
  # to this alias will enable WiceGrid to order and filter by columns belonging to different associatiations but
@@ -258,9 +274,6 @@ module Wice
258
274
  # to false will prohibit the column from inclusion into the export.
259
275
  # * <tt>:in_html</tt> - When CSV export is enabled and it is needed to use a column for CSV export only and ignore it
260
276
  # in HTML, set this parameter to false.
261
- # * <tt>:helper_style</tt> - Changes the flavor of Date and DateTime filters. The values are:
262
- # * <tt>:standard</tt> - the default Rails Date/DateTime helper
263
- # * <tt>:calendar</tt> - a Javascript popup calendar control
264
277
  # * <tt>:negation</tt> - turn on/off the negation checkbox in string filters
265
278
  # * <tt>:auto_reload</tt> - a boolean value specifying if a change in a filter triggers reloading of the grid. Works with all
266
279
  # filter types including the JS calendar, the only exception is the standard Rails date/datetime filters.
@@ -282,44 +295,59 @@ module Wice
282
295
 
283
296
  def column(opts = {}, &block)
284
297
  options = {
285
- allow_multiple_selection: Defaults::ALLOW_MULTIPLE_SELECTION,
286
- ordering: true,
298
+ allow_multiple_selection: ConfigurationProvider.value_for(:ALLOW_MULTIPLE_SELECTION),
299
+ assoc: nil,
287
300
  attribute: nil,
288
- auto_reload: Defaults::AUTO_RELOAD,
301
+ auto_reload: ConfigurationProvider.value_for(:AUTO_RELOAD),
289
302
  boolean_filter_false_label: NlMessage['boolean_filter_false_label'],
290
303
  boolean_filter_true_label: NlMessage['boolean_filter_true_label'],
291
304
  class: nil,
292
- name: '',
293
305
  custom_filter: nil,
294
306
  detach_with_id: nil,
295
- filter_all_label: Defaults::CUSTOM_FILTER_ALL_LABEL,
296
- helper_style: Defaults::HELPER_STYLE,
297
- in_csv: true,
298
- in_html: true,
299
- model: nil,
300
- negation: Defaults::NEGATION_IN_STRING_FILTERS,
301
307
  filter: true,
308
+ filter_all_label: ConfigurationProvider.value_for(:CUSTOM_FILTER_ALL_LABEL),
302
309
  filter_type: nil,
303
- table_alias: nil,
304
- html: {}
310
+ html: {},
311
+ in_csv: true,
312
+ in_html: true,
313
+ model: nil, # will throw an exception with instructions
314
+ name: '',
315
+ negation: ConfigurationProvider.value_for(:NEGATION_IN_STRING_FILTERS),
316
+ ordering: true,
317
+ table_alias: nil
305
318
  }
306
319
 
307
320
  opts.assert_valid_keys(options.keys)
308
321
  options.merge!(opts)
309
322
 
310
- unless options[:model].nil?
311
- options[:model] = options[:model].constantize if options[:model].is_a? String
312
- raise WiceGridArgumentError.new("Option :model can be either a class or a string instance") unless options[:model].is_a? Class
323
+ assocs = nil
324
+
325
+ if options[:model]
326
+ fail WiceGridArgumentError.new('Instead of specifying a model of a joined table please use assoc: :name_of_association')
327
+ end
328
+
329
+ unless options[:assoc].nil?
330
+
331
+ unless options[:assoc].is_a?(Symbol) ||
332
+ (options[:assoc].is_a?(Array) && ! options[:assoc].empty? && options[:assoc].all?{ |assoc| assoc.is_a?(Symbol)})
333
+
334
+ fail WiceGridArgumentError.new('Option :assoc can only be a symbol or an array of symbols')
335
+ end
336
+
337
+ assocs = options[:assoc].is_a?(Symbol) ? [options[:assoc]] : options[:assoc]
338
+
339
+ options[:model] = get_model_from_associations(@grid.klass, assocs)
313
340
  end
314
341
 
315
342
  if options[:attribute].nil? && options[:model]
316
- raise WiceGridArgumentError.new("Option :model is only used together with :attribute")
343
+ fail WiceGridArgumentError.new('Option :assoc is only used together with :attribute')
317
344
  end
318
345
 
319
346
  if options[:attribute] && options[:attribute].index('.')
320
- raise WiceGridArgumentError.new("Invalid attribute name #{options[:attribute]}. An attribute name must not contain a table name!")
347
+ fail WiceGridArgumentError.new("Invalid attribute name #{options[:attribute]}. An attribute name must not contain a table name!")
321
348
  end
322
349
 
350
+
323
351
  if options[:class]
324
352
  options[:html] ||= {}
325
353
  Wice::WgHash.add_or_append_class_value!(options[:html], options[:class])
@@ -327,29 +355,41 @@ module Wice
327
355
  end
328
356
 
329
357
  if block.nil?
330
- if ! options[:attribute].blank?
331
- block = lambda{|obj| obj.send(options[:attribute])}
358
+ if !options[:attribute].blank?
359
+ if assocs.nil?
360
+ block = ->(obj) { obj.send(options[:attribute]) }
361
+ else
362
+ messages = assocs + [ options[:attribute] ]
363
+ block = ->(obj) { obj.deep_send(*messages) }
364
+ end
332
365
  else
333
- raise WiceGridArgumentError.new(
334
- "Missing column block without attribute defined. You can only omit the block if attribute is present.")
366
+ fail WiceGridArgumentError.new(
367
+ 'Missing column block without attribute defined. You can only omit the block if attribute is present.')
335
368
  end
336
369
  end
337
370
 
338
371
  klass = Columns::ViewColumn
339
372
  if options[:attribute] &&
340
- col_type_and_table_name = @grid.declare_column(options[:attribute], options[:model],
341
- options[:custom_filter], options[:table_alias], options[:filter_type])
342
-
373
+ col_type_and_table_name = @grid.declare_column(
374
+ column_name: options[:attribute],
375
+ model: options[:model],
376
+ custom_filter_active: options[:custom_filter],
377
+ table_alias: options[:table_alias],
378
+ filter_type: options[:filter_type],
379
+ assocs: assocs
380
+ )
381
+
382
+ # [ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter::Column, String, Boolean]
343
383
  db_column, table_name, main_table = col_type_and_table_name
344
384
  col_type = db_column.type
345
385
 
346
386
  if options[:custom_filter]
347
387
 
348
388
  custom_filter = if options[:custom_filter] == :auto
349
- lambda{ @grid.distinct_values_for_column(db_column) } # Thank God Ruby has higher order functions!!!
389
+ -> { @grid.distinct_values_for_column(db_column) } # Thank God Ruby has higher order functions!!!
350
390
 
351
391
  elsif options[:custom_filter].class == Symbol
352
- lambda{ @grid.distinct_values_for_column_in_resultset([options[:custom_filter]])}
392
+ -> { @grid.distinct_values_for_column_in_resultset([options[:custom_filter]]) }
353
393
 
354
394
  elsif options[:custom_filter].class == Hash
355
395
  options[:custom_filter].keys
@@ -360,19 +400,19 @@ module Wice
360
400
  if options[:custom_filter].empty?
361
401
  []
362
402
  elsif Wice::WgEnumerable.all_items_are_of_class(options[:custom_filter], Symbol)
363
- lambda{ @grid.distinct_values_for_column_in_resultset(options[:custom_filter]) }
403
+ -> { @grid.distinct_values_for_column_in_resultset(options[:custom_filter]) }
364
404
 
365
405
  elsif Wice::WgEnumerable.all_items_are_of_class(options[:custom_filter], String) || WgEnumerable.all_items_are_of_class(options[:custom_filter], Numeric)
366
- options[:custom_filter].map{|i| [i,i]}
406
+ options[:custom_filter].map { |i| [i, i] }
367
407
 
368
408
  elsif Wice::WgEnumerable.all_items_are_of_class(options[:custom_filter], Array)
369
409
  options[:custom_filter]
370
410
  else
371
- raise WiceGridArgumentError.new(
372
- ':custom_filter can equal :auto, an array of string and/or numbers (direct values for the dropdown), ' +
373
- 'a homogeneous array of symbols (a sequence of methods to send to AR objects in the result set to ' +
374
- 'retrieve unique values for the dropdown), a Symbol (a shortcut for a one member array of symbols), ' +
375
- 'a hash where keys are labels and values are values for the dropdown option, or an array of two-item arrays, ' +
411
+ fail WiceGridArgumentError.new(
412
+ ':custom_filter can equal :auto, an array of string and/or numbers (direct values for the dropdown), ' \
413
+ 'a homogeneous array of symbols (a sequence of methods to send to AR objects in the result set to ' \
414
+ 'retrieve unique values for the dropdown), a Symbol (a shortcut for a one member array of symbols), ' \
415
+ 'a hash where keys are labels and values are values for the dropdown option, or an array of two-item arrays, ' \
376
416
  'each of which contains the label (first element) and the value (second element) for a dropdown option'
377
417
  )
378
418
  end
@@ -382,6 +422,18 @@ module Wice
382
422
  elsif options[:filter_type]
383
423
  klass = Columns.get_view_column_processor(options[:filter_type])
384
424
  else
425
+
426
+ col_type = case col_type
427
+ when :date
428
+ Wice::Defaults::DEFAULT_FILTER_FOR_DATE
429
+ when :datetime
430
+ Wice::Defaults::DEFAULT_FILTER_FOR_DATETIME
431
+ when :timestamp
432
+ Wice::Defaults::DEFAULT_FILTER_FOR_DATETIME
433
+ else
434
+ col_type
435
+ end
436
+
385
437
  klass = Columns.get_view_column_processor(col_type)
386
438
  end # custom_filter
387
439
 
@@ -391,14 +443,30 @@ module Wice
391
443
 
392
444
  vc.negation = options[:negation] if vc.respond_to? :negation=
393
445
 
394
- vc.filter_all_label = options[:filter_all_label] if vc.kind_of?(Columns.get_view_column_processor(:custom))
395
- if vc.kind_of?(Columns.get_view_column_processor(:boolean))
446
+ vc.filter_all_label = options[:filter_all_label] if vc.is_a?(Columns.get_view_column_processor(:custom))
447
+ if vc.is_a?(Columns.get_view_column_processor(:boolean))
396
448
  vc.boolean_filter_true_label = options[:boolean_filter_true_label]
397
449
  vc.boolean_filter_false_label = options[:boolean_filter_false_label]
398
450
  end
399
451
  add_column(vc)
400
452
  end
401
453
 
454
+ def get_model_from_associations(model, assocs) # :nodoc:
455
+ if assocs.empty?
456
+ model
457
+ else
458
+ head = assocs[0]
459
+ tail = assocs[1..-1]
460
+
461
+ if reflection = model.reflect_on_association(head)
462
+ next_model = reflection.klass
463
+ get_model_from_associations(next_model, tail)
464
+ else
465
+ fail WiceGridArgumentError.new("Association #{head} not found in #{model}")
466
+ end
467
+ end
468
+ end
469
+
402
470
  # Optional method inside the +grid+ block, to which every ActiveRecord instance is injected, just like +column+.
403
471
  # Unlike +column+, it returns a hash which will be used as HTML attributes for the row with the given ActiveRecord instance.
404
472
  #
@@ -431,28 +499,28 @@ module Wice
431
499
  def last_row(&block)
432
500
  @last_row_handler = block
433
501
  end
502
+
434
503
  # The output of the block submitted to +blank_slate+ is rendered instead of the whole grid if no filters are active
435
504
  # and there are no records to render.
436
505
  # In addition to the block style two other variants are accepted:
437
506
  # * <tt>g.blank_slate "some text to be rendered"</tt>
438
507
  # * <tt>g.blank_slate partial: "partial_name"</tt>
439
508
  def blank_slate(opts = nil, &block)
440
- if (opts.is_a?(Hash) && opts.has_key?(:partial) && block.nil?) || (opts.is_a?(String) && block.nil?)
509
+ if (opts.is_a?(Hash) && opts.key?(:partial) && block.nil?) || (opts.is_a?(String) && block.nil?)
441
510
  @blank_slate_handler = opts
442
511
  elsif opts.nil? && block
443
512
  @blank_slate_handler = block
444
513
  else
445
- raise WiceGridArgumentError.new("blank_slate accepts only a string, a block, or template: 'path_to_template' ")
514
+ fail WiceGridArgumentError.new("blank_slate accepts only a string, a block, or template: 'path_to_template' ")
446
515
  end
447
516
  end
448
517
 
449
-
450
518
  def get_row_attributes(ar_object) #:nodoc:
451
519
  if @row_attributes_handler
452
520
  row_attributes = @row_attributes_handler.call(ar_object)
453
521
  row_attributes = {} if row_attributes.blank?
454
522
  unless row_attributes.is_a?(Hash)
455
- raise WiceGridArgumentError.new("row_attributes block must return a hash containing HTML attributes. The returned value is #{row_attributes.inspect}")
523
+ fail WiceGridArgumentError.new("row_attributes block must return a hash containing HTML attributes. The returned value is #{row_attributes.inspect}")
456
524
  end
457
525
  row_attributes
458
526
  else
@@ -460,13 +528,12 @@ module Wice
460
528
  end
461
529
  end
462
530
 
463
-
464
531
  def no_filter_needed? #:nodoc:
465
- not @columns.inject(false){|a,b| a || b.filter_shown? }
532
+ !@columns.inject(false) { |a, b| a || b.filter_shown? }
466
533
  end
467
534
 
468
535
  def no_filter_needed_in_main_table? #:nodoc:
469
- not @columns.inject(false){|a,b| a || b.filter_shown_in_main_table? }
536
+ !@columns.inject(false) { |a, b| a || b.filter_shown_in_main_table? }
470
537
  end
471
538
 
472
539
  def base_link_for_filter(controller, extra_parameters = {}) #:nodoc:
@@ -500,19 +567,17 @@ module Wice
500
567
  controller.url_for(new_params)
501
568
  end
502
569
 
503
-
504
570
  def column_link(column, direction, params, extra_parameters = {}) #:nodoc:
505
-
506
- column_attribute_name = if column.attribute.index('.') or column.main_table
571
+ column_attribute_name = if column.attribute.index('.') || column.main_table
507
572
  column.attribute
508
573
  else
509
574
  column.table_alias_or_table_name + '.' + column.attribute
510
575
  end
511
576
 
512
- query_params = {@grid.name => {
513
- @@order_parameter_name => column_attribute_name,
514
- @@order_direction_parameter_name => direction
515
- }}
577
+ query_params = { @grid.name => {
578
+ ORDER_PARAMETER_NAME => column_attribute_name,
579
+ ORDER_DIRECTION_PARAMETER_NAME => direction
580
+ } }
516
581
 
517
582
  cleaned_params = Wice::WgHash.deep_clone params
518
583
  cleaned_params.merge!(extra_parameters)
@@ -520,16 +585,13 @@ module Wice
520
585
  cleaned_params.delete(:controller)
521
586
  cleaned_params.delete(:action)
522
587
 
523
-
524
588
  query_params = Wice::WgHash.rec_merge(cleaned_params, query_params)
525
589
 
526
590
  '?' + query_params.to_query
527
591
  end
528
592
 
529
-
530
593
  protected
531
594
 
532
-
533
595
  def filter_columns(method_name = nil) #:nodoc:
534
596
  method_name ? @columns.select(&method_name) : @columns
535
597
  end
@@ -541,8 +603,7 @@ module Wice
541
603
  # /foo?grid=some_value --> /foo?grid=some_value
542
604
 
543
605
  empty_hash_rx = Regexp.new "([&?])#{Regexp.escape @grid.name}=([&?]|$)" # c.f., issue #140
544
- url.gsub(empty_hash_rx, '\1').gsub /\?+$/, ''
606
+ url.gsub(empty_hash_rx, '\1').gsub(/\?+$/, '')
545
607
  end
546
-
547
608
  end
548
609
  end