module ActiveScaffold::Finder
Constants
- DATE_COMPARATORS
- DATE_RANGES
- DATE_UNITS
- NULL_COMPARATORS
- NUMERIC_COMPARATORS
- STRING_COMPARATORS
- TIME_UNITS
Attributes
Public Class Methods
Source
# File lib/active_scaffold/finder.rb, line 499 def self.included(klass) klass.extend ClassMethods end
Source
# File lib/active_scaffold/finder.rb, line 3 def self.like_operator @@like_operator ||= ::ActiveRecord::Base.connection.adapter_name.in?(%w[PostgreSQL PostGIS]) ? 'ILIKE' : 'LIKE' end
Protected Instance Methods
Source
# File lib/active_scaffold/finder.rb, line 507 def active_scaffold_conditions @active_scaffold_conditions ||= [] end
Source
# File lib/active_scaffold/finder.rb, line 550 def active_scaffold_embedded_conditions params_hash active_scaffold_embedded_params[:conditions] end
Source
# File lib/active_scaffold/finder.rb, line 519 def active_scaffold_habtm_joins ActiveScaffold.deprecator.warn 'use active_scaffold_joins' active_scaffold_joins end
Source
# File lib/active_scaffold/finder.rb, line 524 def active_scaffold_habtm_joins=(value) ActiveScaffold.deprecator.warn 'use active_scaffold_joins=' self.active_scaffold_joins = value end
Source
# File lib/active_scaffold/finder.rb, line 515 def active_scaffold_joins @active_scaffold_joins ||= [] end
Source
# File lib/active_scaffold/finder.rb, line 529 def active_scaffold_outer_joins @active_scaffold_outer_joins ||= [] end
Source
# File lib/active_scaffold/finder.rb, line 511 def active_scaffold_preload @active_scaffold_preload ||= [] end
Source
# File lib/active_scaffold/finder.rb, line 533 def active_scaffold_references @active_scaffold_references ||= [] end
Source
# File lib/active_scaffold/finder.rb, line 554 def all_conditions(id_condition: true) [ (self.id_condition if id_condition), # for list with id (e.g. /users/:id/index) active_scaffold_conditions, # from the search modules conditions_for_collection, # from the dev conditions_from_params, # from the parameters (e.g. /users/list?first_name=Fred) conditions_from_constraints, # from any constraints (embedded scaffolds) active_scaffold_embedded_conditions # embedding conditions (weaker constraints) ].compact_blank end
Source
# File lib/active_scaffold/finder.rb, line 684 def append_to_query(relation, options) options.assert_valid_keys :where, :select, :having, :group, :reorder, :order, :limit, :offset, :joins, :left_joins, :left_outer_joins, :includes, :lock, :readonly, :from, :conditions, :preload, :references relation = options.compact_blank.inject(relation) do |rel, (k, v)| k == :conditions ? apply_conditions(rel, *v) : rel.send(k, v) end relation.distinct_value = true if options[:left_outer_joins].present? || options[:left_joins].present? relation end
Source
# File lib/active_scaffold/finder.rb, line 706 def apply_conditions(relation, *conditions) conditions.compact_blank.inject(relation) do |rel, condition| if condition.is_a?(Array) && !condition.first.is_a?(String) # multiple conditions apply_conditions(rel, *condition) else rel.where(condition) end end end
Source
# File lib/active_scaffold/finder.rb, line 663 def calculate_last_modified(query) return unless conditional_get_support? && ActiveScaffold::OrmChecks.columns_hash(query.klass)['updated_at'] @last_modified = query.maximum(:updated_at) end
Source
# File lib/active_scaffold/finder.rb, line 680 def calculate_query(id_condition: true) active_scaffold_config.model.where(active_scaffold_config.primary_key => calculate_subquery(id_condition: id_condition)) end
Source
# File lib/active_scaffold/finder.rb, line 669 def calculate_subquery(id_condition: true) conditions = all_conditions(id_condition: id_condition) includes = active_scaffold_config.list.count_includes includes ||= active_scaffold_references if conditions.present? left_joins = active_scaffold_outer_joins left_joins += includes if includes primary_key = active_scaffold_config.primary_key subquery = append_to_query(filtered_query, conditions: conditions, joins: joins_for_finder, left_joins: left_joins, select: active_scaffold_config.columns[primary_key].field) subquery.unscope(:order) end
Source
# File lib/active_scaffold/finder.rb, line 539 def conditions_for_collection; end
Override this method on your controller to define conditions to be used when querying a recordset (e.g. for List). The return of this method should be any format compatible with the :conditions clause of ActiveRecord::Base
‘s find.
Source
# File lib/active_scaffold/finder.rb, line 614 def count_items(query, find_options = {}, count_includes = nil) count_includes ||= find_options[:includes] if find_options[:conditions].present? options = find_options.except(:select, :reorder, :order) # NOTE: we must use includes in the count query, because some conditions may reference other tables options[:includes] = count_includes count = append_to_query(query, options).count # Converts count to an integer if ActiveRecord returned an OrderedHash # that happens when find_options contains a :group key count = count.length if count.is_a?(Hash) count end
Source
# File lib/active_scaffold/finder.rb, line 546 def custom_finder_options {} end
Override this method on your controller to provide custom finder options to the find() call. The return of this method should be a hash.
Source
# File lib/active_scaffold/finder.rb, line 572 def find_if_allowed(id, security_options, klass = filtered_query) record = klass.find(id) security_options = {crud_type: security_options.to_sym} unless security_options.is_a? Hash raise ActiveScaffold::RecordNotAllowed, "#{klass} with id = #{id}" unless record.authorized_for? security_options record end
returns a single record (the given id) but only if it’s allowed for the specified security options. security options can be a hash for authorized_for? method or a value to check as a :crud_type accomplishes this by checking model.#{action}_authorized?
Source
# File lib/active_scaffold/finder.rb, line 630 def find_page(options = {}) options.assert_valid_keys :sorting, :per_page, :page, :count_includes, :pagination, :select options[:per_page] ||= 999_999_999 options[:page] ||= 1 find_options = finder_options(options) query = filtered_query query = query.where(nil) if active_scaffold_config.active_record? # where(nil) is needed because we need a relation # NOTE: we must use :include in the count query, because some conditions may reference other tables if options[:pagination] && options[:pagination] != :infinite count = count_items(query, find_options, options[:count_includes]) end query = append_to_query(query, find_options) # we build the paginator differently for method- and sql-based sorting pager = if options[:sorting]&.sorts_by_method? ::Paginator.new(count, options[:per_page]) do |offset, per_page| calculate_last_modified(query) sorted_collection = sort_collection_by_column(query.to_a, *options[:sorting].first) sorted_collection = sorted_collection.slice(offset, per_page) if options[:pagination] sorted_collection end else ::Paginator.new(count, options[:per_page]) do |offset, per_page| query = append_to_query(query, offset: offset, limit: per_page) if options[:pagination] calculate_last_modified(query) query end end pager.page(options[:page]) end
returns a Paginator::Page
(not from ActiveRecord::Paginator
) for the given parameters See finder_options
for valid options
Source
# File lib/active_scaffold/finder.rb, line 587 def finder_options(options = {}) search_conditions = all_conditions sorting = options[:sorting]&.clause sorting = sorting.map { |part| Arel.sql(part) } if sorting && active_scaffold_config.active_record? # create a general-use options array that's compatible with Rails finders finder_options = { reorder: sorting, conditions: search_conditions } if active_scaffold_config.mongoid? finder_options[:includes] = [active_scaffold_references, active_scaffold_preload].compact.flatten.uniq.presence else finder_options.merge!( joins: joins_for_finder, left_joins: active_scaffold_outer_joins, preload: active_scaffold_preload, includes: active_scaffold_references.presence, references: active_scaffold_references.presence, select: options[:select] ) end finder_options.merge! custom_finder_options finder_options end
valid options may include:
-
:sorting - a Sorting DataStructure (basically an array of hashes of field => direction,
e.g. [{field1: 'asc'}, {field2: 'desc'}]). please note that multi-column sorting has some limitations: if any column in a multi-field sort uses method-based sorting, it will be ignored. method sorting only works for single-column sorting.
-
:per_page
-
:page
Source
# File lib/active_scaffold/finder.rb, line 565 def id_condition {active_scaffold_config.primary_key => params[:id]} if params[:id] end
Source
# File lib/active_scaffold/finder.rb, line 543 def joins_for_collection; end
Override this method on your controller to define joins to be used when querying a recordset (e.g. for List). The return of this method should be any format compatible with the :joins clause of ActiveRecord::Base
‘s find.
Source
# File lib/active_scaffold/finder.rb, line 695 def joins_for_finder case joins_for_collection when String [joins_for_collection] when Array joins_for_collection else [] end + active_scaffold_joins end
Source
# File lib/active_scaffold/finder.rb, line 717 def sort_collection_by_column(collection, column, order) sorter = column.sort[:method] collection = collection.sort_by do |record| value = sorter.is_a?(Proc) ? record.instance_eval(&sorter) : record.instance_eval(sorter.to_s) value = '' if value.nil? value end collection.reverse! if order.casecmp('DESC').zero? collection end
TODO: this should reside on the column, not the controller