with_filters 0.1.0
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.
- data/.gitignore +8 -0
- data/.yardopts +1 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +63 -0
- data/Rakefile +1 -0
- data/app/views/with_filters/_filter_form.html.erb +14 -0
- data/app/views/with_filters/filter/_check_box.html.erb +2 -0
- data/app/views/with_filters/filter/_check_boxes.html.erb +5 -0
- data/app/views/with_filters/filter/_radio.html.erb +5 -0
- data/app/views/with_filters/filter/_select.html.erb +2 -0
- data/app/views/with_filters/filter/_select_range.html.erb +4 -0
- data/app/views/with_filters/filter/_text.html.erb +2 -0
- data/app/views/with_filters/filter/_text_range.html.erb +4 -0
- data/changelog.md +2 -0
- data/lib/generators/with_filters/theme/theme_generator.rb +43 -0
- data/lib/with_filters/action_view_extension.rb +110 -0
- data/lib/with_filters/active_record_extension.rb +26 -0
- data/lib/with_filters/active_record_model_extension.rb +163 -0
- data/lib/with_filters/engine.rb +5 -0
- data/lib/with_filters/hash_extraction.rb +31 -0
- data/lib/with_filters/models/action.rb +14 -0
- data/lib/with_filters/models/filter/base.rb +36 -0
- data/lib/with_filters/models/filter/base_range.rb +42 -0
- data/lib/with_filters/models/filter/check_box.rb +20 -0
- data/lib/with_filters/models/filter/choice.rb +23 -0
- data/lib/with_filters/models/filter/collection.rb +28 -0
- data/lib/with_filters/models/filter/filter.rb +59 -0
- data/lib/with_filters/models/filter/radio.rb +7 -0
- data/lib/with_filters/models/filter/select.rb +22 -0
- data/lib/with_filters/models/filter/select_range.rb +15 -0
- data/lib/with_filters/models/filter/text.rb +30 -0
- data/lib/with_filters/models/filter/text_range.rb +15 -0
- data/lib/with_filters/models/filter_form.rb +93 -0
- data/lib/with_filters/value_prep/boolean_prep.rb +10 -0
- data/lib/with_filters/value_prep/date_prep.rb +10 -0
- data/lib/with_filters/value_prep/date_time_prep.rb +51 -0
- data/lib/with_filters/value_prep/default_prep.rb +88 -0
- data/lib/with_filters/value_prep/value_prep.rb +28 -0
- data/lib/with_filters/version.rb +3 -0
- data/lib/with_filters.rb +32 -0
- data/spec/active_record_model_extension_spec.rb +435 -0
- data/spec/dummy/README.rdoc +261 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.gitkeep +0 -0
- data/spec/dummy/app/models/.gitkeep +0 -0
- data/spec/dummy/app/models/date_time_tester.rb +2 -0
- data/spec/dummy/app/models/field_format_tester.rb +2 -0
- data/spec/dummy/app/models/nobel_prize.rb +3 -0
- data/spec/dummy/app/models/nobel_prize_winner.rb +3 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config/application.rb +56 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +67 -0
- data/spec/dummy/config/environments/test.rb +37 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +58 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/migrate/20111227224959_additional_columns.rb +73 -0
- data/spec/dummy/db/migrate/20120127203225_create_nobel_prize_winners.rb +30 -0
- data/spec/dummy/db/migrate/20120203212237_create_nobel_prizes.rb +34 -0
- data/spec/dummy/db/migrate/20120209051208_modify_updated_at.rb +13 -0
- data/spec/dummy/db/migrate/20120210163052_change_created_at.rb +17 -0
- data/spec/dummy/db/migrate/20120214172946_fix_einstein.rb +9 -0
- data/spec/dummy/db/migrate/20120227200013_create_date_time_testers.rb +25 -0
- data/spec/dummy/db/migrate/20120309202722_create_field_format_testers.rb +22 -0
- data/spec/dummy/db/migrate/20120310195447_update_field_format_testers.rb +15 -0
- data/spec/dummy/db/schema.rb +51 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/lib/assets/.gitkeep +0 -0
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/generators/with_filters_theme_spec.rb +33 -0
- data/spec/hash_extraction_spec.rb +51 -0
- data/spec/helpers/action_view_extension_spec.rb +345 -0
- data/spec/models/action.rb +20 -0
- data/spec/models/filter/base_range_spec.rb +32 -0
- data/spec/models/filter/base_spec.rb +76 -0
- data/spec/models/filter/check_box_spec.rb +36 -0
- data/spec/models/filter/choice_spec.rb +24 -0
- data/spec/models/filter/collection_spec.rb +72 -0
- data/spec/models/filter/filter_spec.rb +35 -0
- data/spec/models/filter/select_spec.rb +12 -0
- data/spec/models/filter/text_spec.rb +16 -0
- data/spec/models/filter_form_spec.rb +212 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/value_prep/boolean_prep_spec.rb +13 -0
- data/spec/value_prep/date_prep_spec.rb +28 -0
- data/spec/value_prep/date_time_prep_spec.rb +106 -0
- data/spec/value_prep/default_prep_spec.rb +43 -0
- data/with_filters.gemspec +27 -0
- metadata +280 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module WithFilters
|
|
2
|
+
module Filter
|
|
3
|
+
# @private
|
|
4
|
+
class Choice
|
|
5
|
+
attr_reader :field_name, :label, :value, :attrs
|
|
6
|
+
|
|
7
|
+
def initialize(field_name, label, value, options = {})
|
|
8
|
+
@field_name = "#{field_name}[]"
|
|
9
|
+
@label = label
|
|
10
|
+
@value = value
|
|
11
|
+
|
|
12
|
+
options[:id] ||= "#{field_name}_#{value}".gsub(']', '').gsub(/[^-a-zA-Z0-9:.]/, '_')
|
|
13
|
+
|
|
14
|
+
@selected = !!options.delete(:selected)
|
|
15
|
+
@attrs = options
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def selected?
|
|
19
|
+
@selected
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module WithFilters
|
|
2
|
+
module Filter
|
|
3
|
+
# @private
|
|
4
|
+
class Collection < Array
|
|
5
|
+
def initialize(field_name, choices, options = {})
|
|
6
|
+
choices = choices.to_a if choices.is_a?(Range)
|
|
7
|
+
|
|
8
|
+
selected = Array.wrap(options[:selected]).map(&:to_s)
|
|
9
|
+
|
|
10
|
+
choices.map do |element|
|
|
11
|
+
text, value, choice_options = if element.is_a?(Array)
|
|
12
|
+
html_attrs = element.detect {|e| Hash === e} || {}
|
|
13
|
+
element = element.reject {|e| Hash === e}
|
|
14
|
+
[element.first.to_s, element.last, html_attrs]
|
|
15
|
+
elsif !element.is_a?(String) && element.respond_to?(:first) && element.respond_to?(:last)
|
|
16
|
+
[element.first.to_s, element.last, {}]
|
|
17
|
+
else
|
|
18
|
+
[element.to_s, element, {}]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
choice_options[:selected] = 'selected' if selected.include?(value.to_s)
|
|
22
|
+
|
|
23
|
+
self.push(Choice.new(field_name, text, value, choice_options))
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module WithFilters
|
|
2
|
+
# @private
|
|
3
|
+
module Filter
|
|
4
|
+
TYPES = {
|
|
5
|
+
:'datetime-local' => Text,
|
|
6
|
+
text: Text,
|
|
7
|
+
email: Text,
|
|
8
|
+
url: Text,
|
|
9
|
+
tel: Text,
|
|
10
|
+
number: Text,
|
|
11
|
+
range: Text,
|
|
12
|
+
date: Text,
|
|
13
|
+
month: Text,
|
|
14
|
+
week: Text,
|
|
15
|
+
time: Text,
|
|
16
|
+
datetime: Text,
|
|
17
|
+
search: Text,
|
|
18
|
+
color: Text,
|
|
19
|
+
hidden: Text,
|
|
20
|
+
checkbox: CheckBox,
|
|
21
|
+
radio: Radio,
|
|
22
|
+
select: Select
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
RANGED_TYPES = {
|
|
26
|
+
:'datetime-local' => TextRange,
|
|
27
|
+
text: TextRange,
|
|
28
|
+
email: TextRange,
|
|
29
|
+
url: TextRange,
|
|
30
|
+
tel: TextRange,
|
|
31
|
+
number: TextRange,
|
|
32
|
+
range: TextRange,
|
|
33
|
+
date: TextRange,
|
|
34
|
+
month: TextRange,
|
|
35
|
+
week: TextRange,
|
|
36
|
+
time: TextRange,
|
|
37
|
+
datetime: TextRange,
|
|
38
|
+
search: TextRange,
|
|
39
|
+
color: TextRange,
|
|
40
|
+
select: SelectRange
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
def self.create(name, namespace, value, options = {})
|
|
44
|
+
as = options.delete(:as)
|
|
45
|
+
|
|
46
|
+
options[:type] = as.to_s
|
|
47
|
+
|
|
48
|
+
TYPES[as].new(name, namespace, value, options)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def self.create_range(name, namespace, value, options = {})
|
|
52
|
+
as = options.delete(:as)
|
|
53
|
+
|
|
54
|
+
options[:type] = as.to_s
|
|
55
|
+
|
|
56
|
+
RANGED_TYPES[as].new(name, namespace, value, options)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module WithFilters
|
|
2
|
+
module Filter
|
|
3
|
+
# @private
|
|
4
|
+
class Select < Base
|
|
5
|
+
def initialize(name, namespace, value, options = {})
|
|
6
|
+
collection = options.delete(:collection) if options[:collection].is_a?(String)
|
|
7
|
+
if collection
|
|
8
|
+
Array.wrap(value).each do |v|
|
|
9
|
+
matched = collection.sub!(/(<option[^>]*value\s*=\s*['"]?#{v}[^>]*)/, '\1 selected="selected"')
|
|
10
|
+
unless matched
|
|
11
|
+
collection.sub!(/>#{v}</, " selected=\"selected\">#{v}<")
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
super
|
|
17
|
+
|
|
18
|
+
@collection = collection if collection
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module WithFilters
|
|
2
|
+
module Filter
|
|
3
|
+
# @private
|
|
4
|
+
class Text < Base
|
|
5
|
+
def initialize(name, namespace, value, options = {})
|
|
6
|
+
super
|
|
7
|
+
|
|
8
|
+
if @attrs[:type] != :text
|
|
9
|
+
new_partial = @to_partial_path.split(File::SEPARATOR)
|
|
10
|
+
new_partial[-1] = "_#{new_partial[-1]}_as_#{@attrs[:type]}.*"
|
|
11
|
+
|
|
12
|
+
@to_partial_path << "_as_#{@attrs[:type]}" if Dir.glob(File.join(Rails.root, 'app', 'views', *new_partial)).any?
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def create_partial_path
|
|
17
|
+
partial_path = nil
|
|
18
|
+
if @theme and @attrs[:type] != :text
|
|
19
|
+
themed_partial_path = self.class.name.underscore.split(File::SEPARATOR).insert(1, @theme)
|
|
20
|
+
themed_partial_path[themed_partial_path.length - 1] << "_as_#{@attrs[:type]}"
|
|
21
|
+
if Dir.glob(File.join(Rails.root, 'app', 'views', *themed_partial_path).sub(/([^#{File::SEPARATOR}]+?)$/, '_\1.*')).any?
|
|
22
|
+
partial_path = themed_partial_path.join(File::SEPARATOR)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
partial_path || super
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
module WithFilters
|
|
2
|
+
class FilterForm
|
|
3
|
+
attr_reader :attrs, :to_partial_path, :filters, :param_namespace, :hidden_filters, :actions
|
|
4
|
+
|
|
5
|
+
# @see ActionViewExtension#filter_form_for
|
|
6
|
+
#
|
|
7
|
+
# @since 0.1.0
|
|
8
|
+
def initialize(records, values = {}, options = {})
|
|
9
|
+
@records = records
|
|
10
|
+
@values = values
|
|
11
|
+
|
|
12
|
+
@theme = options.delete(:theme)
|
|
13
|
+
@attrs = options.reverse_merge(novalidate: 'novalidate', method: 'get')
|
|
14
|
+
|
|
15
|
+
@to_partial_path = self.class.name.underscore
|
|
16
|
+
@param_namespace = @records.with_filters_data[:param_namespace]
|
|
17
|
+
@hidden_filters = []
|
|
18
|
+
@filters = []
|
|
19
|
+
@actions = []
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# @see input
|
|
23
|
+
#
|
|
24
|
+
# @since 0.1.0
|
|
25
|
+
def hidden(name, options = {})
|
|
26
|
+
options.merge!(as: :hidden)
|
|
27
|
+
|
|
28
|
+
input(name, options)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @param [Symbol] name
|
|
32
|
+
# @param [Hash] options
|
|
33
|
+
#
|
|
34
|
+
# @since 0.1.0
|
|
35
|
+
def input(name, options = {})
|
|
36
|
+
options[:as] = find_as(name, options[:collection]) unless options[:as]
|
|
37
|
+
options.merge!(theme: @theme)
|
|
38
|
+
as = options[:as]
|
|
39
|
+
|
|
40
|
+
filter = WithFilters::Filter.create(name, self.param_namespace, @values[name], options)
|
|
41
|
+
|
|
42
|
+
(as == :hidden ? @hidden_filters : @filters).push(filter)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# @param [Symbol] name
|
|
46
|
+
# @param [Hash] options
|
|
47
|
+
#
|
|
48
|
+
# @since 0.1.0
|
|
49
|
+
def input_range(name, options = {})
|
|
50
|
+
options[:as] = find_as(name, options[:collection]) unless options[:as]
|
|
51
|
+
options.merge!(theme: @theme)
|
|
52
|
+
|
|
53
|
+
@filters.push(WithFilters::Filter.create_range(name, self.param_namespace, @values[name] || {}, options))
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# @param [Symbol] type
|
|
57
|
+
# @param [Hash] options
|
|
58
|
+
#
|
|
59
|
+
# @since 0.1.0
|
|
60
|
+
def action(type, options = {})
|
|
61
|
+
@actions.push(WithFilters::Action.new(type, options))
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
private
|
|
65
|
+
|
|
66
|
+
# Converts a database column type to an input type.
|
|
67
|
+
#
|
|
68
|
+
# @param [Symbol] name
|
|
69
|
+
# @param [Boolean] has_collection Indicates whether or not there is a collection
|
|
70
|
+
# associated with the input data.
|
|
71
|
+
#
|
|
72
|
+
# @since 0.1.0
|
|
73
|
+
def find_as(name, has_collection)
|
|
74
|
+
return :select if has_collection
|
|
75
|
+
|
|
76
|
+
case @records.with_filters_data[:column_types][name]
|
|
77
|
+
when :integer, :float, :decimal then :number
|
|
78
|
+
when :date then :date
|
|
79
|
+
when :time then :time
|
|
80
|
+
when :datetime, :timestamp then :datetime
|
|
81
|
+
when :boolean then :checkbox
|
|
82
|
+
when :string
|
|
83
|
+
case name
|
|
84
|
+
when /email/ then :email
|
|
85
|
+
when /url/ then :url
|
|
86
|
+
when /phone/ then :tel
|
|
87
|
+
else :text
|
|
88
|
+
end
|
|
89
|
+
else :text
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module WithFilters
|
|
2
|
+
module ValuePrep
|
|
3
|
+
# @private
|
|
4
|
+
class DateTimePrep < DefaultPrep
|
|
5
|
+
def prepare_value(value)
|
|
6
|
+
value = super
|
|
7
|
+
date_info = Date._parse(value)
|
|
8
|
+
|
|
9
|
+
if date_info[:sec_fraction]
|
|
10
|
+
to_parsed_s(value, {}, date_info[:sec_fraction].to_f)
|
|
11
|
+
else
|
|
12
|
+
{start: prepare_start_value(value), stop: prepare_stop_value(value)}
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def prepare_start_value(value)
|
|
17
|
+
date_info = Date._parse(value)
|
|
18
|
+
|
|
19
|
+
if date_info[:sec_fraction]
|
|
20
|
+
to_parsed_s(value, {}, date_info[:sec_fraction])
|
|
21
|
+
else
|
|
22
|
+
to_parsed_s(value)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def prepare_stop_value(value)
|
|
27
|
+
date_info = Date._parse(value)
|
|
28
|
+
|
|
29
|
+
if date_info[:sec_fraction]
|
|
30
|
+
to_parsed_s(value, {}, date_info[:sec_fraction])
|
|
31
|
+
elsif date_info[:sec]
|
|
32
|
+
to_parsed_s(value, seconds: 1)
|
|
33
|
+
elsif date_info[:min]
|
|
34
|
+
to_parsed_s(value, minutes: 1)
|
|
35
|
+
elsif date_info[:hour]
|
|
36
|
+
to_parsed_s(value, hours: 1)
|
|
37
|
+
elsif date_info[:mday]
|
|
38
|
+
to_parsed_s(value, days: 1)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def to_parsed_s(value, advance_options = {}, sec_decimal = nil)
|
|
45
|
+
parsed_s = Time.zone.parse(value).advance(advance_options).to_s(:db)
|
|
46
|
+
parsed_s << ('%.6f' % sec_decimal)[1..-1] if sec_decimal
|
|
47
|
+
parsed_s
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
module WithFilters
|
|
2
|
+
module ValuePrep
|
|
3
|
+
# @private
|
|
4
|
+
class DefaultPrep
|
|
5
|
+
# @param [Array, Hash, String] value The value to filter on.
|
|
6
|
+
# @param [Hash] options
|
|
7
|
+
# @option options [Symbol] :match Determines the way the filter is matched.
|
|
8
|
+
# Accepts `:exact`, `:contains`, `:begins_with` and `:ends_with`.
|
|
9
|
+
#
|
|
10
|
+
# @since 0.1.0
|
|
11
|
+
def initialize(value, options = {})
|
|
12
|
+
@value = value
|
|
13
|
+
@options = options
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Returns the value so that it is ready to be filtered with.
|
|
17
|
+
#
|
|
18
|
+
# @return [Array, Hash, String]
|
|
19
|
+
#
|
|
20
|
+
# @since 0.1.0
|
|
21
|
+
def value
|
|
22
|
+
@prepared_value ||= if @value.is_a?(Hash)
|
|
23
|
+
{start: prepare_start_value(@value[:start]), stop: prepare_stop_value(@value[:stop])}
|
|
24
|
+
else
|
|
25
|
+
temp = Array.wrap(@value).map do |value|
|
|
26
|
+
add_match(prepare_value(value))
|
|
27
|
+
end
|
|
28
|
+
temp.length == 1 ? temp.first : temp
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
# Prepares a value for use in the filter.
|
|
35
|
+
#
|
|
36
|
+
# @param [String] value The value to filter on.
|
|
37
|
+
#
|
|
38
|
+
# @return [String]
|
|
39
|
+
#
|
|
40
|
+
# @since 0.1.0
|
|
41
|
+
def prepare_value(value)
|
|
42
|
+
value.respond_to?(:strip) ? value.strip : value
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Prepares the start value for a ranged filter.
|
|
46
|
+
#
|
|
47
|
+
# @param [String] value The value to filter on.
|
|
48
|
+
#
|
|
49
|
+
# @return [String]
|
|
50
|
+
#
|
|
51
|
+
# @since 0.1.0
|
|
52
|
+
def prepare_start_value(value)
|
|
53
|
+
prepare_value(value)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Prepares the stop value for a ranged filter.
|
|
57
|
+
#
|
|
58
|
+
# @param [String] value The value to filter on.
|
|
59
|
+
#
|
|
60
|
+
# @return [String]
|
|
61
|
+
#
|
|
62
|
+
# @since 0.1.0
|
|
63
|
+
def prepare_stop_value(value)
|
|
64
|
+
prepare_value(value)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Add string matchers based on the `:match` option passed to #initialize.
|
|
68
|
+
#
|
|
69
|
+
# @param [String] value The value to filter on.
|
|
70
|
+
#
|
|
71
|
+
# @return [String]
|
|
72
|
+
#
|
|
73
|
+
# @since 0.1.0
|
|
74
|
+
def add_match(value)
|
|
75
|
+
case @options[:match]
|
|
76
|
+
when :contains
|
|
77
|
+
"%#{value}%"
|
|
78
|
+
when :begins_with
|
|
79
|
+
"#{value}%"
|
|
80
|
+
when :ends_with
|
|
81
|
+
"%#{value}"
|
|
82
|
+
else
|
|
83
|
+
value
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module WithFilters
|
|
2
|
+
# @private
|
|
3
|
+
module ValuePrep
|
|
4
|
+
# A mapping of Rails column types to value preparation class.
|
|
5
|
+
#
|
|
6
|
+
# since 0.1.0
|
|
7
|
+
TYPE_MAP = {
|
|
8
|
+
boolean: BooleanPrep,
|
|
9
|
+
date: DatePrep,
|
|
10
|
+
datetime: DateTimePrep,
|
|
11
|
+
timestamp: DateTimePrep
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
# A factory returning a class that prepares filter values based on a Rails
|
|
15
|
+
# column type.
|
|
16
|
+
#
|
|
17
|
+
# @param [Symbol] column_type A Rails column type.
|
|
18
|
+
# @param [String] value Value to be passed to the value preparation class.
|
|
19
|
+
# @param [Hash] options Options to be passed to the value preparation class.
|
|
20
|
+
#
|
|
21
|
+
# @return [WithFilters::DefaultPrep, Inherited from WithFilters::DefaultPrep]
|
|
22
|
+
#
|
|
23
|
+
# since 0.1.0
|
|
24
|
+
def self.prepare(column_type, value, options = {})
|
|
25
|
+
(TYPE_MAP[column_type].try(:new, value, options) || DefaultPrep.new(value, options)).value
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
data/lib/with_filters.rb
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'with_filters/engine'
|
|
2
|
+
require 'with_filters/hash_extraction'
|
|
3
|
+
require 'with_filters/active_record_extension'
|
|
4
|
+
require 'with_filters/active_record_model_extension'
|
|
5
|
+
require 'with_filters/value_prep/default_prep'
|
|
6
|
+
require 'with_filters/value_prep/boolean_prep'
|
|
7
|
+
require 'with_filters/value_prep/date_prep'
|
|
8
|
+
require 'with_filters/value_prep/date_time_prep'
|
|
9
|
+
require 'with_filters/value_prep/value_prep'
|
|
10
|
+
require 'with_filters/action_view_extension'
|
|
11
|
+
require 'with_filters/models/action'
|
|
12
|
+
require 'with_filters/models/filter/choice'
|
|
13
|
+
require 'with_filters/models/filter/collection'
|
|
14
|
+
require 'with_filters/models/filter/base'
|
|
15
|
+
require 'with_filters/models/filter/base_range'
|
|
16
|
+
require 'with_filters/models/filter/text'
|
|
17
|
+
require 'with_filters/models/filter/text_range'
|
|
18
|
+
require 'with_filters/models/filter/radio'
|
|
19
|
+
require 'with_filters/models/filter/select'
|
|
20
|
+
require 'with_filters/models/filter/select_range'
|
|
21
|
+
require 'with_filters/models/filter/check_box'
|
|
22
|
+
require 'with_filters/models/filter/filter'
|
|
23
|
+
require 'with_filters/models/filter_form'
|
|
24
|
+
require 'with_filters/version'
|
|
25
|
+
|
|
26
|
+
ActiveSupport.on_load(:active_record) do
|
|
27
|
+
include WithFilters::ActiveRecordExtension
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
ActiveSupport.on_load(:action_view) do
|
|
31
|
+
include WithFilters::ActionViewExtension
|
|
32
|
+
end
|