Summary
Within a Sinatra web app, how can I make a virtual request to the application and get the response body back as text? For example, these routes...
get('/foo'){ "foo" }
get('/bar'){ "#{spoof_request '/foo'} - bar" }
...should result in the response "foo - bar" when requesting "/bar" with the web browser.
Motivation
My application has a page representing an bug entry, with lots of details about that bug entry: what version was the bug experienced in, how important is it, what tags are associated with it, to whom is the bug assigned, etc.
The user may edit individual pieces of data on this page interactively. Using my AJAXFetch jQuery plugin, JavaScript uses AJAX to swap out a read-only section of the page (e.g. the name of the person that this bug is assigned to) with an HTML partial form for editing just that section. The user submits the form, and AJAX makes a new request for the static version of that field.
In order to be DRY, I want the Haml view that creates the page to use the exact same request that AJAX makes when creating the individual static pieces. For example:
#notifications.section
%h2 Email me if someone...
.section-body= spoof_request "/partial/notifications/#{@bug.id}"
Not-Quite-Working Code
The following helper defining spoof_request
worked under Sinatra 1.1.2:
PATH_VARS = %w[ REQUEST_PATH PATH_INFO REQUEST_URI ]
def spoof_request( uri, headers=nil )
new_env = env.dup
PATH_VARS.each{ |k| new_env[k] = uri.to_s }
new_env.merge!(headers) if headers
call( new_env ).last.join
end
Under Sinatra 1.2.3, however, this no longer works. Despite setting each of the PATH_VARS
to the desired URI, the call( new_env )
still causes Sinatra to process the route for the current request, not for the specified path. (This results in infinite recursion until the stack level finally bottoms out.)
This question differs from Calling Sinatra from within Sinatra because the accepted answer to that (old) question does not maintain the session of the user.