@@ -18,6 +18,7 @@ class Configuration
1818 attr_accessor :before_sideload
1919
2020 attr_reader :debug , :debug_models
21+ attr_reader :uri_decoder
2122
2223 attr_writer :schema_path
2324 attr_writer :cache_rendering
@@ -37,6 +38,8 @@ def initialize
3738 self . debug = ENV . fetch ( "GRAPHITI_DEBUG" , true )
3839 self . debug_models = ENV . fetch ( "GRAPHITI_DEBUG_MODELS" , false )
3940
41+ @uri_decoder = infer_uri_decoder
42+
4043 # FIXME: Don't duplicate graphiti-rails efforts
4144 if defined? ( ::Rails . root ) && ( root = ::Rails . root )
4245 config_file = root . join ( ".graphiticfg.yml" )
@@ -85,6 +88,33 @@ def with_option(key, value)
8588 ensure
8689 send ( :"#{ key } =" , original )
8790 end
91+
92+ def uri_decoder = ( decoder )
93+ unless decoder . respond_to? ( :call )
94+ raise "uri_decoder must respond to `call`."
95+ end
96+
97+ @uri_decoder = decoder
98+ end
99+
100+ private
101+
102+ def infer_uri_decoder
103+ if defined? ( ::ActionDispatch ::Journey ::Router ::Utils )
104+ # available in all supported versions of Rails.
105+ # This method should be preferred for comparing URI path segments
106+ # to params, as it is the exact decoder used in the Rails router.
107+ @uri_decoder = ::ActionDispatch ::Journey ::Router ::Utils . method ( :unescape_uri )
108+ elsif URI . respond_to? ( :decode_uri_component )
109+ # available in Ruby >= 3.2
110+ @uri_decoder = URI . method ( :decode_uri_component )
111+ end
112+ rescue => e
113+ Kernel . warn ( "Error inferring Graphiti uri_decoder: #{ e } " )
114+ ensure
115+ # fallback
116+ @uri_decoder ||= :itself . to_proc
117+ end
88118 end
89119
90120 msg = "Use graphiti-rails's `config.graphiti.respond_to_formats`"
0 commit comments