wice_grid_mongoid 0.5.6

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 (67) hide show
  1. data/.gitignore +8 -0
  2. data/CHANGELOG +409 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +1172 -0
  5. data/Rakefile +42 -0
  6. data/SAVED_QUERIES_HOWTO.rdoc +123 -0
  7. data/VERSION +1 -0
  8. data/generators/common_templates/icons/arrow_down.gif +0 -0
  9. data/generators/common_templates/icons/arrow_up.gif +0 -0
  10. data/generators/common_templates/icons/calendar_view_month.png +0 -0
  11. data/generators/common_templates/icons/delete.png +0 -0
  12. data/generators/common_templates/icons/expand.png +0 -0
  13. data/generators/common_templates/icons/page_white_excel.png +0 -0
  14. data/generators/common_templates/icons/page_white_find.png +0 -0
  15. data/generators/common_templates/icons/table.png +0 -0
  16. data/generators/common_templates/icons/table_refresh.png +0 -0
  17. data/generators/common_templates/icons/tick_all.png +0 -0
  18. data/generators/common_templates/icons/untick_all.png +0 -0
  19. data/generators/common_templates/initializers/wice_grid_config.rb +215 -0
  20. data/generators/common_templates/locales/wice_grid.yml +269 -0
  21. data/generators/common_templates/stylesheets/wice_grid.css +173 -0
  22. data/generators/wice_grid_assets_jquery/templates/USAGE +6 -0
  23. data/generators/wice_grid_assets_jquery/templates/javascripts/wice_grid_jquery.js +161 -0
  24. data/generators/wice_grid_assets_jquery/wice_grid_assets_jquery_generator.rb +35 -0
  25. data/generators/wice_grid_assets_prototype/USAGE +8 -0
  26. data/generators/wice_grid_assets_prototype/templates/javascripts/calendarview.js +1168 -0
  27. data/generators/wice_grid_assets_prototype/templates/javascripts/wice_grid_prototype.js +153 -0
  28. data/generators/wice_grid_assets_prototype/templates/stylesheets/calendarview.css +107 -0
  29. data/generators/wice_grid_assets_prototype/wice_grid_assets_prototype_generator.rb +37 -0
  30. data/init.rb +1 -0
  31. data/install.rb +1 -0
  32. data/lib/grid_output_buffer.rb +52 -0
  33. data/lib/grid_renderer.rb +531 -0
  34. data/lib/helpers/js_calendar_helpers.rb +188 -0
  35. data/lib/helpers/wice_grid_misc_view_helpers.rb +113 -0
  36. data/lib/helpers/wice_grid_serialized_queries_view_helpers.rb +82 -0
  37. data/lib/helpers/wice_grid_view_helpers.rb +781 -0
  38. data/lib/js_adaptors/jquery_adaptor.rb +145 -0
  39. data/lib/js_adaptors/js_adaptor.rb +12 -0
  40. data/lib/js_adaptors/prototype_adaptor.rb +168 -0
  41. data/lib/table_column_matrix.rb +51 -0
  42. data/lib/view_columns.rb +469 -0
  43. data/lib/views/create.rjs +13 -0
  44. data/lib/views/delete.rjs +12 -0
  45. data/lib/wice_grid.rb +809 -0
  46. data/lib/wice_grid_controller.rb +165 -0
  47. data/lib/wice_grid_core_ext.rb +179 -0
  48. data/lib/wice_grid_misc.rb +99 -0
  49. data/lib/wice_grid_serialized_queries_controller.rb +77 -0
  50. data/lib/wice_grid_serialized_query.rb +14 -0
  51. data/lib/wice_grid_spreadsheet.rb +33 -0
  52. data/tasks/wice_grid_tasks.rake +28 -0
  53. data/test/.gitignore +2 -0
  54. data/test/database.yml +21 -0
  55. data/test/schema.rb +33 -0
  56. data/test/test_helper.rb +89 -0
  57. data/test/views/projects_and_people_grid.html.erb +12 -0
  58. data/test/views/projects_and_people_grid_invalid.html.erb +12 -0
  59. data/test/views/simple_projects_grid.html.erb +9 -0
  60. data/test/wice_grid_core_ext_test.rb +183 -0
  61. data/test/wice_grid_functional_test.rb +68 -0
  62. data/test/wice_grid_misc_test.rb +41 -0
  63. data/test/wice_grid_test.rb +42 -0
  64. data/test/wice_grid_view_helper_test.rb +12 -0
  65. data/uninstall.rb +1 -0
  66. data/wice_grid_mongoid.gemspec +111 -0
  67. metadata +141 -0
@@ -0,0 +1,13 @@
1
+ if @notification_messages
2
+ page.replace_html(@notification_messages_dom_id, %!<div class="wice_grid_notice"> #{h @notification_messages}</div>!)
3
+ end
4
+
5
+ if @error_messages
6
+ page.replace_html(@notification_messages_dom_id, %!<div class="errorExplanation"> #{h @error_messages} </div>!)
7
+ else
8
+ page.replace(@query_list_dom_id, saved_queries_list(@grid_name, @saved_query, controller.extra))
9
+ page[@query_list_dom_id].visual_effect :highlight
10
+ page.replace_html(@grid_title_id, content_tag(:h3,@saved_query.name))
11
+ end
12
+
13
+ page[@notification_messages_dom_id].show
@@ -0,0 +1,12 @@
1
+ if @notification_messages
2
+ page.replace_html(@notification_messages_dom_id, %!<div class="wice_grid_notice"> #{h @notification_messages}</div>!)
3
+ end
4
+
5
+ if @error_messages
6
+ page.replace_html(@notification_messages_dom_id, %!<div class="errorExplanation"> #{h @error_messages} </div>!)
7
+ else
8
+ page.replace(@query_list_dom_id, saved_queries_list(@grid_name, @current, controller.extra))
9
+ page[@query_list_dom_id].visual_effect :highlight
10
+ end
11
+
12
+ page[@notification_messages_dom_id].show
data/lib/wice_grid.rb ADDED
@@ -0,0 +1,809 @@
1
+ # encoding: UTF-8
2
+ require 'will_paginate.rb'
3
+ require 'wice_grid_misc.rb'
4
+ require 'wice_grid_core_ext.rb'
5
+ require 'grid_renderer.rb'
6
+ require 'table_column_matrix.rb'
7
+ require 'helpers/wice_grid_view_helpers.rb'
8
+ require 'helpers/wice_grid_misc_view_helpers.rb'
9
+ require 'helpers/wice_grid_serialized_queries_view_helpers.rb'
10
+ require 'helpers/wice_grid_view_helpers.rb'
11
+ require 'helpers/js_calendar_helpers.rb'
12
+ require 'grid_output_buffer.rb'
13
+ require 'wice_grid_controller.rb'
14
+ require 'wice_grid_spreadsheet.rb'
15
+ require 'wice_grid_serialized_queries_controller.rb'
16
+ require 'js_adaptors/js_adaptor.rb'
17
+ require 'js_adaptors/jquery_adaptor.rb'
18
+ require 'js_adaptors/prototype_adaptor.rb'
19
+ require 'view_columns.rb'
20
+
21
+ ActionView::Base.class_eval { include Wice::GridViewHelper }
22
+ ActionController::Base.send(:include, Wice::Controller)
23
+ ActionController::Base.send(:helper_method, :wice_grid_custom_filter_params)
24
+
25
+ module Wice
26
+
27
+ class WiceGrid
28
+
29
+ attr_reader :klass, :name, :resultset, :custom_order, :query_store_model
30
+ attr_reader :ar_options, :status, :export_to_csv_enabled, :csv_file_name, :saved_query
31
+ attr_writer :renderer
32
+ attr_accessor :output_buffer, :view_helper_finished, :csv_tempfile
33
+
34
+ # core workflow methods START
35
+
36
+ def initialize(klass, controller, opts = {}) #:nodoc:
37
+ @controller = controller
38
+
39
+ # check for will_paginate
40
+ # raise WiceGridException.new("Plugin will_paginate not found! wice_grid requires will_paginate.")
41
+ unless klass.respond_to?(:paginate)
42
+ raise Wice::WiceGridException.new('will_paginate not found, WiceGrid cannot proceed. Please install gem mislav-will_paginate. ' +
43
+ 'You might need to add github.com as the gem source before you install the gem: ' +
44
+ 'gem sources -a http://gems.github.com')
45
+ end
46
+
47
+ unless klass.kind_of?(Class) && klass.ancestors.index(ActiveRecord::Base)
48
+ raise WiceGridArgumentError.new("ActiveRecord model class (second argument) must be a Class derived from ActiveRecord::Base")
49
+ end
50
+
51
+ Wice.deprecated_call(:after, :with_resultset, opts)
52
+
53
+ # validate :with_resultset & :with_paginated_resultset
54
+ [:with_resultset, :with_paginated_resultset].each do |callback_symbol|
55
+ unless [NilClass, Symbol, Proc].index(opts[callback_symbol].class)
56
+ raise WiceGridArgumentError.new(":#{callback_symbol} must be either a Proc or Symbol object")
57
+ end
58
+ end
59
+
60
+ opts[:order_direction].downcase! if opts[:order_direction].kind_of?(String)
61
+
62
+ # validate :order_direction
63
+ if opts[:order_direction] && ! (opts[:order_direction] == 'asc' ||
64
+ opts[:order_direction] == :asc ||
65
+ opts[:order_direction] == 'desc' ||
66
+ opts[:order_direction] == :desc)
67
+ raise WiceGridArgumentError.new(":order_direction must be either 'asc' or 'desc'.")
68
+ end
69
+
70
+ # options that are understood
71
+ @options = {
72
+ :conditions => nil,
73
+ :csv_file_name => nil,
74
+ :custom_order => {},
75
+ :enable_export_to_csv => Defaults::ENABLE_EXPORT_TO_CSV,
76
+ :group => nil,
77
+ :include => nil,
78
+ :joins => nil,
79
+ :name => Defaults::GRID_NAME,
80
+ :order => nil,
81
+ :order_direction => Defaults::ORDER_DIRECTION,
82
+ :page => 1,
83
+ :per_page => Defaults::PER_PAGE,
84
+ :saved_query => nil,
85
+ :select => nil,
86
+ :total_entries => nil,
87
+ :with_paginated_resultset => nil,
88
+ :with_resultset => nil
89
+ }
90
+
91
+ # validate parameters
92
+ opts.assert_valid_keys(@options.keys)
93
+
94
+ @options.merge!(opts)
95
+ @export_to_csv_enabled = @options[:enable_export_to_csv]
96
+ @csv_file_name = @options[:csv_file_name]
97
+
98
+ case @name = @options[:name]
99
+ when String
100
+ when Symbol
101
+ @name = @name.to_s
102
+ else
103
+ raise WiceGridArgumentError.new("name of the grid should be a string or a symbol")
104
+ end
105
+ raise WiceGridArgumentError.new("name of the grid can only contain alphanumeruc characters") unless @name =~ /^[a-zA-Z\d_]*$/
106
+
107
+ @klass = klass
108
+
109
+ @table_column_matrix = TableColumnMatrix.new
110
+ @table_column_matrix.default_model_class = @klass
111
+
112
+ @ar_options = {}
113
+ @status = HashWithIndifferentAccess.new
114
+
115
+ if @options[:order]
116
+ @options[:order] = @options[:order].to_s
117
+ @options[:order_direction] = @options[:order_direction].to_s
118
+
119
+ @status[:order_direction] = @options[:order_direction]
120
+ @status[:order] = @options[:order]
121
+
122
+ end
123
+ @status[:total_entries] = @options[:total_entries]
124
+ @status[:per_page] = @options[:per_page]
125
+ @status[:page] = @options[:page]
126
+ @status[:conditions] = @options[:conditions]
127
+ @status[:f] = @options[:f]
128
+
129
+ process_loading_query
130
+ process_params
131
+
132
+ @ar_options_formed = false
133
+
134
+ @method_scoping = @klass.send(:scoped_methods)[-1]
135
+ end
136
+
137
+ # A block executed from within the plugin to process records of the current page.
138
+ # The argument to the callback is the array of the records. See the README for more details.
139
+ def with_paginated_resultset(&callback)
140
+ @options[:with_paginated_resultset] = callback
141
+ end
142
+
143
+ # A block executed from within the plugin to process all records browsable through
144
+ # all pages with the current filters. The argument to
145
+ # the callback is a lambda object which returns the list of records when called. See the README for the explanation.
146
+ def with_resultset(&callback)
147
+ @options[:with_resultset] = callback
148
+ end
149
+
150
+ def process_loading_query #:nodoc:
151
+ @saved_query = nil
152
+ if params[name] && params[name][:q]
153
+ @saved_query = load_query(params[name][:q])
154
+ params[name].delete(:q)
155
+ elsif @options[:saved_query]
156
+ if @options[:saved_query].is_a? ActiveRecord::Base
157
+ @saved_query = @options[:saved_query]
158
+ else
159
+ @saved_query = load_query(@options[:saved_query])
160
+ end
161
+ else
162
+ return
163
+ end
164
+
165
+ unless @saved_query.nil?
166
+ params[name] = HashWithIndifferentAccess.new if params[name].blank?
167
+ [:f, :order, :order_direction].each do |key|
168
+ if @saved_query.query[key].blank?
169
+ params[name].delete(key)
170
+ else
171
+ params[name][key] = @saved_query.query[key]
172
+ end
173
+ end
174
+ end
175
+ end
176
+
177
+ def process_params #:nodoc:
178
+ if this_grid_params
179
+ @status.merge!(this_grid_params)
180
+ @status.delete(:export) unless self.export_to_csv_enabled
181
+ end
182
+ end
183
+
184
+ def declare_column(column_name, model_class, custom_filter_active, table_alias) #:nodoc:
185
+ if model_class # this is an included table
186
+ column = @table_column_matrix.get_column_by_model_class_and_column_name(model_class, column_name)
187
+ raise WiceGridArgumentError.new("Column '#{column_name}' is not found in table '#{model_class.table_name}'!") if column.nil?
188
+ main_table = false
189
+ table_name = model_class.table_name
190
+ else
191
+ column = @table_column_matrix.get_column_in_default_model_class_by_column_name(column_name)
192
+ if column.nil?
193
+ raise WiceGridArgumentError.new("Column '#{column_name}' is not found in table '#{@klass.table_name}'! " +
194
+ "If '#{column_name}' belongs to another table you should declare it in :include or :join when initialising " +
195
+ "the grid, and specify :model_class in column declaration.")
196
+ end
197
+ main_table = true
198
+ table_name = @table_column_matrix.default_model_class.table_name
199
+ end
200
+
201
+ if column
202
+ conditions, current_parameter_name = column.wg_initialize_request_parameters(@status[:f], main_table, table_alias, custom_filter_active)
203
+ if @status[:f] && conditions.blank?
204
+ @status[:f].delete(current_parameter_name)
205
+ end
206
+
207
+ @table_column_matrix.add_condition(column, conditions)
208
+ [column, table_name , main_table]
209
+ else
210
+ nil
211
+ end
212
+ end
213
+
214
+ def form_ar_options(opts = {}) #:nodoc:
215
+
216
+ return if @ar_options_formed
217
+ @ar_options_formed = true unless opts[:forget_generated_options]
218
+
219
+ # validate @status[:order_direction]
220
+ @status[:order_direction] = case @status[:order_direction]
221
+ when /desc/i
222
+ 'desc'
223
+ when /asc/i
224
+ 'asc'
225
+ else
226
+ ''
227
+ end
228
+
229
+ # conditions
230
+ if @table_column_matrix.generated_conditions.size == 0
231
+ @status.delete(:f)
232
+ end
233
+
234
+ @ar_options[:conditions] = klass.send(:merge_conditions, @status[:conditions], * @table_column_matrix.conditions )
235
+ # conditions processed
236
+
237
+ if (! opts[:skip_ordering]) && @status[:order]
238
+ @ar_options[:order] = add_custom_order_sql(complete_column_name(@status[:order]))
239
+
240
+ @ar_options[:order] += ' ' + @status[:order_direction]
241
+ end
242
+
243
+ if self.output_html?
244
+ @ar_options[:per_page] = if all_record_mode?
245
+ # reset the :pp value in all records mode
246
+ @status[:pp] = count_resultset_without_paging_without_user_filters
247
+ else
248
+ @status[:per_page]
249
+ end
250
+
251
+ @ar_options[:page] = @status[:page]
252
+ @ar_options[:total_entries] = @status[:total_entries] if @status[:total_entries]
253
+ end
254
+
255
+ @ar_options[:joins] = @options[:joins]
256
+ @ar_options[:include] = @options[:include]
257
+ @ar_options[:group] = @options[:group]
258
+ @ar_options[:select] = @options[:select]
259
+ end
260
+
261
+ def read #:nodoc:
262
+ form_ar_options
263
+ with_exclusive_scope do
264
+ @resultset = self.output_csv? ? @klass.find(:all, @ar_options) : @klass.paginate(@ar_options)
265
+ end
266
+ invoke_resultset_callbacks
267
+ end
268
+
269
+
270
+ # core workflow methods END
271
+
272
+ # Getters
273
+
274
+ def filter_params(view_column) #:nodoc:
275
+ column_name = view_column.attribute_name_fully_qualified_for_all_but_main_table_columns
276
+ if @status[:f] && @status[:f][column_name]
277
+ @status[:f][column_name]
278
+ else
279
+ {}
280
+ end
281
+ end
282
+
283
+ def resultset #:nodoc:
284
+ self.read unless @resultset # database querying is late!
285
+ @resultset
286
+ end
287
+
288
+ def each #:nodoc:
289
+ self.read unless @resultset # database querying is late!
290
+ @resultset.each do |r|
291
+ yield r
292
+ end
293
+ end
294
+
295
+ def ordered_by?(column) #:nodoc:
296
+ return nil if @status[:order].blank?
297
+ if column.main_table && ! offs = @status[:order].index('.')
298
+ @status[:order] == column.attribute_name
299
+ else
300
+ @status[:order] == column.table_alias_or_table_name + '.' + column.attribute_name
301
+ end
302
+ end
303
+
304
+ def ordered_by #:nodoc:
305
+ @status[:order]
306
+ end
307
+
308
+
309
+ def order_direction #:nodoc:
310
+ @status[:order_direction]
311
+ end
312
+
313
+ def filtering_on? #:nodoc:
314
+ not @status[:f].blank?
315
+ end
316
+
317
+ def filtered_by #:nodoc:
318
+ @status[:f].nil? ? [] : @status[:f].keys
319
+ end
320
+
321
+ def filtered_by?(view_column) #:nodoc:
322
+ @status[:f].nil? ? false : @status[:f].has_key?(view_column.attribute_name_fully_qualified_for_all_but_main_table_columns)
323
+ end
324
+
325
+ def get_state_as_parameter_value_pairs(including_saved_query_request = false) #:nodoc:
326
+ res = []
327
+ unless status[:f].blank?
328
+ status[:f].parameter_names_and_values([name, 'f']).collect do |param_name, value|
329
+ if value.is_a?(Array)
330
+ param_name_ar = param_name + '[]'
331
+ value.each do |v|
332
+ res << [param_name_ar, v]
333
+ end
334
+ else
335
+ res << [param_name, value]
336
+ end
337
+ end
338
+ end
339
+
340
+ if including_saved_query_request && @saved_query
341
+ res << ["#{name}[q]", @saved_query.id ]
342
+ end
343
+
344
+ [:order, :order_direction].select{|parameter|
345
+ status[parameter]
346
+ }.collect do |parameter|
347
+ res << ["#{name}[#{parameter}]", status[parameter] ]
348
+ end
349
+
350
+ res
351
+ end
352
+
353
+ def count #:nodoc:
354
+ form_ar_options(:skip_ordering => true, :forget_generated_options => true)
355
+ @klass.count(:conditions => @ar_options[:conditions], :joins => @ar_options[:joins], :include => @ar_options[:include], :group => @ar_options[:group])
356
+ end
357
+
358
+ alias_method :size, :count
359
+
360
+ def empty? #:nodoc:
361
+ self.count == 0
362
+ end
363
+
364
+ # with this variant we get even those values which do not appear in the resultset
365
+ def distinct_values_for_column(column) #:nodoc:
366
+ res = column.model_klass.find(:all, :select => "distinct #{column.name}", :order => "#{column.name} asc").collect{|ar|
367
+ ar[column.name]
368
+ }.reject{|e| e.blank?}.map{|i|[i,i]}
369
+ end
370
+
371
+
372
+ def distinct_values_for_column_in_resultset(messages) #:nodoc:
373
+ uniq_vals = Set.new
374
+
375
+ resultset_without_paging_without_user_filters.each do |ar|
376
+ v = ar.deep_send(*messages)
377
+ uniq_vals << v unless v.nil?
378
+ end
379
+ return uniq_vals.to_a.map{|i|
380
+ if i.is_a?(Array) && i.size == 2
381
+ i
382
+ elsif i.is_a?(Hash) && i.size == 1
383
+ i.to_a.flatten
384
+ else
385
+ [i,i]
386
+ end
387
+ }.sort{|a,b| a[0]<=>b[0]}
388
+ end
389
+
390
+ def output_csv? #:nodoc:
391
+ @status[:export] == 'csv'
392
+ end
393
+
394
+ def output_html? #:nodoc:
395
+ @status[:export].blank?
396
+ end
397
+
398
+ def all_record_mode? #:nodoc:
399
+ @status[:pp]
400
+ end
401
+
402
+ def dump_status #:nodoc:
403
+ " params: #{params[name].inspect}\n" +
404
+ " status: #{@status.inspect}\n" +
405
+ " ar_options #{@ar_options.inspect}\n"
406
+ end
407
+
408
+
409
+ def selected_records #:nodoc:
410
+ STDERR.puts "WiceGrid: Parameter :#{selected_records} is deprecated, use :#{all_pages_records} or :#{current_page_records} instead!"
411
+ all_pages_records
412
+ end
413
+
414
+ # Returns the list of objects browsable through all pages with the current filters.
415
+ # Should only be called after the +grid+ helper.
416
+ def all_pages_records
417
+ raise WiceGridException.new("all_pages_records can only be called only after the grid view helper") unless self.view_helper_finished
418
+ resultset_without_paging_with_user_filters
419
+ end
420
+
421
+ # Returns the list of objects displayed on current page. Should only be called after the +grid+ helper.
422
+ def current_page_records
423
+ raise WiceGridException.new("current_page_records can only be called only after the grid view helper") unless self.view_helper_finished
424
+ @resultset
425
+ end
426
+
427
+
428
+
429
+ protected
430
+
431
+ def invoke_resultset_callback(callback, argument) #:nodoc:
432
+ case callback
433
+ when Proc
434
+ callback.call(argument)
435
+ when Symbol
436
+ @controller.send(callback, argument)
437
+ end
438
+ end
439
+
440
+ def invoke_resultset_callbacks #:nodoc:
441
+ invoke_resultset_callback(@options[:with_paginated_resultset], @resultset)
442
+ invoke_resultset_callback(@options[:with_resultset], lambda{self.send(:resultset_without_paging_with_user_filters)})
443
+ end
444
+
445
+ def with_exclusive_scope #:nodoc:
446
+ if @method_scoping
447
+ @klass.send(:with_exclusive_scope, @method_scoping) do
448
+ yield
449
+ end
450
+ else
451
+ yield
452
+ end
453
+ end
454
+
455
+
456
+ def add_custom_order_sql(fully_qualified_column_name) #:nodoc:
457
+ custom_order = if @options[:custom_order].has_key?(fully_qualified_column_name)
458
+ @options[:custom_order][fully_qualified_column_name]
459
+ else
460
+ if view_column = @renderer[fully_qualified_column_name]
461
+ view_column.custom_order
462
+ else
463
+ nil
464
+ end
465
+ end
466
+
467
+ if custom_order.blank?
468
+ ActiveRecord::Base.connection.quote_table_name(fully_qualified_column_name.strip)
469
+ else
470
+ if custom_order.is_a? String
471
+ custom_order.gsub(/\?/, fully_qualified_column_name)
472
+ elsif custom_order.is_a? Proc
473
+ custom_order.call(fully_qualified_column_name)
474
+ else
475
+ raise WiceGridArgumentError.new("invalid custom order #{custom_order.inspect}")
476
+ end
477
+ end
478
+ end
479
+
480
+ def complete_column_name(col_name) #:nodoc:
481
+ if col_name.index('.') # already has a table name
482
+ col_name
483
+ else # add the default table
484
+ "#{@klass.table_name}.#{col_name}"
485
+ end
486
+ end
487
+
488
+ def params #:nodoc:
489
+ @controller.params
490
+ end
491
+
492
+ def this_grid_params #:nodoc:
493
+ params[name]
494
+ end
495
+
496
+
497
+ def resultset_without_paging_without_user_filters #:nodoc:
498
+ form_ar_options
499
+ with_exclusive_scope do
500
+ @klass.find(:all, :joins => @ar_options[:joins],
501
+ :include => @ar_options[:include],
502
+ :group => @ar_options[:group],
503
+ :conditions => @options[:conditions])
504
+ end
505
+ end
506
+
507
+ def count_resultset_without_paging_without_user_filters #:nodoc:
508
+ form_ar_options
509
+ with_exclusive_scope do
510
+ @klass.count(
511
+ :joins => @ar_options[:joins],
512
+ :include => @ar_options[:include],
513
+ :group => @ar_options[:group],
514
+ :conditions => @options[:conditions]
515
+ )
516
+ end
517
+ end
518
+
519
+
520
+ def resultset_without_paging_with_user_filters #:nodoc:
521
+ form_ar_options
522
+ with_exclusive_scope do
523
+ @klass.find(:all, :joins => @ar_options[:joins],
524
+ :include => @ar_options[:include],
525
+ :group => @ar_options[:group],
526
+ :conditions => @ar_options[:conditions],
527
+ :order => @ar_options[:order])
528
+ end
529
+ end
530
+
531
+
532
+ def load_query(query_id) #:nodoc:
533
+ @query_store_model ||= Wice::get_query_store_model
534
+ query = @query_store_model.find_by_id_and_grid_name(query_id, self.name)
535
+ Wice::log("Query with id #{query_id} for grid '#{self.name}' not found!!!") if query.nil?
536
+ query
537
+ end
538
+
539
+
540
+ end
541
+
542
+ # routines called from WiceGridExtentionToActiveRecordColumn (ActiveRecord::ConnectionAdapters::Column) or FilterConditionsGenerator classes
543
+ module GridTools #:nodoc:
544
+ class << self
545
+ def special_value(str) #:nodoc:
546
+ str =~ /^\s*(not\s+)?null\s*$/i
547
+ end
548
+
549
+ # create a Time instance out of parameters
550
+ def params_2_datetime(par) #:nodoc:
551
+ return nil if par.blank?
552
+ params = [par[:year], par[:month], par[:day], par[:hour], par[:minute]].collect{|v| v.blank? ? nil : v.to_i}
553
+ begin
554
+ Time.local(*params)
555
+ rescue ArgumentError, TypeError
556
+ nil
557
+ end
558
+ end
559
+
560
+ # create a Date instance out of parameters
561
+ def params_2_date(par) #:nodoc:
562
+ return nil if par.blank?
563
+ params = [par[:year], par[:month], par[:day]].collect{|v| v.blank? ? nil : v.to_i}
564
+ begin
565
+ Date.civil(*params)
566
+ rescue ArgumentError, TypeError
567
+ nil
568
+ end
569
+ end
570
+
571
+ end
572
+ end
573
+
574
+ # to be mixed in into ActiveRecord::ConnectionAdapters::Column
575
+ module WiceGridExtentionToActiveRecordColumn #:nodoc:
576
+
577
+ attr_accessor :model_klass
578
+
579
+ def alias_or_table_name(table_alias)
580
+ table_alias || self.model_klass.table_name
581
+ end
582
+
583
+ def wg_initialize_request_parameters(all_filter_params, main_table, table_alias, custom_filter_active) #:nodoc:
584
+ @request_params = nil
585
+ return if all_filter_params.nil?
586
+
587
+ # if the parameter does not specify the table name we only allow columns in the default table to use these parameters
588
+ if main_table && @request_params = all_filter_params[self.name]
589
+ current_parameter_name = self.name
590
+ elsif @request_params = all_filter_params[alias_or_table_name(table_alias) + '.' + self.name]
591
+ current_parameter_name = alias_or_table_name(table_alias) + '.' + self.name
592
+ end
593
+
594
+ # Preprocess incoming parameters for datetime, if what's coming in is
595
+ # a datetime (with custom_filter it can be anything else, and not
596
+ # the datetime hash {:fr => ..., :to => ...})
597
+ if @request_params
598
+ if (self.type == :datetime || self.type == :timestamp) && @request_params.is_a?(Hash)
599
+ [:fr, :to].each do |sym|
600
+ if @request_params[sym]
601
+ if @request_params[sym].is_a?(String)
602
+ @request_params[sym] = Wice::Defaults::DATETIME_PARSER.call(@request_params[sym])
603
+ elsif @request_params[sym].is_a?(Hash)
604
+ @request_params[sym] = ::Wice::GridTools.params_2_datetime(@request_params[sym])
605
+ end
606
+ end
607
+ end
608
+
609
+ end
610
+
611
+ # Preprocess incoming parameters for date, if what's coming in is
612
+ # a date (with custom_filter it can be anything else, and not
613
+ # the date hash {:fr => ..., :to => ...})
614
+ if self.type == :date && @request_params.is_a?(Hash)
615
+ [:fr, :to].each do |sym|
616
+ if @request_params[sym]
617
+ if @request_params[sym].is_a?(String)
618
+ @request_params[sym] = Wice::Defaults::DATE_PARSER.call(@request_params[sym])
619
+ elsif @request_params[sym].is_a?(Hash)
620
+ @request_params[sym] = ::Wice::GridTools.params_2_date(@request_params[sym])
621
+ end
622
+ end
623
+ end
624
+ end
625
+ end
626
+
627
+ return wg_generate_conditions(table_alias, custom_filter_active), current_parameter_name
628
+ end
629
+
630
+ def wg_generate_conditions(table_alias, custom_filter_active) #:nodoc:
631
+ return nil if @request_params.nil?
632
+
633
+ if custom_filter_active
634
+ return ::Wice::FilterConditionsGeneratorCustomFilter.new(self).generate_conditions(table_alias, @request_params)
635
+ end
636
+
637
+ column_type = self.type.to_s
638
+
639
+ processor_class = ::Wice::FilterConditionsGenerator.handled_type[column_type]
640
+
641
+ if processor_class
642
+ return processor_class.new(self).generate_conditions(table_alias, @request_params)
643
+ else
644
+ Wice.log("No processor for database type #{column_type}!!!")
645
+ nil
646
+ end
647
+ end
648
+
649
+ end
650
+
651
+ class FilterConditionsGenerator #:nodoc:
652
+
653
+ cattr_accessor :handled_type
654
+ @@handled_type = HashWithIndifferentAccess.new
655
+
656
+ def initialize(column) #:nodoc:
657
+ @column = column
658
+ end
659
+ end
660
+
661
+ class FilterConditionsGeneratorCustomFilter < FilterConditionsGenerator #:nodoc:
662
+
663
+ def generate_conditions(table_alias, opts) #:nodoc:
664
+ if opts.empty?
665
+ Wice.log "empty parameters for the grid custom filter"
666
+ return false
667
+ end
668
+ opts = (opts.kind_of?(Array) && opts.size == 1) ? opts[0] : opts
669
+
670
+ if opts.kind_of?(Array)
671
+ opts_with_special_values, normal_opts = opts.partition{|v| ::Wice::GridTools.special_value(v)}
672
+
673
+ conditions_ar = if normal_opts.size > 0
674
+ [" #{@column.alias_or_table_name(table_alias)}.#{@column.name} IN ( " + (['?'] * normal_opts.size).join(', ') + ' )'] + normal_opts
675
+ else
676
+ []
677
+ end
678
+
679
+ if opts_with_special_values.size > 0
680
+ special_conditions = opts_with_special_values.collect{|v| " #{@column.alias_or_table_name(table_alias)}.#{@column.name} is " + v}.join(' or ')
681
+ if conditions_ar.size > 0
682
+ conditions_ar[0] = " (#{conditions_ar[0]} or #{special_conditions} ) "
683
+ else
684
+ conditions_ar = " ( #{special_conditions} ) "
685
+ end
686
+ end
687
+ conditions_ar
688
+ else
689
+ if ::Wice::GridTools.special_value(opts)
690
+ " #{@column.alias_or_table_name(table_alias)}.#{@column.name} is " + opts
691
+ else
692
+ [" #{@column.alias_or_table_name(table_alias)}.#{@column.name} = ?", opts]
693
+ end
694
+ end
695
+ end
696
+
697
+ end
698
+
699
+ class FilterConditionsGeneratorBoolean < FilterConditionsGenerator #:nodoc:
700
+ @@handled_type[:boolean] = self
701
+
702
+ def generate_conditions(table_alias, opts) #:nodoc:
703
+ unless (opts.kind_of?(Array) && opts.size == 1)
704
+ Wice.log "invalid parameters for the grid boolean filter - must be an one item array: #{opts.inspect}"
705
+ return false
706
+ end
707
+ opts = opts[0]
708
+ if opts == 'f'
709
+ [" (#{@column.alias_or_table_name(table_alias)}.#{@column.name} = ? or #{@column.alias_or_table_name(table_alias)}.#{@column.name} is null) ", false]
710
+ elsif opts == 't'
711
+ [" #{@column.alias_or_table_name(table_alias)}.#{@column.name} = ?", true]
712
+ else
713
+ nil
714
+ end
715
+ end
716
+ end
717
+
718
+ class FilterConditionsGeneratorString < FilterConditionsGenerator #:nodoc:
719
+ @@handled_type[:string] = self
720
+ @@handled_type[:text] = self
721
+
722
+ def generate_conditions(table_alias, opts) #:nodoc:
723
+ if opts.kind_of? String
724
+ string_fragment = opts
725
+ negation = ''
726
+ elsif (opts.kind_of? Hash) && opts.has_key?(:v)
727
+ string_fragment = opts[:v]
728
+ negation = opts[:n] == '1' ? 'NOT' : ''
729
+ else
730
+ Wice.log "invalid parameters for the grid string filter - must be a string: #{opts.inspect} or a Hash with keys :v and :n"
731
+ return false
732
+ end
733
+ if string_fragment.empty?
734
+ Wice.log "invalid parameters for the grid string filter - empty string"
735
+ return false
736
+ end
737
+ [" #{negation} #{@column.alias_or_table_name(table_alias)}.#{@column.name} #{::Wice.get_string_matching_operators(@column.model_klass)} ?",
738
+ '%' + string_fragment + '%']
739
+ end
740
+
741
+ end
742
+
743
+ class FilterConditionsGeneratorInteger < FilterConditionsGenerator #:nodoc:
744
+ @@handled_type[:integer] = self
745
+ @@handled_type[:float] = self
746
+ @@handled_type[:decimal] = self
747
+
748
+ def generate_conditions(table_alias, opts) #:nodoc:
749
+ unless opts.kind_of? Hash
750
+ Wice.log "invalid parameters for the grid integer filter - must be a hash"
751
+ return false
752
+ end
753
+ conditions = [[]]
754
+ if opts[:fr]
755
+ if opts[:fr] =~ /\d/
756
+ conditions[0] << " #{@column.alias_or_table_name(table_alias)}.#{@column.name} >= ? "
757
+ conditions << opts[:fr]
758
+ else
759
+ opts.delete(:fr)
760
+ end
761
+ end
762
+
763
+ if opts[:to]
764
+ if opts[:to] =~ /\d/
765
+ conditions[0] << " #{@column.alias_or_table_name(table_alias)}.#{@column.name} <= ? "
766
+ conditions << opts[:to]
767
+ else
768
+ opts.delete(:to)
769
+ end
770
+ end
771
+
772
+ if conditions.size == 1
773
+ Wice.log "invalid parameters for the grid integer filter - either range limits are not supplied or they are not numeric"
774
+ return false
775
+ end
776
+
777
+ conditions[0] = conditions[0].join(' and ')
778
+
779
+ return conditions
780
+ end
781
+ end
782
+
783
+ class FilterConditionsGeneratorDate < FilterConditionsGenerator #:nodoc:
784
+ @@handled_type[:date] = self
785
+ @@handled_type[:datetime] = self
786
+ @@handled_type[:timestamp] = self
787
+
788
+ def generate_conditions(table_alias, opts) #:nodoc:
789
+ conditions = [[]]
790
+ if opts[:fr]
791
+ conditions[0] << " #{@column.alias_or_table_name(table_alias)}.#{@column.name} >= ? "
792
+ conditions << opts[:fr]
793
+ end
794
+
795
+ if opts[:to]
796
+ conditions[0] << " #{@column.alias_or_table_name(table_alias)}.#{@column.name} <= ? "
797
+ conditions << opts[:to]
798
+ end
799
+
800
+ return false if conditions.size == 1
801
+
802
+ conditions[0] = conditions[0].join(' and ')
803
+ return conditions
804
+ end
805
+ end
806
+
807
+ end
808
+
809
+ ActiveRecord::ConnectionAdapters::Column.send(:include, ::Wice::WiceGridExtentionToActiveRecordColumn)