will_filter 3.1.3 → 3.1.5

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 (64) hide show
  1. data/.gitignore +1 -0
  2. data/.rvmrc +1 -1
  3. data/Gemfile.lock +2 -2
  4. data/README.rdoc +0 -3
  5. data/app/assets/javascripts/will_filter/filter.js +5 -5
  6. data/app/assets/javascripts/will_filter/filter_prototype_effects.js +1 -1
  7. data/app/assets/stylesheets/will_filter/exporter.css.scss +72 -49
  8. data/app/assets/stylesheets/will_filter/filter.css.scss +1 -0
  9. data/app/controllers/will_filter/application_controller.rb +1 -1
  10. data/app/controllers/will_filter/calendar_controller.rb +1 -1
  11. data/app/controllers/will_filter/exporter_controller.rb +15 -26
  12. data/app/controllers/will_filter/filter_controller.rb +7 -1
  13. data/app/models/will_filter/filter.rb +69 -12
  14. data/app/views/will_filter/exporter/export.html.erb +26 -2
  15. data/app/views/will_filter/exporter/index.html.erb +35 -43
  16. data/app/views/will_filter/filter/_conditions.html.erb +13 -32
  17. data/app/views/will_filter/filter/_conditions_footer.html.erb +17 -0
  18. data/app/views/will_filter/filter/_conditions_header.html.erb +38 -0
  19. data/app/views/will_filter/filter/_container.html.erb +3 -25
  20. data/lib/generators/will_filter/templates/config.yml +34 -1
  21. data/lib/generators/will_filter/will_filter_generator.rb +1 -1
  22. data/lib/tasks/will_filter_tasks.rake +1 -5
  23. data/lib/will_filter.rb +1 -1
  24. data/lib/will_filter/calendar.rb +1 -1
  25. data/lib/will_filter/config.rb +9 -1
  26. data/lib/will_filter/containers/boolean.rb +1 -1
  27. data/lib/will_filter/containers/date.rb +2 -8
  28. data/lib/will_filter/containers/date_range.rb +3 -9
  29. data/lib/will_filter/containers/date_time.rb +2 -8
  30. data/lib/will_filter/containers/date_time_range.rb +4 -16
  31. data/lib/will_filter/containers/double.rb +52 -0
  32. data/lib/will_filter/containers/double_delimited.rb +50 -0
  33. data/lib/will_filter/containers/double_range.rb +64 -0
  34. data/lib/will_filter/containers/filter_list.rb +1 -1
  35. data/lib/will_filter/containers/list.rb +1 -1
  36. data/lib/will_filter/containers/nil.rb +1 -1
  37. data/lib/will_filter/containers/numeric.rb +1 -1
  38. data/lib/will_filter/containers/numeric_delimited.rb +1 -1
  39. data/lib/will_filter/containers/numeric_range.rb +1 -1
  40. data/lib/will_filter/containers/single_date.rb +3 -3
  41. data/lib/will_filter/containers/text.rb +1 -1
  42. data/lib/will_filter/containers/text_delimited.rb +1 -1
  43. data/lib/will_filter/engine.rb +1 -1
  44. data/lib/will_filter/extensions/action_controller_extension.rb +1 -1
  45. data/lib/will_filter/extensions/action_view_extension.rb +1 -1
  46. data/lib/will_filter/extensions/active_record_extension.rb +1 -1
  47. data/lib/will_filter/extensions/array_extension.rb +1 -1
  48. data/lib/will_filter/filter_condition.rb +1 -1
  49. data/lib/will_filter/filter_container.rb +21 -3
  50. data/lib/will_filter/filter_exception.rb +1 -1
  51. data/lib/will_filter/railtie.rb +1 -1
  52. data/lib/will_filter/version.rb +2 -2
  53. data/spec/containers/double_spec.rb +16 -0
  54. data/spec/fake_app.rb +6 -12
  55. data/test/dummy/app/models/event.rb +1 -1
  56. data/test/dummy/app/models/event_filter.rb +4 -0
  57. data/test/dummy/app/models/event_user_filter.rb +4 -0
  58. data/test/dummy/app/models/user_filter.rb +31 -2
  59. data/test/dummy/config/will_filter/config.yml +9 -1
  60. data/test/dummy/db/migrate/20120223232000_add_rank_to_events.rb +5 -0
  61. data/test/dummy/db/schema.rb +2 -1
  62. metadata +40 -108
  63. data/config/will_filter/config.yml +0 -97
  64. data/db/migrate/20110924023807_create_will_filter_filters.rb +0 -15
data/.gitignore CHANGED
@@ -4,6 +4,7 @@ pkg/
4
4
  test/dummy/db/*.sqlite3
5
5
  test/dummy/log/*.log
6
6
  test/dummy/tmp/
7
+ test/dummy/.sass-cache/
7
8
  db/schema.rb*
8
9
  tmp/*
9
10
  log/*
data/.rvmrc CHANGED
@@ -1 +1 @@
1
- rvm 1.9.2 --create
1
+ rvm use 1.9.2@will_filter --create
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- will_filter (3.1.3)
4
+ will_filter (3.1.5)
5
5
  coffee-script
6
6
  kaminari
7
7
  rails (>= 3.1.0)
@@ -126,7 +126,7 @@ GEM
126
126
  sprockets (2.0.0)
127
127
  hike (~> 1.2)
128
128
  rack (~> 1.0)
129
- tilt (!= 1.3.0, ~> 1.1)
129
+ tilt (~> 1.1, != 1.3.0)
130
130
  sqlite3 (1.3.4)
131
131
  steak (2.0.0)
132
132
  capybara (>= 1.0.0)
data/README.rdoc CHANGED
@@ -72,9 +72,6 @@ Open your browser and point to:
72
72
 
73
73
  http://localhost:3000
74
74
 
75
- Live will_filter_examples application is running here:
76
-
77
- http://wf.tr8n.org
78
75
 
79
76
  If you have any questions, comments or suggestions, email me at theiceberk@gmail.com
80
77
 
@@ -1,5 +1,5 @@
1
1
  /****************************************************************************
2
- Copyright (c) 2010-2011 Michael Berkovich
2
+ # Copyright (c) 2010-2012 Michael Berkovich
3
3
 
4
4
  Permission is hereby granted, free of charge, to any person obtaining
5
5
  a copy of this software and associated documentation files (the
@@ -235,7 +235,7 @@ Wf.Calendar.prototype = {
235
235
  var trigger_position = Wf.Utils.cumulativeOffset(wfCalendar.trigger);
236
236
  var calendar_container = Wf.element("wf_calendar");
237
237
  calendar_container.style.left = (trigger_position[0] - 273) + "px";
238
- calendar_container.style.top = trigger_position[1] - 6 + "px";
238
+ calendar_container.style.top = trigger_position[1] - 38 + "px";
239
239
  calendar_container.style.width = "260px";
240
240
  Wf.Effects.appear("wf_calendar");
241
241
  }
@@ -261,7 +261,7 @@ Wf.Calendar.prototype = {
261
261
  var width = (mode=='annual' ? 760 : 400);
262
262
  var calendar_container = Wf.element("wf_calendar");
263
263
  calendar_container.style.left = (trigger_position[0] - width - 13) + "px";
264
- calendar_container.style.top = trigger_position[1] - 6 + "px";
264
+ calendar_container.style.top = trigger_position[1] - 38 + "px";
265
265
  calendar_container.style.width = width + "px";
266
266
  }
267
267
  });
@@ -340,8 +340,8 @@ Wf.Exporter.prototype = {
340
340
  onComplete: function(transport) {
341
341
  var trigger_position = Wf.Utils.cumulativeOffset(trigger);
342
342
  var exporter_container = Wf.element("wf_exporter");
343
- exporter_container.style.left = (trigger_position[0] - 245) + "px";
344
- exporter_container.style.top = trigger_position[1] + "px";
343
+ exporter_container.style.left = (trigger_position[0] - 240) + "px";
344
+ exporter_container.style.top = (trigger_position[1] - 32) + "px";
345
345
  Wf.Effects.appear("wf_exporter");
346
346
  }
347
347
  });
@@ -1,5 +1,5 @@
1
1
  /****************************************************************************
2
- Copyright (c) 2010-2011 Michael Berkovich
2
+ # Copyright (c) 2010-2012 Michael Berkovich
3
3
 
4
4
  Permission is hereby granted, free of charge, to any person obtaining
5
5
  a copy of this software and associated documentation files (the
@@ -5,62 +5,85 @@
5
5
  }
6
6
 
7
7
  @mixin shadow($info) {
8
- box-shadow:$info;
9
- -moz-box-shadow:$info;
10
- -webkit-box-shadow:$info;
8
+ box-shadow:$info;
9
+ -moz-box-shadow:$info;
10
+ -webkit-box-shadow:$info;
11
+ }
12
+
13
+ .wf_exporter_header {
14
+ font-size:12px;
15
+ font-weight:bold;
16
+ margin:0 10px;
17
+
18
+ .close {
19
+ text-decoration:none;
20
+ font-size:18px;
21
+ color:#888;
22
+ &:hover { color:#222;}
23
+ }
11
24
  }
12
25
 
13
26
  .wf_exporter {
14
- background-color:#eee;
15
- position:absolute;
16
- width:230px;
17
- padding: 5px;
18
- font-size:10px;
19
- border:solid 1px #e8e8e8;
20
- border-color:#e8e8e8 #bababa #bababa #e8e8e8;
21
- @include rounded-corners(10px);
22
- @include shadow(2px 3px 3px 2px rgba(0,0,0,0.6));
27
+ background-color:#eee;
28
+ position:absolute;
29
+ width:230px;
30
+ padding: 5px;
31
+ font-size:10px;
32
+ border:solid 1px #e8e8e8;
33
+ border-color:#e8e8e8 #bababa #bababa #e8e8e8;
34
+ @include rounded-corners(10px);
35
+ @include shadow(2px 3px 3px 2px rgba(0,0,0,0.6));
36
+
37
+ img {
38
+ border: 0px;
39
+ }
40
+
41
+ input {
42
+ border: 1px solid #ccc;
43
+ font-size: 12px;
44
+ font-family: Arial;
45
+ @include rounded-corners(10px);
46
+ }
23
47
 
24
- img {
25
- border: 0px;
26
- }
48
+ select {
49
+ border: 1px solid #ccc;
50
+ font-size: 12px;
51
+ font-family: Arial;
52
+ background-color:#EDEDED;
53
+ @include rounded-corners(10px);
54
+ }
27
55
 
28
- input {
29
- border: 1px solid #ccc;
30
- font-size: 12px;
31
- font-family: Arial;
32
- @include rounded-corners(10px);
33
- }
34
-
35
- select {
36
- border: 1px solid #ccc;
37
- font-size: 12px;
38
- font-family: Arial;
39
- background-color:#EDEDED;
40
- @include rounded-corners(10px);
41
- }
56
+ table {
57
+ width:100%;
58
+ border-collapse: collapse;
59
+ font-size:12px;
60
+ padding:0px;
61
+ margin:0px;
62
+
63
+ thead tr {
64
+ border-bottom:1px solid #bababa;
65
+ font-weight:bold;
66
+ }
67
+
68
+ td {
69
+ vertical-align:top;
70
+ padding: 0px;
71
+ margin: 0px;
72
+ }
73
+
74
+ }
75
+
76
+ .center { padding-bottom: 5px;}
42
77
 
43
- table {
44
- width:100%;
45
- border-collapse: collapse;
46
- font-size:12px;
47
- padding:0px;
48
- margin:0px;
49
- }
50
-
51
- td {
52
- vertical-align:top;
53
- padding: 0px;
54
- margin: 0px;
55
- }
56
78
  }
57
79
 
58
80
  .wf_exporter_container {
59
- background-color:white;
60
- padding: 5px;
61
- margin: 5px;
62
- font-size:10px;
63
- border:solid 1px #bababa;
64
- border-color:#bababa #e8e8e8 #e8e8e8 #bababa;
65
- @include rounded-corners(10px);
81
+ background-color:white;
82
+ padding: 5px;
83
+ margin: 5px;
84
+ font-size:10px;
85
+ border:solid 1px #bababa;
86
+ border-color:#bababa #e8e8e8 #e8e8e8 #bababa;
87
+ @include rounded-corners(10px);
66
88
  }
89
+
@@ -166,6 +166,7 @@
166
166
 
167
167
  .end {float:right;}
168
168
  .begin {float:left;}
169
+ .center {text-align:center;}
169
170
  .full_width {width:100%;}
170
171
 
171
172
  .boolean_container {
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2010-2011 Michael Berkovich
2
+ # Copyright (c) 2010-2012 Michael Berkovich
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining
5
5
  # a copy of this software and associated documentation files (the
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2010-2011 Michael Berkovich
2
+ # Copyright (c) 2010-2012 Michael Berkovich
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining
5
5
  # a copy of this software and associated documentation files (the
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2010-2011 Michael Berkovich
2
+ # Copyright (c) 2010-2012 Michael Berkovich
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining
5
5
  # a copy of this software and associated documentation files (the
@@ -32,7 +32,7 @@ module WillFilter
32
32
 
33
33
  def export
34
34
  params[:page] = 1
35
- params[:per_page] = 10000 # mas export limit
35
+ params[:wf_per_page] = 10000 # max export limit
36
36
 
37
37
  @wf_filter = WillFilter::Filter.deserialize_from_params(params)
38
38
 
@@ -62,38 +62,27 @@ module WillFilter
62
62
  end
63
63
 
64
64
  private
65
-
66
- def send_xml_data(wf_filter)
67
- class_name = wf_filter.model_class_name.underscore
68
-
69
- result = ""
70
- xml = Builder::XmlMarkup.new(:target => result, :indent => 1)
71
- xml.instruct!
72
- xml.tag!(class_name.pluralize) do
73
- wf_filter.results.each do |obj|
74
- xml.tag!(class_name.underscore) do
75
- wf_filter.fields.each do |field|
76
- xml.tag!(field.to_s, obj.send(field).to_s)
77
- end
78
- end
79
- end
80
- end
81
-
82
- send_data(result, :type => 'text/xml', :charset => 'utf-8')
83
- end
84
-
85
- def send_json_data(wf_filter)
86
- result = []
65
+
66
+ def results_from(wf_filter)
67
+ results = []
87
68
 
88
69
  wf_filter.results.each do |obj|
89
70
  hash = {}
90
71
  wf_filter.fields.each do |field|
91
72
  hash[field] = obj.send(field).to_s
92
73
  end
93
- result << hash
74
+ results << hash
94
75
  end
95
76
 
96
- send_data(result.to_json, :type => 'text', :charset => 'utf-8')
77
+ results
78
+ end
79
+
80
+ def send_xml_data(wf_filter)
81
+ send_data(results_from(wf_filter).to_xml, :type => 'text/xml', :charset => 'utf-8')
82
+ end
83
+
84
+ def send_json_data(wf_filter)
85
+ send_data(results_from(wf_filter).to_json, :type => 'text', :charset => 'utf-8')
97
86
  end
98
87
 
99
88
  def send_csv_data(wf_filter)
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2010-2011 Michael Berkovich
2
+ # Copyright (c) 2010-2012 Michael Berkovich
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining
5
5
  # a copy of this software and associated documentation files (the
@@ -64,6 +64,8 @@ module WillFilter
64
64
  end
65
65
 
66
66
  def save_filter
67
+ raise WillFilter::FilterException.new("Saving functions are disabled") unless WillFilter::Config.saving_enabled?
68
+
67
69
  params.delete(:wf_id)
68
70
 
69
71
  wf_filter = WillFilter::Filter.deserialize_from_params(params)
@@ -79,6 +81,8 @@ module WillFilter
79
81
  end
80
82
 
81
83
  def update_filter
84
+ raise WillFilter::FilterException.new("Update functions are disabled") unless WillFilter::Config.saving_enabled?
85
+
82
86
  wf_filter = WillFilter::Filter.find_by_id(params.delete(:wf_id))
83
87
  wf_filter.deserialize_from_params(params)
84
88
  wf_filter.validate!
@@ -93,6 +97,8 @@ module WillFilter
93
97
  end
94
98
 
95
99
  def delete_filter
100
+ raise WillFilter::FilterException.new("Delete functions are disabled") unless WillFilter::Config.saving_enabled?
101
+
96
102
  wf_filter = WillFilter::Filter.find_by_id(params[:wf_id])
97
103
  wf_filter.destroy if wf_filter
98
104
 
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2010-2011 Michael Berkovich
2
+ # Copyright (c) 2010-2012 Michael Berkovich
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining
5
5
  # a copy of this software and associated documentation files (the
@@ -33,6 +33,11 @@ module WillFilter
33
33
  #############################################################################
34
34
  def initialize(model_class)
35
35
  super()
36
+
37
+ if WillFilter::Config.require_filter_extensions? and self.class.name == "WillFilter::Filter"
38
+ raise WillFilter::FilterException.new("Your configuration requires you to subclass the filter. Default filter cannot be created.")
39
+ end
40
+
36
41
  self.model_class_name = model_class.to_s
37
42
  end
38
43
 
@@ -378,6 +383,7 @@ module WillFilter
378
383
  #############################################################################
379
384
  def self.deserialize_from_params(params)
380
385
  params = HashWithIndifferentAccess.new(params) unless params.is_a?(HashWithIndifferentAccess)
386
+
381
387
  params[:wf_type] = self.name unless params[:wf_type]
382
388
  params[:wf_type].constantize.new(params[:wf_model]).deserialize_from_params(params)
383
389
  end
@@ -476,14 +482,15 @@ module WillFilter
476
482
  # SQL Conditions
477
483
  #############################################################################
478
484
  def sql_conditions
479
- @sql_conditions ||= begin
480
-
485
+ @sql_conditions ||= begin
481
486
  if errors?
482
- all_sql_conditions = [" 1 = 2 "]
487
+ [" 1 = 2 "]
483
488
  else
484
489
  all_sql_conditions = [""]
485
490
  0.upto(size - 1) do |index|
486
491
  condition = condition_at(index)
492
+ next if custom_condition?(condition)
493
+
487
494
  sql_condition = condition.container.sql_condition
488
495
 
489
496
  unless sql_condition
@@ -493,15 +500,17 @@ module WillFilter
493
500
  if all_sql_conditions[0].size > 0
494
501
  all_sql_conditions[0] << ( match.to_sym == :all ? " AND " : " OR ")
495
502
  end
496
-
503
+
497
504
  all_sql_conditions[0] << sql_condition[0]
505
+
498
506
  sql_condition[1..-1].each do |c|
499
507
  all_sql_conditions << c
500
508
  end
509
+
501
510
  end
511
+
512
+ all_sql_conditions
502
513
  end
503
-
504
- all_sql_conditions
505
514
  end
506
515
  end
507
516
 
@@ -547,7 +556,7 @@ module WillFilter
547
556
  if include_default
548
557
  filters = default_filters
549
558
  if (filters.size > 0)
550
- filters.insert(0, ["-- Select Default Filter --", "-1"])
559
+ filters.insert(0, ["Select default filter", "-1"])
551
560
  end
552
561
  end
553
562
 
@@ -569,7 +578,7 @@ module WillFilter
569
578
  user_filters = WillFilter::Filter.find(:all, :conditions => conditions)
570
579
 
571
580
  if user_filters.size > 0
572
- filters << ["-- Select Saved Filter --", "-2"] if include_default
581
+ filters << ["Select saved filter", "-2"] if include_default
573
582
 
574
583
  user_filters.each do |filter|
575
584
  filters << [filter.name, filter.id.to_s]
@@ -638,12 +647,12 @@ module WillFilter
638
647
  #############################################################################
639
648
  def export_formats
640
649
  formats = []
641
- formats << ["-- Generic Formats --", -1]
650
+ formats << ["Generic formats", -1]
642
651
  WillFilter::Config.default_export_formats.each do |frmt|
643
652
  formats << [frmt, frmt]
644
653
  end
645
654
  if custom_formats.size > 0
646
- formats << ["-- Custom Formats --", -2]
655
+ formats << ["Custom formats", -2]
647
656
  custom_formats.each do |frmt|
648
657
  formats << frmt
649
658
  end
@@ -683,7 +692,49 @@ module WillFilter
683
692
  "INNER JOIN #{join_table_name} ON #{join_table_name}.id = #{table_name}.#{join_on_field}"
684
693
  end
685
694
  end
686
-
695
+
696
+ # overload this method to indicate which conditions are custom
697
+ def custom_conditions
698
+ []
699
+ end
700
+
701
+ # overload this method to evaluate a custom condition on an object
702
+ def custom_condition_met?(condition, object)
703
+ false
704
+ end
705
+
706
+ def custom_condition?(condition)
707
+ custom_conditions.include?(condition.key)
708
+ end
709
+
710
+ def custom_conditions?
711
+ return if custom_conditions.empty?
712
+ conditions.each do |condition|
713
+ return true if custom_condition?(condition)
714
+ end
715
+ end
716
+
717
+ def process_custom_conditions(objects)
718
+ filtered = []
719
+ objects.each do |obj|
720
+ condition_flags = []
721
+
722
+ 0.upto(size - 1) do |index|
723
+ condition = condition_at(index)
724
+ next unless custom_condition?(condition)
725
+ condition_flags << custom_condition_met?(condition, obj)
726
+ end
727
+
728
+ if condition_flags.size > 0
729
+ next if match.to_s == "all" and condition_flags.include?(false)
730
+ next unless condition_flags.include?(true)
731
+ end
732
+
733
+ filtered << obj
734
+ end
735
+ filtered
736
+ end
737
+
687
738
  def results
688
739
  @results ||= begin
689
740
  handle_empty_filter!
@@ -691,6 +742,12 @@ module WillFilter
691
742
  inner_joins.each do |inner_join|
692
743
  recs = recs.joins(association_name(inner_join))
693
744
  end
745
+
746
+ if custom_conditions?
747
+ recs = process_custom_conditions(recs.all)
748
+ recs = Kaminari.paginate_array(recs)
749
+ end
750
+
694
751
  recs = recs.page(page).per(per_page)
695
752
  recs.wf_filter = self
696
753
  recs