Class: Mongoid::Criteria

Inherits:
Object show all
Defined in:
lib/frecon/mongoid/criteria.rb

Overview

Public: A monkey-patch for the Mongoid::Criteria class which introduces a #psv_filter method.

Instance Method Summary collapse

Instance Method Details

#psv_filter(psv_parameters = {}) ⇒ Object

Public: Filter by given PSV parameters.

PSV is an introduced system that can be used within query strings to narrow a query. Since HTTP query strings can use ‘+’ to act as spaces within a key-value pair, one can use these pluses to define nested query parameters when querying the database as in an indexing or showing request.

psv_parameters - A Hash of PSV strings to comparison values.

Examples

Record.all.psv_filter({'participation robot team number' => '2503'})
=> #<Mongoid::Criteria ...>

# Since each instance of Record has a :team shortcut method,
# we can just filter it like so.
Record.all.psv_filter({'team number' => '2503'})
=> #<Mongoid::Criteria ...>

Returns a filtered version of self.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/frecon/mongoid/criteria.rb', line 39

def psv_filter(psv_parameters = {})
	collection = self

	# Iterate through the Hash of query Strings to values, filtering using
	# each pairing where the key is the query specifier and the value is the
	# value that the last word in the query specifier is equal to.  For
	# multiple key-value pairs, just keep adding specifiers to the chain.
	psv_parameters.each do |psv_string, comparison_value|
		# Split the query String, and convert each subsequent String
		# to a symbol.  Then, reverse the array to make it easy to perform
		# an inside-out operation.
		psv_keys = psv_string.split(/\W/).map do |psv_key|
			psv_key.to_sym
		end.reverse

		# Get the final key in the query string.
		comparison_key = psv_keys.shift

		# Create a comparison hash to be used to compare <attribute> to
		# <expected value>.
		if comparison_value.length == 0 || comparison_value == '__nil__'
			comparison_hash = {comparison_key => nil}
		else
			comparison_hash = {comparison_key => comparison_value}
		end

		# Each of the subsequent keys should be a model name.  Generate a string
		# corresponding to the '<model>' + '_id' for use as the comparison key,
		# and find the model class by generating a constant.
		#
		# Then, nest a comparison around the current comparison hash.
		psv_keys.each do |model|
			model_id = (model.to_s + '_id').to_sym
			model_class = ('FReCon::' + model.to_s.capitalize).constantize

			comparison_hash = {model_id => model_class.in(comparison_hash).map(&:id)}
		end

		# Finally, complete this nested comparison.
		collection = collection.in(comparison_hash)
	end

	# Return the fully-filtered collection.
	collection
end