Class: WillFilter::Filter
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- WillFilter::Filter
- Defined in:
- app/models/will_filter/filter.rb
Constant Summary collapse
- JOIN_NAME_INDICATOR =
'>'
Class Method Summary collapse
- .container_by_sql_type(type) ⇒ Object
-
.deserialize_from_params(params) ⇒ Object
allows to create a filter from params only.
Instance Method Summary collapse
- #add_condition(condition_key, operator_key, values = []) ⇒ Object
- #add_condition!(condition_key, operator_key, values = []) ⇒ Object
- #add_condition_at(index, condition_key, operator_key, values = []) ⇒ Object
- #add_default_condition_at(index) ⇒ Object
- #association_class(inner_join) ⇒ Object
- #association_name(inner_join) ⇒ Object
- #avg(column_name) ⇒ Object
- #clone_with_condition(condition_key, operator_key, values = []) ⇒ Object
- #column_sorted?(key) ⇒ Boolean
- #condition_at(index) ⇒ Object
- #condition_by_key(key) ⇒ Object
- #condition_options ⇒ Object
-
#condition_title_for(key) ⇒ Object
Can be overloaded for custom titles.
- #conditions ⇒ Object
- #conditions=(new_conditions) ⇒ Object
- #conditions_for(condition_key) ⇒ Object
- #container_by_sql_type(type) ⇒ Object
- #container_for(condition_key, operator_key) ⇒ Object
- #contains_column?(key) ⇒ Boolean
- #count(column_name) ⇒ Object
- #custom_condition?(condition) ⇒ Boolean
-
#custom_condition_met?(condition, object) ⇒ Boolean
overload this method to evaluate a custom condition on an object.
-
#custom_conditions ⇒ Object
overload this method to indicate which conditions are custom.
- #custom_conditions? ⇒ Boolean
- #custom_format? ⇒ Boolean
- #custom_formats ⇒ Object
- #debug_conditions(conds) ⇒ Object
- #debug_sql_conditions ⇒ Object
- #default_condition_definition_for(name, sql_data_type) ⇒ Object
-
#default_condition_key ⇒ Object
options always go in [NAME, KEY] format.
- #default_filter_conditions(key) ⇒ Object
-
#default_filter_if_empty ⇒ Object
overload this method if you don’t want to allow empty filters.
- #default_filters ⇒ Object
-
#default_operator_key(condition_key) ⇒ Object
options always go in [NAME, KEY] format.
- #default_order ⇒ Object
- #default_order_type ⇒ Object
- #default_per_page ⇒ Object
- #default_per_page_options ⇒ Object
- #definition ⇒ Object
- #deserialize_from_params(params) ⇒ Object (also: #from_params)
- #dup ⇒ Object
- #empty? ⇒ Boolean
- #errors ⇒ Object
-
#errors? ⇒ Boolean
Validations.
-
#export_formats ⇒ Object
Export Filter Data.
- #extra_params ⇒ Object
- #fields ⇒ Object
- #filter_options ⇒ Object
- #first_sorted_operator(opers) ⇒ Object
- #format ⇒ Object
- #handle_empty_filter! ⇒ Object
- #has_condition?(key) ⇒ Boolean
-
#initialize(model_class = nil) ⇒ Filter
constructor
Basics.
-
#inner_joins ⇒ Object
Inner Joins come in a form of [[joining_model_name, column_name], [joining_model_name, column_name]].
-
#joins ⇒ Object
deprecated for Rails 3.0 and up.
- #key ⇒ Object
- #key=(new_key) ⇒ Object
- #load_default_filter(key) ⇒ Object
- #load_filter!(key_or_id) ⇒ Object
- #match ⇒ Object
- #match=(new_match) ⇒ Object
- #match_options ⇒ Object
- #max(column_name) ⇒ Object
- #min(column_name) ⇒ Object
-
#model_class ⇒ Object
For extra security, this method must be overloaded by the extending class.
- #model_class_for_column_key(key) ⇒ Object
- #model_column_keys ⇒ Object
- #model_columns ⇒ Object
- #operator_options_for(condition_key) ⇒ Object
- #order ⇒ Object
- #order_clause ⇒ Object
- #order_configurable? ⇒ Boolean
- #order_model ⇒ Object
- #order_type ⇒ Object
- #order_type_options ⇒ Object
- #page ⇒ Object
- #per_page ⇒ Object
- #per_page_configurable? ⇒ Boolean
- #per_page_options ⇒ Object
- #prepare_save ⇒ Object
- #process_custom_conditions(objects) ⇒ Object
- #process_custom_format ⇒ Object
- #process_find ⇒ Object
- #remove_all ⇒ Object
- #remove_condition(condition_key) ⇒ Object
- #remove_condition_at(index) ⇒ Object
- #replace_condition(condition_key, operator_key, values = []) ⇒ Object
-
#required_condition_keys ⇒ Object
a list of indexed fields where at least one of them has to be in a query otherwise the filter may hang the database.
- #required_conditions_met? ⇒ Boolean
- #reset! ⇒ Object
- #results ⇒ Object
- #saved_filters(include_default = true) ⇒ Object
-
#serialize_to_params(merge_params = {}) ⇒ Object
(also: #to_params)
Serialization.
-
#show_export_options? ⇒ Boolean
Defaults.
- #show_save_options? ⇒ Boolean
- #size ⇒ Object
- #sorted_operators(opers) ⇒ Object
- #sql_attribute_for_key(key) ⇒ Object
- #sql_conditions ⇒ Object
-
#sum(column_name) ⇒ Object
sums up the column for the given conditions.
- #table_name ⇒ Object
- #to_s ⇒ Object
-
#to_sql_condition(condition) ⇒ Object
SQL Conditions.
- #to_url_params ⇒ Object
-
#user_filters ⇒ Object
Saved Filters.
- #valid_format? ⇒ Boolean
- #valid_operator?(condition_key, operator_key) ⇒ Boolean
- #validate! ⇒ Object
-
#value_options_for(condition_key) ⇒ Object
called by the list container, should be overloaded in a subclass.
Constructor Details
#initialize(model_class = nil) ⇒ Filter
Basics
66 67 68 69 70 71 72 73 74 |
# File 'app/models/will_filter/filter.rb', line 66 def initialize(model_class = nil) super() if WillFilter::Config.require_filter_extensions? and self.class.name == 'WillFilter::Filter' raise WillFilter::FilterException.new('Your configuration requires you to subclass the filter. Default filter cannot be created.') end self.model_class_name = model_class.to_s end |
Class Method Details
.container_by_sql_type(type) ⇒ Object
207 208 209 210 |
# File 'app/models/will_filter/filter.rb', line 207 def self.container_by_sql_type(type) raise WillFilter::FilterException.new("Unsupported data type #{type}") unless WillFilter::Config.data_types[type] WillFilter::Config.data_types[type] end |
.deserialize_from_params(params) ⇒ Object
allows to create a filter from params only
536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 |
# File 'app/models/will_filter/filter.rb', line 536 def self.deserialize_from_params(params) params = HashWithIndifferentAccess.new(params) unless params.is_a?(HashWithIndifferentAccess) params[:wf_type] = self.name unless params[:wf_type] filter_class = params[:wf_type].constantize filter_instance = filter_class.new unless filter_instance.kind_of?(WillFilter::Filter) raise WillFilter::FilterException.new("Invalid filter class. Filter classes must extand WillFilter::Filter.") end if WillFilter::Config.require_filter_extensions? filter_instance.deserialize_from_params(params) else filter_class.new(params[:wf_model]).deserialize_from_params(params) end end |
Instance Method Details
#add_condition(condition_key, operator_key, values = []) ⇒ Object
407 408 409 |
# File 'app/models/will_filter/filter.rb', line 407 def add_condition(condition_key, operator_key, values = []) add_condition_at(size, condition_key, operator_key, values) end |
#add_condition!(condition_key, operator_key, values = []) ⇒ Object
411 412 413 414 |
# File 'app/models/will_filter/filter.rb', line 411 def add_condition!(condition_key, operator_key, values = []) add_condition(condition_key, operator_key, values) self end |
#add_condition_at(index, condition_key, operator_key, values = []) ⇒ Object
432 433 434 435 436 437 438 439 440 441 442 443 444 445 |
# File 'app/models/will_filter/filter.rb', line 432 def add_condition_at(index, condition_key, operator_key, values = []) values = [values] unless values.instance_of?(Array) values = values.collect{|v| v.to_s} condition_key = condition_key.to_sym if condition_key.is_a?(String) unless valid_operator?(condition_key, operator_key) opers = definition[condition_key] operator_key = first_sorted_operator(opers) end condition = WillFilter::FilterCondition.new(self, condition_key, operator_key, container_for(condition_key, operator_key), values) @conditions.insert(index, condition) end |
#add_default_condition_at(index) ⇒ Object
484 485 486 |
# File 'app/models/will_filter/filter.rb', line 484 def add_default_condition_at(index) add_condition_at(index, default_condition_key, default_operator_key(default_condition_key)) end |
#association_class(inner_join) ⇒ Object
866 867 868 |
# File 'app/models/will_filter/filter.rb', line 866 def association_class(inner_join) model_class.new.association(association_name(inner_join)).build.class end |
#association_name(inner_join) ⇒ Object
862 863 864 |
# File 'app/models/will_filter/filter.rb', line 862 def association_name(inner_join) (inner_join.is_a?(Array) ? inner_join.first : inner_join).to_sym end |
#avg(column_name) ⇒ Object
963 964 965 |
# File 'app/models/will_filter/filter.rb', line 963 def avg(column_name) model_class.average(column_name, :conditions => sql_conditions) end |
#clone_with_condition(condition_key, operator_key, values = []) ⇒ Object
416 417 418 |
# File 'app/models/will_filter/filter.rb', line 416 def clone_with_condition(condition_key, operator_key, values = []) dup.add_condition!(condition_key, operator_key, values) end |
#column_sorted?(key) ⇒ Boolean
295 296 297 |
# File 'app/models/will_filter/filter.rb', line 295 def column_sorted?(key) key.to_s == order end |
#condition_at(index) ⇒ Object
469 470 471 |
# File 'app/models/will_filter/filter.rb', line 469 def condition_at(index) conditions[index] end |
#condition_by_key(key) ⇒ Object
473 474 475 476 477 478 |
# File 'app/models/will_filter/filter.rb', line 473 def condition_by_key(key) conditions.each do |c| return c if c.key==key end nil end |
#condition_options ⇒ Object
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 |
# File 'app/models/will_filter/filter.rb', line 349 def @condition_options ||= begin opts = [] definition.keys.each do |cond| opts << [condition_title_for(cond), cond.to_s] end opts = opts.sort_by{|opt| opt.first.gsub(JOIN_NAME_INDICATOR, 'zzz') } separated = [] opts.each_with_index do |opt, index| if index > 0 prev_opt_parts = opts[index-1].first.split(":") curr_opt_parts = opt.first.split(":") if (prev_opt_parts.size != curr_opt_parts.size) or (curr_opt_parts.size > 1 and (prev_opt_parts.first != curr_opt_parts.first)) key_parts = opt.last.split('.') separated << ["-------------- #{curr_opt_parts.first.gsub("#{JOIN_NAME_INDICATOR} ", '')} --------------", "#{key_parts.first}.id"] end end separated << opt end separated end end |
#condition_title_for(key) ⇒ Object
Can be overloaded for custom titles
338 339 340 341 342 343 344 345 346 347 |
# File 'app/models/will_filter/filter.rb', line 338 def condition_title_for(key) title_parts = key.to_s.split('.') title = key.to_s.gsub(".", ": ").gsub("_", " ") title = title.split(" ").collect{|part| part.split("/").last.capitalize}.join(" ") if title_parts.size > 1 "#{JOIN_NAME_INDICATOR} #{title}" else title end end |
#conditions ⇒ Object
465 466 467 |
# File 'app/models/will_filter/filter.rb', line 465 def conditions @conditions ||= [] end |
#conditions=(new_conditions) ⇒ Object
461 462 463 |
# File 'app/models/will_filter/filter.rb', line 461 def conditions=(new_conditions) @conditions = new_conditions end |
#conditions_for(condition_key) ⇒ Object
399 400 401 |
# File 'app/models/will_filter/filter.rb', line 399 def conditions_for(condition_key) @conditions.select{|cond| cond.key == condition_key} end |
#container_by_sql_type(type) ⇒ Object
212 213 214 |
# File 'app/models/will_filter/filter.rb', line 212 def container_by_sql_type(type) self.class.container_by_sql_type(type) end |
#container_for(condition_key, operator_key) ⇒ Object
387 388 389 390 391 392 393 394 395 396 397 |
# File 'app/models/will_filter/filter.rb', line 387 def container_for(condition_key, operator_key) condition_key = condition_key.to_sym if condition_key.is_a?(String) opers = definition[condition_key] raise WillFilter::FilterException.new("Invalid condition #{condition_key} for filter #{self.class.name}") unless opers oper = opers[operator_key] # if invalid operator_key was passed, use first operator oper = opers[first_sorted_operator(opers)] unless oper oper end |
#contains_column?(key) ⇒ Boolean
174 175 176 |
# File 'app/models/will_filter/filter.rb', line 174 def contains_column?(key) model_column_keys.index(key.to_sym) != nil end |
#count(column_name) ⇒ Object
967 968 969 |
# File 'app/models/will_filter/filter.rb', line 967 def count(column_name) model_class.count(column_name, :conditions => sql_conditions) end |
#custom_condition?(condition) ⇒ Boolean
890 891 892 |
# File 'app/models/will_filter/filter.rb', line 890 def custom_condition?(condition) custom_conditions.include?(condition.key) end |
#custom_condition_met?(condition, object) ⇒ Boolean
overload this method to evaluate a custom condition on an object
886 887 888 |
# File 'app/models/will_filter/filter.rb', line 886 def custom_condition_met?(condition, object) false end |
#custom_conditions ⇒ Object
overload this method to indicate which conditions are custom
881 882 883 |
# File 'app/models/will_filter/filter.rb', line 881 def custom_conditions [] end |
#custom_conditions? ⇒ Boolean
894 895 896 897 898 899 |
# File 'app/models/will_filter/filter.rb', line 894 def custom_conditions? return if custom_conditions.empty? conditions.each do |condition| return true if custom_condition?(condition) end end |
#custom_format? ⇒ Boolean
847 848 849 850 851 852 |
# File 'app/models/will_filter/filter.rb', line 847 def custom_format? custom_formats.each do |frmt| return true if frmt[1].to_sym == format end false end |
#custom_formats ⇒ Object
854 855 856 |
# File 'app/models/will_filter/filter.rb', line 854 def custom_formats [] end |
#debug_conditions(conds) ⇒ Object
697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 |
# File 'app/models/will_filter/filter.rb', line 697 def debug_conditions(conds) all_conditions = [] conds.each_with_index do |c, i| cond = "" if i == 0 cond << "\"<b>#{c}</b>\"" else cond << "<br> <b>#{i})</b> " if c.is_a?(Array) cond << "[" cond << (c.collect{|v| "\"#{v.strip}\""}.join(", ")) cond << "]" elsif c.is_a?(Date) cond << "\"#{c.strftime("%Y-%m-%d")}\"" elsif c.is_a?(Time) cond << "\"#{c.strftime("%Y-%m-%d %H:%M:%S")}\"" elsif c.is_a?(Integer) cond << c.to_s else cond << "\"#{c}\"" end end all_conditions << cond end all_conditions.join("") end |
#debug_sql_conditions ⇒ Object
725 726 727 |
# File 'app/models/will_filter/filter.rb', line 725 def debug_sql_conditions debug_conditions(sql_conditions) end |
#default_condition_definition_for(name, sql_data_type) ⇒ Object
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'app/models/will_filter/filter.rb', line 216 def default_condition_definition_for(name, sql_data_type) type = sql_data_type.split(" ").first.split("(").first.downcase containers = container_by_sql_type(type) operators = {} containers.each do |c| raise WillFilter::FilterException.new("Unsupported container implementation for #{c}") unless WillFilter::Config.containers[c] container_klass = WillFilter::Config.containers[c].constantize container_klass.operators.each do |o| operators[o] = c end end if name == "id" operators[:is_filtered_by] = :filter_list elsif "_id" == name[-3..-1] begin name[0..-4].camelcase.constantize operators[:is_filtered_by] = :filter_list rescue end end operators end |
#default_condition_key ⇒ Object
options always go in [NAME, KEY] format
450 451 452 |
# File 'app/models/will_filter/filter.rb', line 450 def default_condition_key .first.last end |
#default_filter_conditions(key) ⇒ Object
793 794 795 |
# File 'app/models/will_filter/filter.rb', line 793 def default_filter_conditions(key) [] end |
#default_filter_if_empty ⇒ Object
overload this method if you don’t want to allow empty filters
779 780 781 |
# File 'app/models/will_filter/filter.rb', line 779 def default_filter_if_empty nil end |
#default_filters ⇒ Object
789 790 791 |
# File 'app/models/will_filter/filter.rb', line 789 def default_filters [] end |
#default_operator_key(condition_key) ⇒ Object
options always go in [NAME, KEY] format
457 458 459 |
# File 'app/models/will_filter/filter.rb', line 457 def default_operator_key(condition_key) (condition_key).first.last end |
#default_order ⇒ Object
253 254 255 |
# File 'app/models/will_filter/filter.rb', line 253 def default_order 'id' end |
#default_order_type ⇒ Object
263 264 265 |
# File 'app/models/will_filter/filter.rb', line 263 def default_order_type 'desc' end |
#default_per_page ⇒ Object
299 300 301 |
# File 'app/models/will_filter/filter.rb', line 299 def default_per_page 100 end |
#default_per_page_options ⇒ Object
311 312 313 |
# File 'app/models/will_filter/filter.rb', line 311 def [10, 20, 30, 40, 50, 100, 500, 1000] end |
#definition ⇒ Object
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'app/models/will_filter/filter.rb', line 178 def definition @definition ||= begin defs = {} model_columns.each do |col| key = col.name.to_sym next unless contains_column?(key) defs[key] = default_condition_definition_for(col.name, col.sql_type) end inner_joins.each do |inner_join| join_class = association_class(inner_join) join_class.columns.each do |col| defs[:"#{join_class.to_s.underscore}.#{col.name.to_sym}"] = default_condition_definition_for(col.name, col.sql_type) end end defs end end |
#deserialize_from_params(params) ⇒ Object Also known as: from_params
554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 |
# File 'app/models/will_filter/filter.rb', line 554 def deserialize_from_params(params) params = HashWithIndifferentAccess.new(params) unless params.is_a?(HashWithIndifferentAccess) @conditions = [] @match = params[:wf_match] || :all @key = params[:wf_key] || self.id.to_s self.model_class_name = params[:wf_model] if params[:wf_model] @per_page = params[:wf_per_page] || default_per_page @page = params[:page] || 1 @order_type = params[:wf_order_type] || default_order_type @order = params[:wf_order] || default_order self.id = params[:wf_id].to_i unless params[:wf_id].blank? self.name = params[:wf_name] unless params[:wf_name].blank? @fields = [] unless params[:wf_export_fields].blank? params[:wf_export_fields].split(",").each do |fld| @fields << fld.to_sym end end if params[:wf_export_format].blank? @format = :html else @format = params[:wf_export_format].to_sym end i = 0 while params["wf_c#{i}"] do conditon_key = params["wf_c#{i}"] operator_key = params["wf_o#{i}"] values = [] j = 0 while params["wf_v#{i}_#{j}"] do values << params["wf_v#{i}_#{j}"] j += 1 end i += 1 add_condition(conditon_key, operator_key.to_sym, values) end if params[:wf_submitted] == 'true' validate! end if WillFilter::Config.user_filters_enabled? and WillFilter::Config.current_user self.user_id = WillFilter::Config.current_user.id end if WillFilter::Config.project_filters_enabled? and WillFilter::Config.current_project self.project_id = WillFilter::Config.current_project.id end self end |
#dup ⇒ Object
76 77 78 |
# File 'app/models/will_filter/filter.rb', line 76 def dup super.tap {|ii| ii.conditions = self.conditions.dup} end |
#empty? ⇒ Boolean
621 622 623 |
# File 'app/models/will_filter/filter.rb', line 621 def empty? size == 0 end |
#errors ⇒ Object
109 110 111 |
# File 'app/models/will_filter/filter.rb', line 109 def errors @errors ||= {} end |
#errors? ⇒ Boolean
Validations
617 618 619 |
# File 'app/models/will_filter/filter.rb', line 617 def errors? (@errors and @errors.size > 0) end |
#export_formats ⇒ Object
Export Filter Data
832 833 834 835 836 837 838 839 840 841 842 843 844 845 |
# File 'app/models/will_filter/filter.rb', line 832 def export_formats formats = [] formats << ["-- Generic Formats --", -1] WillFilter::Config.default_export_formats.each do |frmt| formats << [frmt, frmt] end if custom_formats.size > 0 formats << ["-- Custom Formats --", -2] custom_formats.each do |frmt| formats << frmt end end formats end |
#extra_params ⇒ Object
121 122 123 |
# File 'app/models/will_filter/filter.rb', line 121 def extra_params @extra_params ||= {} end |
#fields ⇒ Object
117 118 119 |
# File 'app/models/will_filter/filter.rb', line 117 def fields @fields ||= [] end |
#filter_options ⇒ Object
758 759 760 761 762 763 764 765 766 767 768 769 770 |
# File 'app/models/will_filter/filter.rb', line 758 def filters = [['', [['', '']]]] if default_filters.any? filters << ['Pre-defined Filters', default_filters] end if saved_filters.any? filters << ['Saved Filters', saved_filters] end filters end |
#first_sorted_operator(opers) ⇒ Object
249 250 251 |
# File 'app/models/will_filter/filter.rb', line 249 def first_sorted_operator(opers) sorted_operators(opers).first.to_sym end |
#format ⇒ Object
113 114 115 |
# File 'app/models/will_filter/filter.rb', line 113 def format @format ||= :html end |
#handle_empty_filter! ⇒ Object
783 784 785 786 787 |
# File 'app/models/will_filter/filter.rb', line 783 def handle_empty_filter! return unless empty? return if default_filter_if_empty.nil? load_filter!(default_filter_if_empty) end |
#has_condition?(key) ⇒ Boolean
625 626 627 |
# File 'app/models/will_filter/filter.rb', line 625 def has_condition?(key) condition_by_key(key) != nil end |
#inner_joins ⇒ Object
Inner Joins come in a form of
- [joining_model_name, column_name], [joining_model_name, column_name]
162 163 164 |
# File 'app/models/will_filter/filter.rb', line 162 def inner_joins [] end |
#joins ⇒ Object
deprecated for Rails 3.0 and up
871 872 873 874 875 876 877 878 |
# File 'app/models/will_filter/filter.rb', line 871 def joins return nil if inner_joins.empty? inner_joins.collect do |inner_join| join_table_name = association_class(inner_join).table_name join_on_field = inner_join.last.to_s "INNER JOIN #{join_table_name} ON #{join_table_name}.id = #{table_name}.#{join_on_field}" end end |
#key ⇒ Object
105 106 107 |
# File 'app/models/will_filter/filter.rb', line 105 def key @key ||= '' end |
#key=(new_key) ⇒ Object
150 151 152 |
# File 'app/models/will_filter/filter.rb', line 150 def key=(new_key) @key = new_key end |
#load_default_filter(key) ⇒ Object
797 798 799 800 801 802 803 804 805 806 807 808 809 |
# File 'app/models/will_filter/filter.rb', line 797 def load_default_filter(key) default_conditions = default_filter_conditions(key) return if default_conditions.nil? or default_conditions.empty? unless default_conditions.first.is_a?(Array) add_condition(*default_conditions) return end default_conditions.each do |default_condition| add_condition(*default_condition) end end |
#load_filter!(key_or_id) ⇒ Object
817 818 819 820 821 822 823 824 825 826 827 |
# File 'app/models/will_filter/filter.rb', line 817 def load_filter!(key_or_id) reset! @key = key_or_id.to_s load_default_filter(key) return self unless empty? filter = WillFilter::Filter.find_by_id(key_or_id.to_i) raise WillFilter::FilterException.new("Invalid filter key #{key_or_id.to_s}") if filter.nil? filter end |
#match ⇒ Object
101 102 103 |
# File 'app/models/will_filter/filter.rb', line 101 def match @match ||= :all end |
#match=(new_match) ⇒ Object
154 155 156 |
# File 'app/models/will_filter/filter.rb', line 154 def match=(new_match) @match = new_match end |
#match_options ⇒ Object
323 324 325 |
# File 'app/models/will_filter/filter.rb', line 323 def [["all", "all"], ["any", "any"]] end |
#max(column_name) ⇒ Object
955 956 957 |
# File 'app/models/will_filter/filter.rb', line 955 def max(column_name) model_class.maximum(column_name, :conditions => sql_conditions) end |
#min(column_name) ⇒ Object
959 960 961 |
# File 'app/models/will_filter/filter.rb', line 959 def min(column_name) model_class.minimum(column_name, :conditions => sql_conditions) end |
#model_class ⇒ Object
For extra security, this method must be overloaded by the extending class.
134 135 136 137 138 139 140 141 142 143 144 |
# File 'app/models/will_filter/filter.rb', line 134 def model_class if WillFilter::Config.require_filter_extensions? raise WillFilter::FilterException.new("model_class method must be overloaded in the extending class.") end if model_class_name.blank? raise WillFilter::FilterException.new("model_class_name was not specified.") end @model_class ||= model_class_name.constantize end |
#model_class_for_column_key(key) ⇒ Object
241 242 243 |
# File 'app/models/will_filter/filter.rb', line 241 def model_class_for_column_key(key) nil end |
#model_column_keys ⇒ Object
170 171 172 |
# File 'app/models/will_filter/filter.rb', line 170 def model_column_keys @model_column_keys ||= model_columns.collect{|col| col.name.to_sym} end |
#model_columns ⇒ Object
166 167 168 |
# File 'app/models/will_filter/filter.rb', line 166 def model_columns @model_columns ||= model_class.columns end |
#operator_options_for(condition_key) ⇒ Object
374 375 376 377 378 379 380 |
# File 'app/models/will_filter/filter.rb', line 374 def (condition_key) condition_key = condition_key.to_sym if condition_key.is_a?(String) opers = definition[condition_key] raise WillFilter::FilterException.new("Invalid condition #{condition_key} for filter #{self.class.name}") unless opers sorted_operators(opers).collect{|o| [o.to_s.gsub('_', ' '), o]} end |
#order ⇒ Object
257 258 259 260 261 |
# File 'app/models/will_filter/filter.rb', line 257 def order @order ||= default_order @order = default_order unless contains_column?(@order.to_sym) @order end |
#order_clause ⇒ Object
284 285 286 287 288 289 290 291 292 293 |
# File 'app/models/will_filter/filter.rb', line 284 def order_clause @order_clause ||= begin order_parts = order.split('.') if order_parts.size > 1 "#{order_parts.first.camelcase.constantize.table_name}.#{order_parts.last} #{order_type}" else "#{model_class_name.constantize.table_name}.#{order_parts.first} #{order_type}" end end end |
#order_configurable? ⇒ Boolean
327 328 329 |
# File 'app/models/will_filter/filter.rb', line 327 def order_configurable? true end |
#order_model ⇒ Object
273 274 275 276 277 278 279 280 281 282 |
# File 'app/models/will_filter/filter.rb', line 273 def order_model @order_model ||= begin order_parts = order.split('.') if order_parts.size > 1 order_parts.first.camelcase else model_class_name end end end |
#order_type ⇒ Object
267 268 269 270 271 |
# File 'app/models/will_filter/filter.rb', line 267 def order_type @order_type ||= default_order_type @order_type = default_order_type unless ['asc', 'desc'].include?(@order_type.to_s) @order_type end |
#order_type_options ⇒ Object
331 332 333 |
# File 'app/models/will_filter/filter.rb', line 331 def [["desc", "desc"], ["asc", "asc"]] end |
#page ⇒ Object
307 308 309 |
# File 'app/models/will_filter/filter.rb', line 307 def page @page ||= 1 end |
#per_page ⇒ Object
303 304 305 |
# File 'app/models/will_filter/filter.rb', line 303 def per_page @per_page ||= default_per_page end |
#per_page_configurable? ⇒ Boolean
315 316 317 |
# File 'app/models/will_filter/filter.rb', line 315 def per_page_configurable? true end |
#per_page_options ⇒ Object
319 320 321 |
# File 'app/models/will_filter/filter.rb', line 319 def @per_page_options ||= .collect{ |n| [n.to_s, n.to_s] } end |
#prepare_save ⇒ Object
80 81 82 83 |
# File 'app/models/will_filter/filter.rb', line 80 def prepare_save self.data = serialize_to_params self.type = self.class.name end |
#process_custom_conditions(objects) ⇒ Object
901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 |
# File 'app/models/will_filter/filter.rb', line 901 def process_custom_conditions(objects) filtered = [] objects.each do |obj| condition_flags = [] 0.upto(size - 1) do |index| condition = condition_at(index) next unless custom_condition?(condition) condition_flags << custom_condition_met?(condition, obj) end if condition_flags.size > 0 next if match.to_s == "all" and condition_flags.include?(false) next unless condition_flags.include?(true) end filtered << obj end filtered end |
#process_custom_format ⇒ Object
858 859 860 |
# File 'app/models/will_filter/filter.rb', line 858 def process_custom_format "" end |
#process_find ⇒ Object
85 86 87 88 |
# File 'app/models/will_filter/filter.rb', line 85 def process_find @errors = {} deserialize_from_params(self.data) end |
#remove_all ⇒ Object
492 493 494 |
# File 'app/models/will_filter/filter.rb', line 492 def remove_all @conditions = [] end |
#remove_condition(condition_key) ⇒ Object
403 404 405 |
# File 'app/models/will_filter/filter.rb', line 403 def remove_condition(condition_key) @conditions -= conditions_for(condition_key) end |
#remove_condition_at(index) ⇒ Object
488 489 490 |
# File 'app/models/will_filter/filter.rb', line 488 def remove_condition_at(index) conditions.delete_at(index) end |
#replace_condition(condition_key, operator_key, values = []) ⇒ Object
420 421 422 423 |
# File 'app/models/will_filter/filter.rb', line 420 def replace_condition(condition_key, operator_key, values = []) remove_condition(condition_key) add_condition_at(size, condition_key, operator_key, values) end |
#required_condition_keys ⇒ Object
a list of indexed fields where at least one of them has to be in a query otherwise the filter may hang the database
129 130 131 |
# File 'app/models/will_filter/filter.rb', line 129 def required_condition_keys [] end |
#required_conditions_met? ⇒ Boolean
633 634 635 636 637 638 |
# File 'app/models/will_filter/filter.rb', line 633 def required_conditions_met? return true if required_condition_keys.blank? sconditions = conditions.collect{|c| c.key.to_s} rconditions = required_condition_keys.collect{|c| c.to_s} not (sconditions & rconditions).empty? end |
#reset! ⇒ Object
811 812 813 814 815 |
# File 'app/models/will_filter/filter.rb', line 811 def reset! remove_all @sql_conditions = nil @results = nil end |
#results ⇒ Object
922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 |
# File 'app/models/will_filter/filter.rb', line 922 def results @results ||= begin handle_empty_filter! if sql_conditions and !sql_conditions[0].blank? recs = model_class.where(sql_conditions).order(order_clause) else recs = model_class.order(order_clause) end inner_joins.each do |inner_join| recs = recs.joins(association_name(inner_join)) end if custom_conditions? recs = process_custom_conditions(recs.all) recs = Kaminari.paginate_array(recs) end recs = recs.page(page).per(per_page) recs.wf_filter = self recs end end |
#saved_filters(include_default = true) ⇒ Object
772 773 774 |
# File 'app/models/will_filter/filter.rb', line 772 def saved_filters(include_default = true) @saved_filters ||= user_filters.collect{|f| [f.name, f.id.to_s]} end |
#serialize_to_params(merge_params = {}) ⇒ Object Also known as: to_params
Serialization
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 |
# File 'app/models/will_filter/filter.rb', line 499 def serialize_to_params(merge_params = {}) params = {} params[:wf_type] = self.class.name params[:wf_match] = match params[:wf_model] = model_class_name params[:wf_order] = order params[:wf_order_type] = order_type params[:wf_per_page] = per_page params[:wf_export_fields] = fields.join(',') params[:wf_export_format] = format 0.upto(size - 1) do |index| condition = condition_at(index) condition.serialize_to_params(params, index) end params.merge!(extra_params) params.merge!(merge_params) HashWithIndifferentAccess.new(params) end |
#show_export_options? ⇒ Boolean
Defaults
93 94 95 |
# File 'app/models/will_filter/filter.rb', line 93 def WillFilter::Config.exporting_enabled? end |
#show_save_options? ⇒ Boolean
97 98 99 |
# File 'app/models/will_filter/filter.rb', line 97 def WillFilter::Config.saving_enabled? end |
#size ⇒ Object
480 481 482 |
# File 'app/models/will_filter/filter.rb', line 480 def size conditions.size end |
#sorted_operators(opers) ⇒ Object
245 246 247 |
# File 'app/models/will_filter/filter.rb', line 245 def sorted_operators(opers) (WillFilter::Config.operator_order & opers.keys.collect{|o| o.to_s}) end |
#sql_attribute_for_key(key) ⇒ Object
197 198 199 200 201 202 203 204 205 |
# File 'app/models/will_filter/filter.rb', line 197 def sql_attribute_for_key(key) if key.to_s.index('.') parts = key.to_s.split('.') join_class = parts.first.camelcase.constantize "#{join_class.table_name}.#{parts.last}" else "#{table_name}.#{key}" end end |
#sql_conditions ⇒ Object
663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 |
# File 'app/models/will_filter/filter.rb', line 663 def sql_conditions @sql_conditions ||= begin if errors? [' 1 = 2 '] else all_sql_conditions = [''] 0.upto(size - 1) do |index| condition = condition_at(index) next if custom_condition?(condition) next unless condition.container sql_condition = to_sql_condition(condition) unless sql_condition raise WillFilter::FilterException.new("Unsupported operator #{condition.operator_key} for container #{condition.container.class.name}") end if all_sql_conditions[0].size > 0 all_sql_conditions[0] << ( match.to_sym == :all ? ' AND ' : ' OR ') end all_sql_conditions[0] << sql_condition[0] sql_condition[1..-1].each do |c| all_sql_conditions << c end end all_sql_conditions end end end |
#sum(column_name) ⇒ Object
sums up the column for the given conditions
951 952 953 |
# File 'app/models/will_filter/filter.rb', line 951 def sum(column_name) model_class.sum(column_name, :conditions => sql_conditions) end |
#table_name ⇒ Object
146 147 148 |
# File 'app/models/will_filter/filter.rb', line 146 def table_name model_class.table_name end |
#to_s ⇒ Object
529 530 531 |
# File 'app/models/will_filter/filter.rb', line 529 def to_s to_url_params end |
#to_sql_condition(condition) ⇒ Object
SQL Conditions
659 660 661 |
# File 'app/models/will_filter/filter.rb', line 659 def to_sql_condition(condition) condition.container.sql_condition end |
#to_url_params ⇒ Object
521 522 523 524 525 526 527 |
# File 'app/models/will_filter/filter.rb', line 521 def to_url_params params = [] serialize_to_params.each do |name, value| params << "#{name.to_s}=#{ERB::Util.url_encode(value)}" end params.join("&") end |
#user_filters ⇒ Object
Saved Filters
732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 |
# File 'app/models/will_filter/filter.rb', line 732 def user_filters @user_filters ||= begin conditions = ['model_class_name = ?', self.model_class_name] if WillFilter::Config.user_filters_enabled? conditions[0] << ' and user_id = ? ' if WillFilter::Config.current_user and WillFilter::Config.current_user.id conditions << WillFilter::Config.current_user.id else conditions << '0' end end if WillFilter::Config.project_filters_enabled? conditions[0] << ' and project_id = ? ' if WillFilter::Config.current_project and WillFilter::Config.current_project.id conditions << WillFilter::Config.current_project.id else conditions << '0' end end WillFilter::Filter.where(conditions) end end |
#valid_format? ⇒ Boolean
629 630 631 |
# File 'app/models/will_filter/filter.rb', line 629 def valid_format? WillFilter::Config.default_export_formats.include?(format.to_s) end |
#valid_operator?(condition_key, operator_key) ⇒ Boolean
425 426 427 428 429 430 |
# File 'app/models/will_filter/filter.rb', line 425 def valid_operator?(condition_key, operator_key) condition_key = condition_key.to_sym if condition_key.is_a?(String) opers = definition[condition_key] return false unless opers opers[operator_key]!=nil end |
#validate! ⇒ Object
640 641 642 643 644 645 646 647 648 649 650 651 652 653 |
# File 'app/models/will_filter/filter.rb', line 640 def validate! @errors = {} 0.upto(size - 1) do |index| condition = condition_at(index) err = condition.validate @errors[index] = err if err end unless required_conditions_met? @errors[:filter] = "Filter must contain at least one of the following conditions: #{required_condition_keys.join(", ")}" end errors? end |
#value_options_for(condition_key) ⇒ Object
called by the list container, should be overloaded in a subclass
383 384 385 |
# File 'app/models/will_filter/filter.rb', line 383 def (condition_key) [] end |