filterrific 1.4.3 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dfb96075da4c30641cdfb5fdf747706a310f0324
4
- data.tar.gz: fc4f107545fa2838949eb88be2b0beee14927d14
3
+ metadata.gz: 5771d0552efaa97955d18305f8199f7691148d93
4
+ data.tar.gz: 037e7d5b634f6183cd6315d35cdd5a8874c47f3c
5
5
  SHA512:
6
- metadata.gz: 32d36a46d02d7fd55951b41c05e54022696dcccee1cb184fdf6da63bf469104e8279141a7fd620a4dbb49a24c8f579a58a4646963ef632f3672f75c8478d95b2
7
- data.tar.gz: 1d427b2a134182022656d1ef5cc3347e2c3f05d9fdcb4bb81cb8d8ad15a1f0cac7e6266f73670dd979df1afa30433e4ba93ca1ef380837a41ef4f79fa6f0c372
6
+ metadata.gz: 6da890161d37d8884debfff82b057f1fe304ebcf858b6a0493cc756739428cc33fdc131abd0f174fd4ea449704404adc10204c33fa22d89b96c623001aefdafc
7
+ data.tar.gz: 192de17ea6192932f6e6c262fa6888fa35b39188ec0c99dcaf76bedd94434671f2754968ac4e9cc0fad8d2fc461c95dbb122e1b11074afc7fe1567b46920258d
data/CHANGELOG.md CHANGED
@@ -1,12 +1,10 @@
1
- # 2.0.0
2
-
3
- API changes
4
-
5
- * Filterrific can build the `sorted_by` and `search_query` scopes automatically,
6
- based on some configuration in the including model.
7
-
1
+ * using the "sorted_by" magic method will add entries to select_options automatically
8
2
  filterrific(
9
- default_settings: { sorted_by: 'name_asc' },
3
+ default_filter_params: { sorted_by: 'name_asc' },
4
+ available_filters: [
5
+ :with_country,
6
+ ...
7
+ ],
10
8
  search_query: {
11
9
  match_terms: :any, # [:all]
12
10
  auto_wildcard: :suffix, # [:prefix, :both, :none]
@@ -17,39 +15,56 @@ API changes
17
15
  name_asc: 'Name (A-Z)',
18
16
  name_desc: 'Name (Z-A)',
19
17
  },
20
- scopes: [
18
+ )
19
+
20
+ filterrific(
21
+ default_filter_params: { sorted_by: 'name_asc' },
22
+ custom_scopes: [
21
23
  :with_country,
22
24
  ...
25
+ ],
26
+ lookup_filters: [ # column_value_filters:, value_filters:
27
+ :with_country_id,
28
+ :with_state,
23
29
  ]
30
+ search_query: {
31
+ match_terms: :any, # [:all]
32
+ auto_wildcard: :suffix, # [:prefix, :both, :none]
33
+ columns: [:first_name, :email, :last_name],
34
+ case_sensitive: false, # [true]
35
+ },
36
+ sorted_by: {
37
+ name_asc: 'Name (A-Z)',
38
+ name_desc: 'Name (Z-A)',
39
+ },
24
40
  )
25
41
 
26
- * Filterrific can handle persistence of search params in session for you.
27
- * Simplified `@filterrific.find` method to load collection from DB.
28
- Replaces `Student.filterrific_find(@filterrific)`
29
42
 
30
- @filterrific = initialize_filterrific(
31
- Student,
32
- default_settings: {},
33
- filter_names: [],
34
- params_key: :filterrific,
35
- select_options: {},
36
- session_persistence_key: 'asdf',
37
- )
38
- @students = @filterrific.find
39
43
 
40
- * The filterrific form builder now doesn't override the standard
41
- `form_for` method. It is used via `form_for_filterrific` instead:
44
+ # 2.0.0
42
45
 
43
- form_for_filterrific @filterrific do |f|
46
+ API changes:
44
47
 
48
+ * Filterrific model API option names have changed.
49
+ * Better initialization of Filterrific via `initialize_filterrific` method:
50
+ * It resets the filter params, so the `reset_filterrific` action is not required any more.
51
+ * It persists filter params in session.
52
+ * Simplified `@filterrific.find` method to load collection from DB.
53
+ Replaces `Student.filterrific_find(@filterrific)`
54
+ * The `form_for_filterrific` form builder doesn't override the standard
55
+ `form_for` method any more.
45
56
  * Dropped support for Ruby 1.8.7 (because of 1.9 Hash syntax)
46
57
  * Dropped support for Rails <= 3.0.0 (because of ActiveRecord
47
58
  bug fixes in 3.1, and use of asset pipeline)
48
59
 
60
+
61
+
49
62
  ### 1.4.3
50
63
 
51
64
  * Handle case where Filterrific filter params are empty.
52
65
 
66
+
67
+
53
68
  ### 1.4.2
54
69
 
55
70
  * Updated initialization of ActiveRecord and ActionView extensions again
data/README.md CHANGED
@@ -13,8 +13,6 @@ search, and sort your ActiveRecord lists:
13
13
  Make sure to go to the fantastic [Filterrific documentation](http://filterrific.clearcove.ca)
14
14
  to find out more!
15
15
 
16
- TODO: look at Jeff's email suggestions (June 23, 2014)
17
-
18
16
  ### Installation
19
17
 
20
18
  `gem install filterrific`
@@ -28,11 +26,11 @@ or with bundler in your Gemfile:
28
26
 
29
27
  Every commit to Filterrific is automatically tested against the following scenarios:
30
28
 
31
- | Rails version | Ruby environments | Database adapters | Build status |
32
- |---------------|-------------------------|------------------------------------|--------------|
33
- | Rails 4.1 | MRI 1.9.3, 2.0.0, 2.1.2 | mysql, mysql2, postgresql, sqlite3 |[![Build Status](https://travis-ci.org/jhund/filterrific_demo.svg?branch=rails-4.1)](https://travis-ci.org/jhund/filterrific_demo)|
34
- | Rails 4.0 | MRI 1.9.3, 2.0.0, 2.1.2 | mysql, mysql2, postgresql, sqlite3 |[![Build Status](https://travis-ci.org/jhund/filterrific_demo.svg?branch=rails-4.0)](https://travis-ci.org/jhund/filterrific_demo)|
35
- | Rails 3.2 | MRI 1.9.3, 2.0.0, 2.1.2 | mysql, mysql2, postgresql, sqlite3 |[![Build Status](https://travis-ci.org/jhund/filterrific_demo.svg?branch=rails-3.2)](https://travis-ci.org/jhund/filterrific_demo)|
29
+ | Rails version | Ruby environments | Database adapters | Build status |
30
+ |---------------|--------------------------------|------------------------------------|--------------|
31
+ | Rails 4.1 | MRI 1.9.3, 2.0.0, 2.1.2, 2.2.0 | mysql, mysql2, postgresql, sqlite3 |[![Build Status](https://travis-ci.org/jhund/filterrific_demo.svg?branch=rails-4.1)](https://travis-ci.org/jhund/filterrific_demo)|
32
+ | Rails 4.0 | MRI 1.9.3, 2.0.0, 2.1.2, 2.2.0 | mysql, mysql2, postgresql, sqlite3 |[![Build Status](https://travis-ci.org/jhund/filterrific_demo.svg?branch=rails-4.0)](https://travis-ci.org/jhund/filterrific_demo)|
33
+ | Rails 3.2 | MRI 1.9.3, 2.0.0, 2.1.2 | mysql, mysql2, postgresql, sqlite3 |[![Build Status](https://travis-ci.org/jhund/filterrific_demo.svg?branch=rails-3.2)](https://travis-ci.org/jhund/filterrific_demo)|
36
34
 
37
35
  Filterrific version 1.4.0 should work on older versions of Rails and Ruby, however
38
36
  the 1.x branch is not supported any more.
@@ -65,6 +63,12 @@ I'm happy to help you if you encounter problems when using filterrific. You'll m
65
63
 
66
64
  [![Code Climate](https://codeclimate.com/github/jhund/filterrific.png)](https://codeclimate.com/github/jhund/filterrific)
67
65
 
66
+ ### Related projects
67
+
68
+ * has_scope
69
+ * http://www.justinweiss.com/blog/2014/02/17/search-and-filter-rails-models-without-bloating-your-controller/
70
+ * https://github.com/laserlemon/periscope
71
+
68
72
  ### License
69
73
 
70
74
  [MIT licensed](https://github.com/jhund/filterrific/blob/master/MIT-LICENSE).
data/lib/filterrific.rb CHANGED
@@ -1,11 +1,7 @@
1
+ # -*- coding: utf-8 -*-
2
+
1
3
  require 'filterrific/version'
2
4
  require 'filterrific/engine'
3
5
 
4
6
  module Filterrific
5
-
6
- # Wrapper around Filterrific::ParamSet initialization
7
- def self.new(a_resource_class, filterrific_params = {})
8
- Filterrific::ParamSet.new(a_resource_class, filterrific_params)
9
- end
10
-
11
7
  end
@@ -0,0 +1,58 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Adds Filterrific methods ActionController instances
4
+ #
5
+ module Filterrific
6
+ module ActionControllerExtension
7
+
8
+ protected
9
+
10
+ # @param model_class [Class]
11
+ # @param filterrific_params [Hash] typically the Rails request params under
12
+ # the :filterrific key (params[:filterrific]), however can be any Hash.
13
+ # @param opts [Hash]
14
+ # @option opts [Array<String>, optional] :available_filters
15
+ # further restrict which of the filters specified in the model are
16
+ # available in this context.
17
+ # @option opts [Hash, optional] :default_filter_params
18
+ # overrides the defaults specified in the model.
19
+ # @option opts [String, Symbol, optional] :persistence_id
20
+ # defaults to "namespace/controller#action" string, used for session key
21
+ # and saved searches to isolate different filters' persisted params from
22
+ # each other.
23
+ # @option opts [Hash, optional] :select_options
24
+ # these are available in the view to populate select lists and other
25
+ # dynamic values.
26
+ # @return [Filterrific::ParamSet]
27
+ def initialize_filterrific(model_class, filterrific_params, opts)
28
+ f_params = (filterrific_params || {}).deep_stringify_keys
29
+ opts = opts.stringify_keys
30
+ pi = opts['persistence_id'] || compute_default_persistence_id
31
+
32
+ if (f_params.delete('reset_filterrific'))
33
+ # Reset query and session_persisted params
34
+ session[pi] = nil
35
+ redirect_to url_for({}) and return false # works with `or return` in calling action.
36
+ end
37
+
38
+ f_params = f_params.presence || # start with passed in params
39
+ session[pi].presence || # then try session persisted params
40
+ opts['default_filter_params'] || # then use passed in opts
41
+ model_class.filterrific_default_filter_params # finally use model_class defaults
42
+
43
+ f_params.deep_stringify_keys!
44
+ f_params.slice!(opts['available_filters'].map(&:to_s)) if opts['available_filters']
45
+
46
+ filterrific = Filterrific::ParamSet.new(model_class, f_params)
47
+ filterrific.select_options = opts['select_options']
48
+ session[pi] = filterrific.to_hash
49
+ filterrific
50
+ end
51
+
52
+ # Computes a default persistence id based on controller and action name
53
+ def compute_default_persistence_id
54
+ [controller_name, action_name].join('#')
55
+ end
56
+
57
+ end
58
+ end
@@ -1,23 +1,25 @@
1
1
  # -*- coding: utf-8 -*-
2
-
3
2
  #
4
- # Adds view helpers to ActionView
3
+ # Adds Filterrific view helpers to ActionView instances
5
4
  #
6
5
  module Filterrific
7
6
  module ActionViewExtension
8
7
 
9
- # Sets all options on form_for to defaults if called with Filterrific object
10
- def form_for(record, options = {}, &block)
11
- if record.is_a?(Filterrific::ParamSet)
12
- options[:as] ||= :filterrific
13
- options[:html] ||= {}
14
- options[:html][:method] ||= :get
15
- options[:html][:id] ||= :filterrific_filter
16
- options[:url] ||= url_for(:controller => controller.controller_name, :action => controller.action_name)
17
- end
18
- super
8
+ # Sets all options on form_for to defaults that work with Filterrific
9
+ # @param record [Filterrific] the @filterrific object
10
+ # @param options [Hash] standard options for form_for
11
+ # @param block [Proc] the form body
12
+ def form_for_filterrific(record, options = {}, &block)
13
+ options[:as] ||= :filterrific
14
+ options[:html] ||= {}
15
+ options[:html][:method] ||= :get
16
+ options[:html][:id] ||= :filterrific_filter
17
+ options[:url] ||= url_for(
18
+ :controller => controller.controller_name,
19
+ :action => controller.action_name
20
+ )
21
+ form_for(record, options, &block)
19
22
  end
20
- # TODO: change this to form_for_filterrific!
21
23
 
22
24
  # Renders a spinner while the list is being updated
23
25
  def render_filterrific_spinner
@@ -27,36 +29,40 @@ module Filterrific
27
29
  </span>
28
30
  ).html_safe
29
31
  end
30
- #alias: filterrific_spinner
31
32
 
32
33
  # Renders a link which indicates the current sorting and which can be used to
33
34
  # toggle the list sorting (set column and direction).
35
+ #
34
36
  # NOTE: Make sure that this is used in the list partial that is re-rendered
35
37
  # when the filterrific params are changed, so that the filterrific params in
36
38
  # the URL are always current.
37
- # @param[Filterrific::ParamSet] filterrific the current filterrific instance
38
- # @param[String, Symbol] sort_key the key to sort by, without direction.
39
+ #
40
+ # NOTE: Currently the filterrific_sorting_link is not synchronized with a
41
+ # SELECT input you may have in the filter form for sorting. We recommend you
42
+ # use one or the other to avoid conflicting sort settings in the UI.
43
+ #
44
+ # @param filterrific [Filterrific::ParamSet] the current filterrific instance
45
+ # @param sort_key [String, Symbol] the key to sort by, without direction.
39
46
  # Example: 'name', 'created_at'
40
- # @param[Hash, optional] options:
41
- # * active_column_class: CSS class applied to current sort column.
42
- # Default: 'filterrific_current_sort_column'
43
- # * ascending_indicator: HTML string to indicate ascending sort direction.
44
- # Default: Triangle pointing up.
45
- # * default_sort_direction: override the default sorting when selecting
46
- # a new sort column. Default: 'asc'.
47
- # * descending_indicator: HTML string to indicate descending sort direction.
48
- # Default: Triangle pointing down.
49
- # * html_attrs: HTML attributes to be added to the sorting link. Default: {}
50
- # * label: override label. Default: `sort_key.humanize`.
51
- # * sorting_scope_name: override the name of the scope used for sorting.
52
- # Default: `:sorted_by`
53
- # * url_for_attrs: override the target URL attributes to be used for `url_for`.
54
- # Default: {} (current URL).
55
- # TODO: update documentation
56
- # TODO: update demo app
57
- # TODO: synchronize with sorting select in filter
58
- def filterrific_sorting_link(filterrific, sort_key, options = {})
59
- options = {
47
+ # @param opts [Hash, optional]
48
+ # @options opts [String, optional] active_column_class
49
+ # CSS class applied to current sort column. Default: 'filterrific_current_sort_column'
50
+ # @options opts [String, optional] ascending_indicator
51
+ # HTML string to indicate ascending sort direction. Default: '⬆'
52
+ # @options opts [String, optional] default_sort_direction
53
+ # Override the default sorting when selecting a new sort column. Default: 'asc'.
54
+ # @options opts [String, optional] descending_indicator
55
+ # HTML string to indicate descending sort direction. Default: '⬇'
56
+ # @options opts [Hash, optional] html_attrs
57
+ # HTML attributes to be added to the sorting link. Default: {}
58
+ # @options opts [String, optional] label
59
+ # Override label. Default: `sort_key.to_s.humanize`.
60
+ # @options opts [String, Symbol, optional] sorting_scope_name
61
+ # Override the name of the scope used for sorting. Default: :sorted_by
62
+ # @options opts [Hash, optional] url_for_attrs
63
+ # Override the target URL attributes to be used for `url_for`. Default: {} (current URL).
64
+ def filterrific_sorting_link(filterrific, sort_key, opts = {})
65
+ opts = {
60
66
  :active_column_class => 'filterrific_current_sort_column',
61
67
  :inactive_column_class => 'filterrific_sort_column',
62
68
  :ascending_indicator => '⬆',
@@ -66,52 +72,82 @@ module Filterrific
66
72
  :label => sort_key.to_s.humanize,
67
73
  :sorting_scope_name => :sorted_by,
68
74
  :url_for_attrs => {},
69
- }.merge(options)
70
- options[:html_attrs] = options[:html_attrs].with_indifferent_access
71
- current_sorting = filterrific.send(options[:sorting_scope_name])
72
- current_sort_key = current_sorting ? current_sorting.gsub(/_asc|_desc/, '') : nil
73
- current_sort_direction = current_sorting ? (current_sorting =~ /_desc\z/ ? 'desc' : 'asc') : nil
75
+ }.merge(opts)
76
+ opts.merge!(
77
+ :html_attrs => opts[:html_attrs].with_indifferent_access,
78
+ :current_sorting => filterrific.send(opts[:sorting_scope_name]),
79
+ :current_sort_key => current_sorting ? current_sorting.gsub(/_asc|_desc/, '') : nil,
80
+ :current_sort_direction => current_sorting ? (current_sorting =~ /_desc\z/ ? 'desc' : 'asc') : nil,
81
+ )
74
82
  new_sort_key = sort_key.to_s
75
- if new_sort_key == current_sort_key
76
- # current sort column, toggle search_direction
77
- new_sort_direction, current_sort_direction_indicator = if 'asc' == current_sort_direction
78
- ['desc', options[:ascending_indicator]]
79
- else
80
- ['asc', options[:descending_indicator]]
81
- end
82
- new_sorting = [new_sort_key, new_sort_direction].join('_')
83
- css_classes = [
84
- options[:active_column_class],
85
- options[:html_attrs].delete(:class)
86
- ].compact.join(' ')
87
- new_filterrific_params = filterrific.to_hash
88
- .with_indifferent_access
89
- .merge(options[:sorting_scope_name] => new_sorting)
90
- url_for_attrs = options[:url_for_attrs].merge(:filterrific => new_filterrific_params)
91
- link_to(
92
- [options[:label], current_sort_direction_indicator].join(' '),
93
- url_for(url_for_attrs),
94
- options[:html_attrs].reverse_merge(:class => css_classes, :method => :get, :remote => true)
95
- )
83
+ if new_sort_key == opts[:current_sort_key]
84
+ # same sort column, reverse order
85
+ filterrific_sorting_link_reverse_order(filterrific, new_sort_key, opts)
96
86
  else
97
- # new sort column, change sort column
98
- new_sort_direction = options[:default_sort_direction]
99
- new_sorting = [new_sort_key, new_sort_direction].join('_')
100
- css_classes = [
101
- options[:inactive_column_class],
102
- options[:html_attrs].delete(:class)
103
- ].compact.join(' ')
104
- new_filterrific_params = filterrific.to_hash
105
- .with_indifferent_access
106
- .merge(options[:sorting_scope_name] => new_sorting)
107
- url_for_attrs = options[:url_for_attrs].merge(:filterrific => new_filterrific_params)
108
- link_to(
109
- options[:label],
110
- url_for(url_for_attrs),
111
- options[:html_attrs].reverse_merge(:class => css_classes, :method => :get, :remote => true)
112
- )
87
+ # new sort column, default sort order
88
+ filterrific_sorting_link_new_column(filterrific, new_sort_key, opts)
113
89
  end
114
90
  end
115
91
 
92
+ # Returns a url that can be used to reset the Filterrific params
93
+ def reset_filterrific_url(opts = {})
94
+ url_for(
95
+ { filterrific: { reset_filterrific: true } }.merge(opts)
96
+ )
97
+ end
98
+
99
+ protected
100
+
101
+ # Renders HTML to reverse sort order on currently sorted column.
102
+ # @param filterrific [Filterrific::ParamSet]
103
+ # @param new_sort_key [String]
104
+ # @param opts [Hash]
105
+ # @return [String] an HTML fragment
106
+ def filterrific_sorting_link_reverse_order(filterrific, new_sort_key, opts)
107
+ # current sort column, toggle search_direction
108
+ new_sort_direction, current_sort_direction_indicator = if 'asc' == opts[:current_sort_direction]
109
+ ['desc', opts[:ascending_indicator]]
110
+ else
111
+ ['asc', opts[:descending_indicator]]
112
+ end
113
+ new_sorting = [new_sort_key, new_sort_direction].join('_')
114
+ css_classes = [
115
+ opts[:active_column_class],
116
+ opts[:html_attrs].delete(:class)
117
+ ].compact.join(' ')
118
+ new_filterrific_params = filterrific.to_hash
119
+ .with_indifferent_access
120
+ .merge(opts[:sorting_scope_name] => new_sorting)
121
+ url_for_attrs = opts[:url_for_attrs].merge(:filterrific => new_filterrific_params)
122
+ link_to(
123
+ [opts[:label], opts[:current_sort_direction_indicator]].join(' '),
124
+ url_for(url_for_attrs),
125
+ opts[:html_attrs].reverse_merge(:class => css_classes, :method => :get, :remote => true)
126
+ )
127
+ end
128
+
129
+ # Renders HTML to sort by a new column.
130
+ # @param filterrific [Filterrific::ParamSet]
131
+ # @param new_sort_key [String]
132
+ # @param opts [Hash]
133
+ # @return [String] an HTML fragment
134
+ def filterrific_sorting_link_new_column(filterrific, new_sort_key, opts)
135
+ new_sort_direction = opts[:default_sort_direction]
136
+ new_sorting = [new_sort_key, new_sort_direction].join('_')
137
+ css_classes = [
138
+ opts[:inactive_column_class],
139
+ opts[:html_attrs].delete(:class)
140
+ ].compact.join(' ')
141
+ new_filterrific_params = filterrific.to_hash
142
+ .with_indifferent_access
143
+ .merge(opts[:sorting_scope_name] => new_sorting)
144
+ url_for_attrs = opts[:url_for_attrs].merge(:filterrific => new_filterrific_params)
145
+ link_to(
146
+ opts[:label],
147
+ url_for(url_for_attrs),
148
+ opts[:html_attrs].reverse_merge(:class => css_classes, :method => :get, :remote => true)
149
+ )
150
+ end
151
+
116
152
  end
117
153
  end
@@ -1,51 +1,58 @@
1
+ # -*- coding: utf-8 -*-
1
2
  #
2
- # Adds filterrific methods to ActiveRecord::Base and sub classes.
3
+ # Adds Filterrific methods to ActiveRecord::Base model_class.
3
4
  #
4
5
  require 'filterrific/param_set'
5
6
 
6
7
  module Filterrific
7
8
  module ActiveRecordExtension
8
9
 
9
- # Adds filterrific behavior to class when called like so:
10
+ # Adds Filterrific behavior to class when called like so:
10
11
  #
11
12
  # filterrific(
12
- # :default_settings => { :sorted_by => "created_at_asc" },
13
- # :filter_names => [:sorted_by, :search_query, :with_state]
13
+ # :available_filters => [:sorted_by, :search_query, :with_state]
14
+ # :default_filter_params => { :sorted_by => "created_at_asc" },
14
15
  # )
15
16
  #
16
- # @params[Hash] options
17
- # Required keys are:
18
- # * :filter_names: a list of filter_names to be exposed by Filterrific
19
- # Optional keys are:
20
- # * :default_settings: default filter settings
21
- def filterrific(options)
22
- cattr_accessor :filterrific_default_settings
23
- cattr_accessor :filterrific_filter_names
24
-
25
- options.stringify_keys!
26
-
27
- assign_filterrific_filter_names(options)
28
- validate_filterrific_filter_names
29
- assign_filterrific_default_settings(options)
30
- validate_filterrific_default_settings
17
+ # @params opts [Hash] with either string or symbol keys, will be stringified.
18
+ # @option opts [Array<String, Symbol>] available_filters: a list of filters to be exposed by Filterrific.
19
+ # @option opts [Hash, optional] default_filter_params: default filter parameters
20
+ # @return [void]
21
+ def filterrific(opts)
22
+ cattr_accessor :filterrific_available_filters
23
+ cattr_accessor :filterrific_default_filter_params
24
+ self.filterrific_available_filters = []
25
+
26
+ opts.stringify_keys!
27
+
28
+ define_sorted_by_scope(opts['sorted_by']) if opts['sorted_by']
29
+ #define_search_query_scope(opts['search_query']) if opts['search_query']
30
+
31
+ assign_filterrific_available_filters(opts)
32
+ validate_filterrific_available_filters
33
+ assign_filterrific_default_filter_params(opts)
34
+ validate_filterrific_default_filter_params
35
+
31
36
  end
32
37
 
33
- # Returns ActiveRecord relation based on given filterrific_param_set.
34
- # Use like so:
35
- # ModelClass.filterrific_find(@filterrific_param_set)
38
+ # Returns ActiveRecord relation based on filterrific_param_set.
39
+ # Use like so: `ModelClass.filterrific_find(@filterrific)`
36
40
  #
37
- # @param[Filterrific::ParamSet] filterrific_param_set
38
- # @return[ActiveRecord::Relation] an ActiveRecord relation.
41
+ # @param filterrific_param_set [Filterrific::ParamSet]
42
+ # @return [ActiveRecord::Relation] with filters applied
39
43
  def filterrific_find(filterrific_param_set)
40
44
  unless filterrific_param_set.is_a?(Filterrific::ParamSet)
41
- raise(ArgumentError, "Invalid Filterrific::ParamSet: #{ filterrific_param_set.inspect }")
45
+ raise(
46
+ ArgumentError,
47
+ "Invalid Filterrific::ParamSet: #{ filterrific_param_set.inspect }"
48
+ )
42
49
  end
43
50
 
44
- # initialize active record relation
45
- ar_rel = if ::ActiveRecord::Relation === self
51
+ # Initialize ActiveRecord::Relation
52
+ ar_rel = if ActiveRecord::Relation === self
46
53
  # self is already an ActiveRecord::Relation, use as is
47
54
  self
48
- elsif 3 >= Rails::VERSION::MAJOR
55
+ elsif Rails::VERSION::MAJOR <= 3
49
56
  # Active Record 3: send `:scoped` to class to get an ActiveRecord::Relation
50
57
  scoped
51
58
  else
@@ -53,8 +60,8 @@ module Filterrific
53
60
  all
54
61
  end
55
62
 
56
- # apply filterrific params
57
- self.filterrific_filter_names.each do |filter_name|
63
+ # Apply filterrific params
64
+ filterrific_available_filters.each do |filter_name|
58
65
  filter_param = filterrific_param_set.send(filter_name)
59
66
  next if filter_param.blank? # skip blank filter_params
60
67
  ar_rel = ar_rel.send(filter_name, filter_param)
@@ -65,29 +72,42 @@ module Filterrific
65
72
 
66
73
  protected
67
74
 
68
- def assign_filterrific_filter_names(options)
69
- self.filterrific_filter_names = (
70
- options['filter_names'] || options['scope_names'] || []
71
- ).map { |e| e.to_s }
75
+ # Defines a :sorted_by scope based on attrs
76
+ # @param attrs [Hash] with keys as
77
+ def define_sorted_by_scope(attrs)
78
+ scope :sorted_by, lambda {}
72
79
  end
73
80
 
74
- def validate_filterrific_filter_names
75
- # Raise exception if not filter_names are given
76
- raise(ArgumentError, ":filter_names can't be empty") if filterrific_filter_names.blank?
81
+ # Assigns available filters.
82
+ # @param opts [Hash] the complete options hash passed to `filterrific`.
83
+ # This method uses the 'available_filters', 'sorted_by', and 'search_query' keys.
84
+ # @return [void]
85
+ def assign_filterrific_available_filters(opts)
86
+ self.filterrific_available_filters = (
87
+ filterrific_available_filters + (opts['available_filters'] || [])
88
+ ).map(&:to_s).uniq.sort
89
+ end
90
+
91
+ # Validates presence of at least one available filter.
92
+ # @return [void]
93
+ def validate_filterrific_available_filters
94
+ if filterrific_available_filters.blank?
95
+ raise(ArgumentError, ":available_filters can't be empty")
96
+ end
77
97
  end
78
98
 
79
- def assign_filterrific_default_settings(options)
80
- self.filterrific_default_settings = (
81
- options['default_settings'] || options['defaults'] || {}
99
+ def assign_filterrific_default_filter_params(opts)
100
+ self.filterrific_default_filter_params = (
101
+ opts['default_filter_params'] || {}
82
102
  ).stringify_keys
83
103
  end
84
104
 
85
- def validate_filterrific_default_settings
86
- # Raise exception if defaults contain keys that are not present in filter_names
105
+ def validate_filterrific_default_filter_params
106
+ # Raise exception if defaults contain keys that are not present in available_filters
87
107
  if (
88
- invalid_defaults = (filterrific_default_settings.keys - filterrific_filter_names)
108
+ inv_fdfps = filterrific_default_filter_params.keys - filterrific_available_filters
89
109
  ).any?
90
- raise(ArgumentError, "Invalid default keys: #{ invalid_defaults.inspect }")
110
+ raise(ArgumentError, "Invalid default filter params: #{ inv_fdfps.inspect }")
91
111
  end
92
112
  end
93
113
 
@@ -1,4 +1,8 @@
1
+ # -*- coding: utf-8 -*-
2
+
1
3
  require 'filterrific/param_set'
4
+
5
+ require 'filterrific/action_controller_extension'
2
6
  require 'filterrific/action_view_extension'
3
7
  require 'filterrific/active_record_extension'
4
8
 
@@ -10,14 +14,18 @@ module Filterrific
10
14
 
11
15
  isolate_namespace Filterrific
12
16
 
13
- ActiveSupport.on_load :active_record do
14
- extend Filterrific::ActiveRecordExtension
17
+ ActiveSupport.on_load :action_controller do
18
+ include Filterrific::ActionControllerExtension
15
19
  end
16
20
 
17
21
  ActiveSupport.on_load :action_view do
18
22
  include Filterrific::ActionViewExtension
19
23
  end
20
24
 
25
+ ActiveSupport.on_load :active_record do
26
+ extend Filterrific::ActiveRecordExtension
27
+ end
28
+
21
29
  initializer "filterrific" do |app|
22
30
  app.config.assets.precompile += %w(filterrific-spinner.gif)
23
31
  end
@@ -1,3 +1,5 @@
1
+ # -*- coding: utf-8 -*-
2
+
1
3
  require 'active_support/all'
2
4
  require 'digest/sha1'
3
5
 
@@ -6,35 +8,44 @@ module Filterrific
6
8
  # FilterParamSet is a container to store FilterParams
7
9
  class ParamSet
8
10
 
9
- attr_accessor :resource_class
11
+ attr_accessor :model_class
10
12
  attr_accessor :select_options
11
13
 
12
- def initialize(a_resource_class, filterrific_params = {})
13
- self.resource_class = a_resource_class
14
+ # Initializes a new Filterrific::ParamSet. This is the core of Filterrific
15
+ # where all the action happens.
16
+ # @param a_model_class [Class] the class you want to filter records of
17
+ # @param filterrific_params [Hash, optional] the filter params, uses
18
+ # model_class' default_settings
19
+ # @return [Filterrific::ParamSet]
20
+ def initialize(a_model_class, filterrific_params = {})
21
+ self.model_class = a_model_class
14
22
  @select_options = {}
15
23
 
16
24
  # Use either passed in filterrific_params or resource class' default_settings.
17
25
  # Don't merge the hashes. This causes trouble if an option is set to nil
18
26
  # by the user, then it will be overriden by default_settings.
19
27
  # You might wonder "what if I want to change only one thing from the defaults?"
20
- # Persistence, baby. By the time you submit changes to one dimension, all the others
28
+ # Persistence, baby. By the time you submit changes to one filter, all the others
21
29
  # will be already initialized with the defaults.
22
- filterrific_params = resource_class.filterrific_default_settings if filterrific_params.blank?
30
+ filterrific_params = model_class.filterrific_default_settings if filterrific_params.blank?
23
31
  filterrific_params.stringify_keys!
24
32
  filterrific_params = condition_filterrific_params(filterrific_params)
25
- define_attr_accessors_for_each_filter(filterrific_params)
33
+ define_and_assign_attr_accessors_for_each_filter(filterrific_params)
26
34
  end
27
35
 
28
- # A shortcut to run the ActiveRecord query on resource_class. Use this if
29
- # you want to start with the resource_class, and not a special ActiveRecord::Relation.
36
+ # A shortcut to run the ActiveRecord query on model_class. Use this if
37
+ # you want to start with the model_class, and not an existing ActiveRecord::Relation.
38
+ # Allows `@filterrific.find` in controller instead of
39
+ # `ModelClass.filterrific_find(@filterrific)`
30
40
  def find
31
- resource_class.filterrific_find(self)
41
+ model_class.filterrific_find(self)
32
42
  end
33
43
 
34
44
  # Returns Filterrific::ParamSet as hash (used for URL params and serialization)
45
+ # @return [Hash] with stringified keys
35
46
  def to_hash
36
47
  {}.tap { |h|
37
- resource_class.filterrific_filter_names.each do |filter_name|
48
+ model_class.filterrific_available_filters.each do |filter_name|
38
49
  param_value = self.send(filter_name)
39
50
  case
40
51
  when param_value.blank?
@@ -49,27 +60,16 @@ module Filterrific
49
60
  }
50
61
  end
51
62
 
63
+ # Returns params as JSON string.
64
+ # @return [String]
52
65
  def to_json
53
66
  to_hash.to_json
54
67
  end
55
68
 
56
- # Returns a signature that is unique to self's params
57
- def signature
58
- Digest::SHA1.hexdigest(to_hash.to_a.sort.to_s)
59
- end
60
-
61
- # Returns true if this Filterrific::ParamSet is not the model's default.
62
- # TODO: this doesn't work for procs. I need to evaluate the
63
- # filterrific_default_settings before comparing them to to_hash.
64
- #
65
- # def customized?
66
- # resource_class.filterrific_default_settings != to_hash
67
- # end
68
-
69
69
  protected
70
70
 
71
- # Conditions params
72
- # @param[Hash] fp the filterrific params hash
71
+ # Conditions params: Evaluates Procs and type casts integer values.
72
+ # @param fp [Hash] the filterrific params hash
73
73
  # @return[Hash] the conditioned params hash
74
74
  def condition_filterrific_params(fp)
75
75
  fp.each do |key, val|
@@ -88,11 +88,11 @@ module Filterrific
88
88
  fp
89
89
  end
90
90
 
91
- # Defines attr accessors for each filter name on self and assigns
92
- # values based on fp
93
- # @param[Hash] fp filterrific_params
94
- def define_attr_accessors_for_each_filter(fp)
95
- resource_class.filterrific_filter_names.each do |filter_name|
91
+ # Defines attr accessors for each available_filter on self and assigns
92
+ # values based on fp.
93
+ # @param fp [Hash] filterrific_params with stringified keys
94
+ def define_and_assign_attr_accessors_for_each_filter(fp)
95
+ model_class.filterrific_available_filters.each do |filter_name|
96
96
  self.class.send(:attr_accessor, filter_name)
97
97
  v = fp[filter_name]
98
98
  self.send("#{ filter_name }=", v) if v.present?
@@ -1,3 +1,5 @@
1
+ # -*- coding: utf-8 -*-
2
+
1
3
  module Filterrific
2
- VERSION = "1.4.3"
4
+ VERSION = "2.0.0"
3
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: filterrific
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.3
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jo Hund
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-13 00:00:00.000000000 Z
11
+ date: 2015-01-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - '>='
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: 0.7.3
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - '>='
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: 0.7.3
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -70,14 +70,14 @@ dependencies:
70
70
  name: wwtd
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ~>
73
+ - - '>='
74
74
  - !ruby/object:Gem::Version
75
75
  version: 0.5.5
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ~>
80
+ - - '>='
81
81
  - !ruby/object:Gem::Version
82
82
  version: 0.5.5
83
83
  description: Filterrific is a Rails Engine plugin that makes it easy to filter, search,
@@ -101,9 +101,9 @@ files:
101
101
  - doc/development_notes/model_api.rb
102
102
  - doc/development_notes/view_api.txt
103
103
  - doc/meta.md
104
- - doc/rails_conf_talk.md
105
104
  - doc/scratchpad.md
106
105
  - lib/filterrific.rb
106
+ - lib/filterrific/action_controller_extension.rb
107
107
  - lib/filterrific/action_view_extension.rb
108
108
  - lib/filterrific/active_record_extension.rb
109
109
  - lib/filterrific/engine.rb
@@ -126,7 +126,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
126
126
  requirements:
127
127
  - - '>='
128
128
  - !ruby/object:Gem::Version
129
- version: '0'
129
+ version: 1.9.3
130
130
  required_rubygems_version: !ruby/object:Gem::Requirement
131
131
  requirements:
132
132
  - - '>='
@@ -1,33 +0,0 @@
1
- # Filterrific Rails Conf Talk
2
-
3
-
4
- Topics to cover:
5
-
6
- * filter and sort ActiveRecord lists end to end with lots of code
7
- * AR scope patterns
8
- * advanced use cases
9
- * export to CSV/XLS
10
- * saved searches
11
- * full text search
12
- * multiple form inputs for single scope
13
- * checkbox arrays (collection_check_boxes)
14
- * filter persistence strategies
15
- * session
16
- * none (query param)
17
- * database (saved searches)
18
-
19
- Target audience:
20
-
21
- * intermediate
22
-
23
-
24
- Title ideas:
25
-
26
- * Tame/awesomify your ActiveRecord lists with Filterrific
27
- * Dive deep into ActiveRecord scopes, and learn about Filterrific
28
- * Slice and dice your data in many ways with AR scopes and Filterrific
29
-
30
- Other talk ideas (possibly lightning talks?):
31
-
32
- * How to safely mutate objects in Rails
33
- * Service objects, DCI, processors: all dependencies go in one direction