module LaserLemon module SearchParty module Request def self.included(base) base.cattr_accessor :search_parameter_models base.search_parameter_models = {} base.cattr_accessor :search_parameter_finders base.search_parameter_finders = {} base.search_parameter_finders.default = :find_by_id base.cattr_accessor :search_parameter_patterns base.search_parameter_patterns = [] end def search_parameters @search_parameters ||= parse_hash(query_parameters) end private def parse_hash(hash) hash.symbolize_keys.inject({}) do |new_hash, (key, value)| parsed_value = case value when Hash then parse_hash(value) when Array then value.map{|v| parse_value(v) } else parse_value(v) end new_value = if model_name = self.class.search_parameter_models[key] model = model_name.to_s.classify.constantize finder = self.class.search_parameter_finders[key] new_values = [*parsed_value].map{|v| model.send(finder, v) } parsed_value.is_a?(Array) ? new_values.dup : new_values.first else parsed_value end new_hash.update(key => new_value) end.with_indifferent_access end def parse_value(value) if p = self.class.search_parameter_patterns.detect{|r,v| r.match(value) } (v = p.last).respond_to?(:call) ? v.call($~) : v else value end end end module Controller def self.included(base) base.attr_internal :search_params base.class_eval do alias_method_chain :assign_shortcuts, :search_party end end def assign_shortcuts_with_search_party(request, response) @_search_params = request.search_parameters assign_shortcuts_without_search_party(request, response) end end module View def self.included(base) base.delegate :search_params, :to => :controller end end end end ActionController::Request.send(:include, LaserLemon::SearchParty::Request) ActionController::Base.send(:include, LaserLemon::SearchParty::Controller) ActionView::Base.send(:include, LaserLemon::SearchParty::View)