wice_grid_mongo 6.2.4

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 (71) hide show
  1. data/CHANGELOG +409 -0
  2. data/Gemfile +14 -0
  3. data/Gemfile.lock +144 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.rdoc +1188 -0
  6. data/Rakefile +40 -0
  7. data/SAVED_QUERIES_HOWTO.rdoc +123 -0
  8. data/lib/filter_conditions_generators.rb +152 -0
  9. data/lib/generators/wice_grid/templates/calendarview.css +107 -0
  10. data/lib/generators/wice_grid/templates/calendarview.js +1168 -0
  11. data/lib/generators/wice_grid/templates/icons/arrow_down.gif +0 -0
  12. data/lib/generators/wice_grid/templates/icons/arrow_up.gif +0 -0
  13. data/lib/generators/wice_grid/templates/icons/calendar_view_month.png +0 -0
  14. data/lib/generators/wice_grid/templates/icons/delete.png +0 -0
  15. data/lib/generators/wice_grid/templates/icons/expand.png +0 -0
  16. data/lib/generators/wice_grid/templates/icons/page_white_excel.png +0 -0
  17. data/lib/generators/wice_grid/templates/icons/page_white_find.png +0 -0
  18. data/lib/generators/wice_grid/templates/icons/table.png +0 -0
  19. data/lib/generators/wice_grid/templates/icons/table_refresh.png +0 -0
  20. data/lib/generators/wice_grid/templates/icons/tick_all.png +0 -0
  21. data/lib/generators/wice_grid/templates/icons/untick_all.png +0 -0
  22. data/lib/generators/wice_grid/templates/wice_grid.css +173 -0
  23. data/lib/generators/wice_grid/templates/wice_grid.yml +269 -0
  24. data/lib/generators/wice_grid/templates/wice_grid_config.rb +215 -0
  25. data/lib/generators/wice_grid/templates/wice_grid_jquery.js +161 -0
  26. data/lib/generators/wice_grid/templates/wice_grid_prototype.js +153 -0
  27. data/lib/generators/wice_grid/wice_grid_assets_jquery_generator.rb +32 -0
  28. data/lib/generators/wice_grid/wice_grid_assets_prototype_generator.rb +34 -0
  29. data/lib/grid_output_buffer.rb +52 -0
  30. data/lib/grid_renderer.rb +549 -0
  31. data/lib/helpers/js_calendar_helpers.rb +183 -0
  32. data/lib/helpers/wice_grid_misc_view_helpers.rb +113 -0
  33. data/lib/helpers/wice_grid_serialized_queries_view_helpers.rb +82 -0
  34. data/lib/helpers/wice_grid_view_helpers.rb +762 -0
  35. data/lib/js_adaptors/jquery_adaptor.rb +145 -0
  36. data/lib/js_adaptors/js_adaptor.rb +12 -0
  37. data/lib/js_adaptors/prototype_adaptor.rb +168 -0
  38. data/lib/mongoid_field.rb +67 -0
  39. data/lib/tasks/wice_grid_tasks.rake +28 -0
  40. data/lib/view_columns.rb +464 -0
  41. data/lib/views/create.rjs +13 -0
  42. data/lib/views/delete.rjs +12 -0
  43. data/lib/wice_grid.rb +528 -0
  44. data/lib/wice_grid_controller.rb +165 -0
  45. data/lib/wice_grid_core_ext.rb +179 -0
  46. data/lib/wice_grid_misc.rb +99 -0
  47. data/lib/wice_grid_serialized_queries_controller.rb +77 -0
  48. data/lib/wice_grid_serialized_query.rb +14 -0
  49. data/lib/wice_grid_spreadsheet.rb +33 -0
  50. data/test/.gitignore +2 -0
  51. data/test/blueprint.rb +18 -0
  52. data/test/database.yml +21 -0
  53. data/test/public/javascripts/jquery-1.4.2.min.js +154 -0
  54. data/test/public/javascripts/wice_grid.js +163 -0
  55. data/test/rails_mongoid_test.rb +140 -0
  56. data/test/rails_test_app.rb +72 -0
  57. data/test/require_gems.rb +19 -0
  58. data/test/schema.rb +33 -0
  59. data/test/spec_helper.rb +22 -0
  60. data/test/test_helper.rb +89 -0
  61. data/test/views/projects_and_people_grid.html.erb +12 -0
  62. data/test/views/projects_and_people_grid_invalid.html.erb +12 -0
  63. data/test/views/simple_projects_grid.html.erb +9 -0
  64. data/test/wice_grid_core_ext_test.rb +183 -0
  65. data/test/wice_grid_functional_test.rb +68 -0
  66. data/test/wice_grid_initializer.rb +215 -0
  67. data/test/wice_grid_misc_test.rb +41 -0
  68. data/test/wice_grid_test.rb +42 -0
  69. data/test/wice_grid_view_helper_test.rb +12 -0
  70. data/wice_grid_mongo.gemspec +94 -0
  71. metadata +118 -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,528 @@
1
+ # encoding: UTF-8
2
+ require 'wice_grid_misc.rb'
3
+ require 'wice_grid_core_ext.rb'
4
+ require 'grid_renderer.rb'
5
+ require 'helpers/wice_grid_view_helpers.rb'
6
+ require 'helpers/wice_grid_misc_view_helpers.rb'
7
+ require 'helpers/wice_grid_serialized_queries_view_helpers.rb'
8
+ require 'helpers/wice_grid_view_helpers.rb'
9
+ require 'helpers/js_calendar_helpers.rb'
10
+ require 'grid_output_buffer.rb'
11
+ require 'wice_grid_controller.rb'
12
+ require 'mongoid_field'
13
+ require 'wice_grid_spreadsheet.rb'
14
+ require 'wice_grid_serialized_queries_controller.rb'
15
+ require 'js_adaptors/js_adaptor.rb'
16
+ require 'js_adaptors/jquery_adaptor.rb'
17
+ require 'js_adaptors/prototype_adaptor.rb'
18
+ require 'view_columns.rb'
19
+
20
+
21
+ ActionController::Base.send(:helper_method, :wice_grid_custom_filter_params)
22
+
23
+ module Wice
24
+
25
+ class WiceGridRailtie < Rails::Railtie
26
+
27
+ initializer "wice_grid_railtie.configure_rails_initialization" do |app|
28
+ ActionController::Base.send(:include, Wice::Controller)
29
+ Mongoid::Fields.send(:include, ::Wice::MongoidField)
30
+ ::ActionView::Base.class_eval { include Wice::GridViewHelper }
31
+
32
+ [ActionView::Helpers::AssetTagHelper,
33
+ ActionView::Helpers::TagHelper,
34
+ ActionView::Helpers::JavaScriptHelper,
35
+ ActionView::Helpers::FormTagHelper].each do |m|
36
+ JsCalendarHelpers.send(:include, m)
37
+ end
38
+ end
39
+
40
+ rake_tasks do
41
+ load 'tasks/wice_grid_tasks.rake'
42
+ end
43
+ end
44
+
45
+ class WiceGrid
46
+
47
+ attr_reader :klass, :name, :resultset, :custom_order, :query_store_model, :options, :controller
48
+ attr_reader :ar_options, :status, :export_to_csv_enabled, :csv_file_name, :saved_query, :extra_filter
49
+ attr_writer :renderer
50
+ attr_accessor :output_buffer, :view_helper_finished, :csv_tempfile
51
+
52
+ # core workflow methods START
53
+
54
+ def initialize(klass, controller, opts = {}) #:nodoc:
55
+ @controller = controller
56
+
57
+ unless klass.kind_of?(Class) && klass.ancestors.index(Mongoid::Document)
58
+ raise WiceGridArgumentError.new("The model class (second argument) must be a Class derived from Mongoid::Document")
59
+ end
60
+ # validate :with_resultset & :with_paginated_resultset
61
+ [:with_resultset, :with_paginated_resultset].each do |callback_symbol|
62
+ unless [NilClass, Symbol, Proc].index(opts[callback_symbol].class)
63
+ raise WiceGridArgumentError.new(":#{callback_symbol} must be either a Proc or Symbol object")
64
+ end
65
+ end
66
+
67
+ opts[:order_direction].downcase! if opts[:order_direction].kind_of?(String)
68
+
69
+ # validate :order_direction
70
+ if opts[:order_direction] && ! (opts[:order_direction] == 'asc' ||
71
+ opts[:order_direction] == :asc ||
72
+ opts[:order_direction] == 'desc' ||
73
+ opts[:order_direction] == :desc)
74
+ raise WiceGridArgumentError.new(":order_direction must be either 'asc' or 'desc'.")
75
+ end
76
+
77
+ # options that are understood
78
+ @options = {
79
+ :conditions => nil,
80
+ :csv_file_name => nil,
81
+ :custom_order => {},
82
+ :enable_export_to_csv => Defaults::ENABLE_EXPORT_TO_CSV,
83
+ :group => nil,
84
+ :include => nil,
85
+ :joins => nil,
86
+ :name => Defaults::GRID_NAME,
87
+ :order => nil,
88
+ :order_direction => Defaults::ORDER_DIRECTION,
89
+ :per_page => Defaults::PER_PAGE,
90
+ :saved_query => nil,
91
+ :select => nil,
92
+ :total_entries => nil,
93
+ :with_paginated_resultset => nil,
94
+ :with_resultset => nil
95
+ }
96
+
97
+ # validate parameters
98
+ opts.assert_valid_keys(@options.keys)
99
+
100
+ @options.merge!(opts)
101
+ @export_to_csv_enabled = @options[:enable_export_to_csv]
102
+ @csv_file_name = @options[:csv_file_name]
103
+
104
+ case @name = @options[:name]
105
+ when String
106
+ when Symbol
107
+ @name = @name.to_s
108
+ else
109
+ raise WiceGridArgumentError.new("name of the grid should be a string or a symbol")
110
+ end
111
+ raise WiceGridArgumentError.new("name of the grid can only contain alphanumeruc characters") unless @name =~ /^[a-zA-Z\d_]*$/
112
+
113
+ @klass = klass
114
+ @criteria = Mongoid::Criteria.new(@klass)
115
+ @has_any_filter_criteria = false
116
+ @status = HashWithIndifferentAccess.new
117
+
118
+ if @options[:order]
119
+ @options[:order] = @options[:order].to_s
120
+ @options[:order_direction] = @options[:order_direction].to_s
121
+
122
+ @status[:order_direction] = @options[:order_direction]
123
+ @status[:order] = @options[:order]
124
+
125
+ end
126
+ @status[:total_entries] = @options[:total_entries]
127
+ @status[:per_page] = @options[:per_page]
128
+ @status[:page] = @options[:page]
129
+ @status[:conditions] = @options[:conditions]
130
+ @status[:f] = @options[:f]
131
+
132
+ process_loading_query
133
+ process_params
134
+ @criteria_formed = false
135
+ end
136
+
137
+ def add_criteria(extra)
138
+ @extra_filter = extra
139
+ @criteria = @criteria.merge(extra)
140
+ end
141
+
142
+ def has_any_filter_criteria?
143
+ @has_any_filter_criteria
144
+ end
145
+
146
+ def has_more_to_show?
147
+ @status[:per_page].to_i < resultset.count
148
+ end
149
+ # A block executed from within the plugin to process records of the current page.
150
+ # The argument to the callback is the array of the records. See the README for more details.
151
+ def with_paginated_resultset(&callback)
152
+ @options[:with_paginated_resultset] = callback
153
+ end
154
+
155
+ # A block executed from within the plugin to process all records browsable through
156
+ # all pages with the current filters. The argument to
157
+ # the callback is a lambda object which returns the list of records when called. See the README for the explanation.
158
+ def with_resultset(&callback)
159
+ @options[:with_resultset] = callback
160
+ end
161
+
162
+ def process_loading_query #:nodoc:
163
+ @saved_query = nil
164
+ if params[name] && params[name][:q]
165
+ @saved_query = load_query(params[name][:q])
166
+ params[name].delete(:q)
167
+ elsif @options[:saved_query]
168
+ if @options[:saved_query].is_a? ActiveRecord::Base
169
+ @saved_query = @options[:saved_query]
170
+ else
171
+ @saved_query = load_query(@options[:saved_query])
172
+ end
173
+ else
174
+ return
175
+ end
176
+
177
+ unless @saved_query.nil?
178
+ params[name] = HashWithIndifferentAccess.new if params[name].blank?
179
+ [:f, :order, :order_direction].each do |key|
180
+ if @saved_query.query[key].blank?
181
+ params[name].delete(key)
182
+ else
183
+ params[name][key] = @saved_query.query[key]
184
+ end
185
+ end
186
+ end
187
+ end
188
+
189
+ def process_params #:nodoc:
190
+ if this_grid_params
191
+ @status.merge!(this_grid_params)
192
+ @status.delete(:export) unless self.export_to_csv_enabled
193
+ end
194
+ end
195
+
196
+ def declare_column(field_name, custom_filter_active) #:nodoc:
197
+ field = @klass.fields[field_name]
198
+ raise WiceGridArgumentError.new("Model #{@klass.name} does not have field '#{field_name}'.! ") unless field
199
+
200
+ criteria_added, criteria = field.wice_add_filter_criteria(@status[:f], @klass, custom_filter_active)
201
+ @criteria = @criteria.merge(criteria) if criteria
202
+
203
+ @status[:f].delete(field_name) if @status[:f] && !criteria_added
204
+
205
+ @has_any_filter_criteria ||= criteria_added
206
+ [field, nil , true]
207
+ end
208
+
209
+ def form_criteria(opts = {}) #:nodoc:
210
+
211
+ return if @criteria_formed
212
+ @criteria_formed = true unless opts[:forget_generated_options]
213
+
214
+ # validate @status[:order_direction]
215
+ @status[:order_direction] = case @status[:order_direction]
216
+ when /desc/i
217
+ 'desc'
218
+ when /asc/i
219
+ 'asc'
220
+ else
221
+ ''
222
+ end
223
+
224
+ @status.delete(:f) if !@has_any_filter_criteria
225
+
226
+ if !opts[:skip_ordering] && @status[:order]
227
+ order_by = @status[:order].to_sym.send( @status[:order_direction].to_sym )
228
+ @criteria = @criteria.order_by(order_by)
229
+ end
230
+
231
+ @criteria = @criteria.limit(@status[:per_page].to_i)
232
+ # #fix-this, Criteria must respect options
233
+ # if self.output_html?
234
+ # @criteria[:per_page] = if all_record_mode?
235
+ # # reset the :pp value in all records mode
236
+ # @status[:pp] = count_resultset_without_paging_without_user_filters
237
+ # else
238
+ # @status[:per_page]
239
+ # end
240
+
241
+ # @criteria[:page] = @status[:page]
242
+ # @criteria[:total_entries] = @status[:total_entries] if @status[:total_entries]
243
+ # end
244
+
245
+ # @criteria[:joins] = @options[:joins]
246
+ # @criteria[:include] = @options[:include]
247
+ # @criteria[:group] = @options[:group]
248
+ # @criteria[:select] = @options[:select]
249
+ end
250
+
251
+ def read #:nodoc:
252
+ form_criteria
253
+ with_exclusive_scope do
254
+ @criteria.options[:limit] = nil if @resultset = self.output_csv?
255
+ @resultset = @criteria
256
+ end
257
+ invoke_resultset_callbacks
258
+ end
259
+
260
+
261
+ # core workflow methods END
262
+
263
+ # Getters
264
+
265
+ def filter_params(view_column) #:nodoc:
266
+ return (@status[:f][view_column.attribute_name] || "") if @status[:f]
267
+ ""
268
+ end
269
+
270
+ def resultset #:nodoc:
271
+ self.read unless @resultset # database querying is late!
272
+ @resultset
273
+ end
274
+
275
+ def each #:nodoc:
276
+ self.read unless @resultset # database querying is late!
277
+ @resultset.each do |r|
278
+ yield r
279
+ end
280
+ end
281
+
282
+ def ordered_by?(column) #:nodoc:
283
+ return nil if @status[:order].blank?
284
+ @status[:order] == column.attribute_name
285
+ end
286
+
287
+ def ordered_by #:nodoc:
288
+ @status[:order]
289
+ end
290
+
291
+
292
+ def order_direction #:nodoc:
293
+ @status[:order_direction]
294
+ end
295
+
296
+ def filtering_on? #:nodoc:
297
+ not @status[:f].blank?
298
+ end
299
+
300
+ def filtered_by #:nodoc:
301
+ @status[:f].nil? ? [] : @status[:f].keys
302
+ end
303
+
304
+ def filtered_by?(view_column) #:nodoc:
305
+ @status[:f] && @status[:f].has_key?(view_column.attribute_name)
306
+ end
307
+
308
+ def get_state_as_parameter_value_pairs(including_saved_query_request = false) #:nodoc:
309
+ res = []
310
+ unless status[:f].blank?
311
+ status[:f].parameter_names_and_values([name, 'f']).collect do |param_name, value|
312
+ if value.is_a?(Array)
313
+ param_name_ar = param_name + '[]'
314
+ value.each do |v|
315
+ res << [param_name_ar, v]
316
+ end
317
+ else
318
+ res << [param_name, value]
319
+ end
320
+ end
321
+ end
322
+
323
+ if including_saved_query_request && @saved_query
324
+ res << ["#{name}[q]", @saved_query.id ]
325
+ end
326
+
327
+ [:order, :order_direction].select{|parameter|
328
+ status[parameter]
329
+ }.collect do |parameter|
330
+ res << ["#{name}[#{parameter}]", status[parameter] ]
331
+ end
332
+
333
+ res
334
+ end
335
+
336
+ def count #:nodoc:
337
+ form_criteria(:skip_ordering => true, :forget_generated_options => true)
338
+ @klass.count(:conditions => @criteria[:conditions], :joins => @criteria[:joins], :include => @criteria[:include], :group => @criteria[:group])
339
+ end
340
+
341
+ alias_method :size, :count
342
+
343
+ def empty? #:nodoc:
344
+ self.count == 0
345
+ end
346
+
347
+ # with this variant we get even those values which do not appear in the resultset
348
+ def distinct_values_for_column(column) #:nodoc:
349
+ res = column.model_klass.find(:all, :select => "distinct #{column.name}", :order => "#{column.name} asc").collect{|ar|
350
+ ar[column.name]
351
+ }.reject{|e| e.blank?}.map{|i|[i,i]}
352
+ end
353
+
354
+
355
+ def distinct_values_for_column_in_resultset(messages) #:nodoc:
356
+ uniq_vals = Set.new
357
+
358
+ resultset_without_paging_without_user_filters.each do |ar|
359
+ v = ar.deep_send(*messages)
360
+ uniq_vals << v unless v.nil?
361
+ end
362
+ return uniq_vals.to_a.map{|i|
363
+ if i.is_a?(Array) && i.size == 2
364
+ i
365
+ elsif i.is_a?(Hash) && i.size == 1
366
+ i.to_a.flatten
367
+ else
368
+ [i,i]
369
+ end
370
+ }.sort{|a,b| a[0]<=>b[0]}
371
+ end
372
+
373
+ def output_csv? #:nodoc:
374
+ @status[:export] == 'csv'
375
+ end
376
+
377
+ def output_html? #:nodoc:
378
+ @status[:export].blank?
379
+ end
380
+
381
+ def all_record_mode? #:nodoc:
382
+ @status[:pp]
383
+ end
384
+
385
+ def dump_status #:nodoc:
386
+ " params: #{params[name].inspect}\n" +
387
+ " status: #{@status.inspect}\n" +
388
+ " ar_options #{@criteria.inspect}\n"
389
+ end
390
+
391
+
392
+ def selected_records #:nodoc:
393
+ STDERR.puts "WiceGrid: Parameter :#{selected_records} is deprecated, use :#{all_pages_records} or :#{current_page_records} instead!"
394
+ all_pages_records
395
+ end
396
+
397
+ # Returns the list of objects browsable through all pages with the current filters.
398
+ # Should only be called after the +grid+ helper.
399
+ def all_pages_records
400
+ raise WiceGridException.new("all_pages_records can only be called only after the grid view helper") unless self.view_helper_finished
401
+ resultset_without_paging_with_user_filters
402
+ end
403
+
404
+ # Returns the list of objects displayed on current page. Should only be called after the +grid+ helper.
405
+ def current_page_records
406
+ raise WiceGridException.new("current_page_records can only be called only after the grid view helper") unless self.view_helper_finished
407
+ @resultset
408
+ end
409
+
410
+
411
+
412
+ protected
413
+
414
+ def invoke_resultset_callback(callback, argument) #:nodoc:
415
+ case callback
416
+ when Proc
417
+ callback.call(argument)
418
+ when Symbol
419
+ @controller.send(callback, argument)
420
+ end
421
+ end
422
+
423
+ def invoke_resultset_callbacks #:nodoc:
424
+ invoke_resultset_callback(@options[:with_paginated_resultset], @resultset)
425
+ invoke_resultset_callback(@options[:with_resultset], lambda{self.send(:resultset_without_paging_with_user_filters)})
426
+ end
427
+
428
+ def with_exclusive_scope #:nodoc:
429
+ yield
430
+ end
431
+
432
+ def complete_column_name(col_name) #:nodoc:
433
+ if col_name.index('.') # already has a table name
434
+ col_name
435
+ else # add the default table
436
+ "#{@klass.collection_name}.#{col_name}"
437
+ end
438
+ end
439
+
440
+ def params #:nodoc:
441
+ @controller.params
442
+ end
443
+
444
+ def this_grid_params #:nodoc:
445
+ params[name]
446
+ end
447
+
448
+
449
+ def resultset_without_paging_without_user_filters #:nodoc:
450
+ form_criteria
451
+ with_exclusive_scope do
452
+ @klass.find(:all, :joins => @criteria[:joins],
453
+ :include => @criteria[:include],
454
+ :group => @criteria[:group],
455
+ :conditions => @options[:conditions])
456
+ end
457
+ end
458
+
459
+ def count_resultset_without_paging_without_user_filters #:nodoc:
460
+ form_criteria
461
+ with_exclusive_scope do
462
+ @klass.count(
463
+ :joins => @criteria[:joins],
464
+ :include => @criteria[:include],
465
+ :group => @criteria[:group],
466
+ :conditions => @options[:conditions]
467
+ )
468
+ end
469
+ end
470
+
471
+
472
+ def resultset_without_paging_with_user_filters #:nodoc:
473
+ form_criteria
474
+ with_exclusive_scope do
475
+ @klass.find(:all, :joins => @criteria[:joins],
476
+ :include => @criteria[:include],
477
+ :group => @criteria[:group],
478
+ :conditions => @criteria[:conditions],
479
+ :order => @criteria[:order])
480
+ end
481
+ end
482
+
483
+
484
+ def load_query(query_id) #:nodoc:
485
+ @query_store_model ||= Wice::get_query_store_model
486
+ query = @query_store_model.find_by_id_and_grid_name(query_id, self.name)
487
+ Wice::log("Query with id #{query_id} for grid '#{self.name}' not found!!!") if query.nil?
488
+ query
489
+ end
490
+
491
+
492
+ end
493
+
494
+ # routines called from WiceGridExtentionToActiveRecordColumn (ActiveRecord::ConnectionAdapters::Column) or FilterConditionsGenerator classes
495
+ module GridTools #:nodoc:
496
+ class << self
497
+ def special_value(str) #:nodoc:
498
+ str =~ /^\s*(not\s+)?null\s*$/i
499
+ end
500
+
501
+ # create a Time instance out of parameters
502
+ def params_2_datetime(par) #:nodoc:
503
+ return nil if par.blank?
504
+ params = [par[:year], par[:month], par[:day], par[:hour], par[:minute]].collect{|v| v.blank? ? nil : v.to_i}
505
+ begin
506
+ Time.local(*params)
507
+ rescue ArgumentError, TypeError
508
+ nil
509
+ end
510
+ end
511
+
512
+ # create a Date instance out of parameters
513
+ def params_2_date(par) #:nodoc:
514
+ return nil if par.blank?
515
+ params = [par[:year], par[:month], par[:day]].collect{|v| v.blank? ? nil : v.to_i}
516
+ begin
517
+ Date.civil(*params)
518
+ rescue ArgumentError, TypeError
519
+ nil
520
+ end
521
+ end
522
+
523
+ end
524
+ end
525
+
526
+
527
+
528
+ end