Friday, January 09, 2009

Rails Select Filters that Map to In Queries

Example of a Rails select box that performs filtering and is backed by an IN query. First a constant is defined in the controller. It is an array of arrays where the "first" is the text to display in the select and the "last" is an array of the values the first represents.

SERVICE_GRADE_CODE_OPTIONS = [
['Any', []],
['E01-E04', ['E01', 'E02', 'E03', 'E04']],
['E05-E07', ['E05', 'E06', 'E07']],
['E08-E09', ['E08', 'E09']],
['O01-O03', ['O01', 'O02', 'O03']],
['O04-O10', ['O04', 'O05', 'O06', 'O07', 'O08', 'O09', 'O10']],
['WO1-WO5', ['WO1', 'WO2', 'WO3', 'WO4', 'WO5']],
['Other', []]
]
view raw gistfile1.rb hosted with ❤ by GitHub


Then we render that in our page with typical code:

<label for="service_grade_code">Rank:</label>
<%= select_tag 'service_grade_code',
options_for_select EvacuationsController::SERVICE_GRADE_CODE_OPTIONS.map(&:first) %>
view raw gistfile1.rhtml hosted with ❤ by GitHub


Back in the controller, when the form is submitted, the following code sets up the conditions for a find call:

unless params[:service_grade_code].blank? || params[:service_grade_code] == 'Any'
if params[:service_grade_code] == 'Other'
conditions << ['merged_movements.service_grade_code NOT IN (?)',
SERVICE_GRADE_CODE_OPTIONS.inject([]) {|m, sgco| m + sgco.last}]
elsif codes = SERVICE_GRADE_CODE_OPTIONS.detect {|sgco| sgco.first == params[:service_grade_code]}.last
conditions << ['merged_movements.service_grade_code IN (?)', codes]
end
end
view raw gistfile1.rb hosted with ❤ by GitHub


The only somewhat interesting bit is how the conditions for "Other" are set up with an inject from the valid options defined in the SERVICE_GRADE_CODE_OPTIONS constant.