wice_grid_mongoid 0.5.6

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