I need to write some methods that Do Things based on the kind of request object received by a Rails 2.3.14 controller. However, I don't want to fire up the entire application, nor even a controller; I'd like to have just a marshalled copy of such an object that I can work with outside of the Rails environment.
Unfortunately, the ActionController::Request
objects passed to controllers include, deep in their bowels, Proc
objects which are inherently unserialisable.
Does anyone know of a way to serialise one of these objects such that I can store it away in a data file and re-create it in another script? I would prefer not to monkey-patch the Proc
class to provide a #marshal_dump
method..
Thanks!
The trick is to replace/delete not serializable objects (especially in the env-hash). I implemented parts of it in this SO answer. I slightly updated my approach using a rails 3.2.13 request
object.
##
# build a serializable hash out of the given request object
def make_request_serializable(request)
request_hash = {
:env => request.env.clone,
:filtered_parameters => request.filtered_parameters.clone,
:fullpath => request.fullpath,
:method => request.method,
:request_method => request.request_method
}
#clean up the env-hash, as it contains not serializable objects
request_hash[:env].tap do |env|
env.delete "action_dispatch.routes"
env.delete "action_dispatch.logger"
env.delete "action_controller.instance"
env.delete "rack.errors"
env["action_dispatch.remote_ip"] = env["action_dispatch.remote_ip"].to_s
end
request_hash
end
# later in the controller
puts make_request_serializable(request).to_json
#=> {"env":{"SERVER_SOFTWARE":"thin 1.5.1 codename Straight Razor","SERVER_NAME":"localhost","rack.input":[],"rack.version":[1,0], ... (shortened, as it's a lot of output)
Update: owww, I've just seen that you are asking vor Rails 2.3.14
. My visual filter let me see 3.2.14
instead. So this only works for a current rails version, sorry.