lib/roda/plugins/indifferent_params.rb
# frozen-string-literal: true # class Roda module RodaPlugins # The indifferent_params plugin adds a +params+ instance # method which offers indifferent access to the request # params, allowing you to use symbols to lookup values in # a hash where the keys are strings. Note that while this # allows for an easier transition from some other ruby frameworks, # it is a bad idea in general as it makes it more difficult to # separate external data from internal data, and doesn't handle # any typecasting of the data. Consider using the typecast_params # plugin instead of this plugin for accessing parameters. # # Example: # # plugin :indifferent_params # # route do |r| # params[:foo] # end # # The exact behavior depends on the version of Rack in use. # If you are using Rack 2, this plugin uses rack's API # to set the query parser for the request to use indifferent # access. Rack 1 doesn't support indifferent access to # params, so if you are using Rack 1, this plugin will make # a deep copy of the request params hash, where each level # uses indifferent access. On Rack 1, The params hash is # initialized lazily, so you only pay the penalty of # copying the request params if you call the +params+ method. # # Note that there is a rack-indifferent gem that # monkey patches rack to always use indifferent params. If # you are using Rack 1, it is recommended to use # rack-indifferent instead of this plugin, as it is faster # and has some other minor advantages, though # it affects all rack applications instead of just the Roda app that # you load the plugin into. module IndifferentParams INDIFFERENT_PROC = lambda{|h,k| h[k.to_s] if k.is_a?(Symbol)} if Rack.release > '2' require 'rack/query_parser' class QueryParser < Rack::QueryParser # Work around for invalid optimization in rack def parse_nested_query(qs, d=nil) return make_params.to_params_hash if qs.nil? || qs.empty? super end class Params < Rack::QueryParser::Params if Rack.release >= '3' if Params < Hash def initialize super(&INDIFFERENT_PROC) end else def initialize @size = 0 @params = Hash.new(&INDIFFERENT_PROC) end end else def initialize(limit = Rack::Utils.key_space_limit) @limit = limit @size = 0 @params = Hash.new(&INDIFFERENT_PROC) end end end end module RequestMethods query_parser = Rack.release >= '3' ? QueryParser.new(QueryParser::Params, 32) : QueryParser.new(QueryParser::Params, 65536, 32) QUERY_PARSER = Rack::Utils.default_query_parser = query_parser private def query_parser QUERY_PARSER end end module InstanceMethods def params @_request.params end end else module InstanceMethods # A copy of the request params that will automatically # convert symbols to strings. def params @_params ||= indifferent_params(@_request.params) end private # Recursively process the request params and convert # hashes to support indifferent access, leaving # other values alone. def indifferent_params(params) case params when Hash hash = Hash.new(&INDIFFERENT_PROC) params.each{|k, v| hash[k] = indifferent_params(v)} hash when Array params.map{|x| indifferent_params(x)} else params end end end end end register_plugin(:indifferent_params, IndifferentParams) end end