module ActiveScaffold::Finder

Constants

NullComparators
NumericComparators
StringComparators

Attributes

active_scaffold_conditions[W]
active_scaffold_habtm_joins[W]
active_scaffold_includes[W]

Protected Instance Methods

active_scaffold_conditions() click to toggle source
# File lib/active_scaffold/finder.rb, line 254
def active_scaffold_conditions
  @active_scaffold_conditions ||= []
end
active_scaffold_habtm_joins() click to toggle source
# File lib/active_scaffold/finder.rb, line 264
def active_scaffold_habtm_joins
  @active_scaffold_habtm_joins ||= []
end
active_scaffold_includes() click to toggle source
# File lib/active_scaffold/finder.rb, line 259
def active_scaffold_includes
  @active_scaffold_includes ||= []
end
all_conditions() click to toggle source
# File lib/active_scaffold/finder.rb, line 268
def all_conditions
  [
    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_session_storage[:conditions] # embedding conditions (weaker constraints)
  ]
end
append_to_query(query, options) click to toggle source
# File lib/active_scaffold/finder.rb, line 358
def append_to_query(query, options)
  options.assert_valid_keys :where, :select, :group, :reorder, :limit, :offset, :joins, :includes, :lock, :readonly, :from, :conditions
  query = apply_conditions(query, *options.delete(:conditions)) if options[:conditions]
  options.reject{|k, v| v.blank?}.inject(query) do |query, (k, v)|
    query.send((k.to_sym), v) 
  end
end
apply_conditions(query, *conditions) click to toggle source
# File lib/active_scaffold/finder.rb, line 377
def apply_conditions(query, *conditions)
  conditions.reject(&:blank?).inject(query) do |query, condition|
    if condition.is_a?(Array) && !condition.first.is_a?(String) # multiple conditions
      apply_conditions(query, *condition)
    else
      query.where(condition)
    end
  end
end
calculate(column) click to toggle source
# File lib/active_scaffold/finder.rb, line 350
def calculate(column)
  conditions = all_conditions
  includes = active_scaffold_config.list.count_includes
  includes ||= active_scaffold_includes unless conditions.nil?
  append_to_query(beginning_of_chain, :conditions => conditions, :includes => includes,
    :joins => joins_for_collection).calculate(column.calculate, column.name)
end
count_items(find_options = {}, count_includes = nil) click to toggle source
# File lib/active_scaffold/finder.rb, line 304
def count_items(find_options = {}, count_includes = nil)
  count_includes ||= find_options[:includes] unless find_options[:conditions].nil?
  options = find_options.reject{|k,v| [:select, :reorder].include? k}
  options[:includes] = count_includes
  
  # NOTE: we must use :include in the count query, because some conditions may reference other tables
  count_query = append_to_query(beginning_of_chain, options)
  count = count_query.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? ActiveSupport::OrderedHash
  count
end
find_if_allowed(id, crud_type, klass = beginning_of_chain) click to toggle source

returns a single record (the given id) but only if it’s allowed for the specified action. accomplishes this by checking model.#{action}_authorized? TODO: this should reside on the model, not the controller

# File lib/active_scaffold/finder.rb, line 281
def find_if_allowed(id, crud_type, klass = beginning_of_chain)
  record = klass.find(id)
  raise ActiveScaffold::RecordNotAllowed, "#{klass} with id = #{id}" unless record.authorized_for?(:crud_type => crud_type.to_sym)
  return record
end
find_page(options = {}) click to toggle source

returns a Paginator::Page (not from ActiveRecord::Paginator) for the given parameters See #finder_options for valid options

# File lib/active_scaffold/finder.rb, line 321
def find_page(options = {})
  options.assert_valid_keys :sorting, :per_page, :page, :count_includes, :pagination
  options[:per_page] ||= 999999999
  options[:page] ||= 1

  find_options = finder_options(options)
  
  # 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(find_options, options[:count_includes])
  end

  klass = beginning_of_chain
  # we build the paginator differently for method- and sql-based sorting
  if options[:sorting] and options[:sorting].sorts_by_method?
    pager = ::Paginator.new(count, options[:per_page]) do |offset, per_page|
      sorted_collection = sort_collection_by_column(append_to_query(klass, find_options).all, *options[:sorting].first)
      sorted_collection = sorted_collection.slice(offset, per_page) if options[:pagination]
      sorted_collection
    end
  else
    pager = ::Paginator.new(count, options[:per_page]) do |offset, per_page|
      find_options.merge!(:offset => offset, :limit => per_page) if options[:pagination]
      append_to_query(klass, find_options).all
    end
  end
  pager.page(options[:page])
end
finder_options(options = {}) click to toggle source

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

# File lib/active_scaffold/finder.rb, line 290
def finder_options(options = {})
  search_conditions = all_conditions
  full_includes = (active_scaffold_includes.blank? ? nil : active_scaffold_includes)

  # create a general-use options array that's compatible with Rails finders
  finder_options = { :reorder => options[:sorting].try(:clause),
                     :conditions => search_conditions,
                     :joins => joins_for_finder,
                     :includes => full_includes}

  finder_options.merge! custom_finder_options
  finder_options
end
joins_for_finder() click to toggle source
# File lib/active_scaffold/finder.rb, line 366
def joins_for_finder
  case joins_for_collection
    when String
      [ joins_for_collection ]
    when Array
      joins_for_collection
    else
      []
  end + active_scaffold_habtm_joins
end
sort_collection_by_column(collection, column, order) click to toggle source

TODO: this should reside on the column, not the controller

# File lib/active_scaffold/finder.rb, line 388
def sort_collection_by_column(collection, column, order)
  sorter = column.sort[:method]
  collection = collection.sort_by { |record|
    value = (sorter.is_a? Proc) ? record.instance_eval(&sorter) : record.instance_eval(sorter)
    value = '' if value.nil?
    value
  }
  collection.reverse! if order.downcase == 'desc'
  collection
end

Public Class Methods

included(klass) click to toggle source
# File lib/active_scaffold/finder.rb, line 247
def self.included(klass)
  klass.extend ClassMethods
end
like_operator() click to toggle source
# File lib/active_scaffold/finder.rb, line 3
def self.like_operator
  @@like_operator ||= ::ActiveRecord::Base.connection.adapter_name == "PostgreSQL" ? "ILIKE" : "LIKE"
end