require 'criterion' require 'restrictions' module Criteria # Represents a query constructed out of #Criterion objects. # Query is itself a criterion and thus exposes all restriction helper methods class Query < CriterionContainer attr_accessor :limit attr_accessor :offset attr_reader :model_class # Construct a new query for the given _model_class_ def initialize(model_class) super() @model_class = model_class @join_aliases = {} @join_aliases[model_class.table_name] = model_class.table_name yield self if block_given? end # builds the correct join alias for association includes # the table name is determined by reflecting on the parent model classes' attributes # if this is the first time this table is used in the query, user the table name as the alias # for subsequent uses, uses _[_index] where index is only used if the same association is used more than once (see ActiveRecord::Associations::Base) def join_alias(reflection, model_class, parent_model_class) table_name = model_class.table_name new_alias = table_name if @join_aliases[table_name] new_alias = "#{reflection.pluralize}_#{parent_model_class.table_name}" if @join_aliases[table_name].include? new_alias new_alias += '1' while @join_aliases[table_name].include? new_alias new_alias = new_alias.succ end end end (@join_aliases[table_name] ||= []) << new_alias return new_alias end # execute the finder query. def find(options={}) @model_class.send('find', :all, build_query(options)) end def query self end # returns the table prefix for this model def prefix @model_class.name.pluralize.underscore end private # builds the AR query conditions, parameters and includes def build_query(options={}) conditions = build_conditions includes = joins query_params = options query_params[:conditions] = conditions if conditions && !conditions.empty? query_params[:include] = includes if includes && !includes.empty? p query_params if $DEBUG query_params end def build_conditions con = condition nil unless con par = params ([con].concat par).compact end end end