Reloading rails middleware without restarting the server in development

做~自己de王妃 提交于 2019-12-05 03:42:42

I thought that at some point Rails was smart enough replacing middleware code at runtime, but I may be wrong.

Here is what I came up with, circumventing Ruby class loading craziness and leveraging Rails class reloading.

Add the middleware to the stack:

# config/environments/development.rb
[...]
config.middleware.use "SomeMiddleware", "some_additional_paramter"

Make use of auto-reloading, but make sure that the running rails instance and the already initialized middleware object keep "forgetting" about the actual code that is executed:

# app/middlewares/some_middleware.rb
class SomeMiddleware
  def initialize(*args)
    @args = args
  end

  def call(env)
    "#{self.class}::Logic".constantize.new(*@args).call(env)
  end

  class Logic
    def initialize(app, additional)
      @app        = app
      @additional = additional
    end

    def call(env)
      [magic]
      @app.call(env)
    end
  end
end

Changes in Logic should be picked up by rails auto reloading on each request.

I think that this actually might become a useful gem!

Building up on @phoet's answer we can actually wrap any middleware with this kind of lazy loading, which I found even more useful:

class ReloadableMiddleware
  def initialize(app, middleware_module_name, *middleware_args)
    @app = app
    @name = middleware_module_name
    @args = middleware_args
  end

  def call(env)
    # Lazily initialize the middleware item and call it immediately
    @name.constantize.new(@app, *@args).call(env)
  end
end

It can be then hooked into the Rails config with any other middleware as its first argument, given as a string:

Rails.application.config.middleware.use ReloadableMiddleware, 'YourMiddleware'

Alternatively - I packaged it into a gem called reloadable_middleware, which can be used like so:

Rails.application.config.middleware.use ReloadableMiddleware.wrap(YourMiddleware)

Can you not simply use shotgun? If I understand your question you want to ensure the environment reloads on every change you make to your code. That is what shotgun will do.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!