Rails 2.3.14: How to serialise an ActionController

2019-06-27 06:43发布

问题:

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!

回答1:

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.