开发者

Reloading Sinatra app on every request on Windows

开发者 https://www.devze.com 2022-12-14 11:34 出处:网络
I\'ve set up Rack::Reload according to this thread # config.ru require \'rubygems\' require \'sinatra\' set :environment, :development

I've set up Rack::Reload according to this thread

# config.ru
require 'rubygems'
require 'sinatra'

set :environment, :development

require 'app'
run Sinatra::Application

# app.rb  
class Sinatra::Reloader < Rack::Reloader
  def safe_load(file, mtime, stderr = $stderr)
    if file == Sinatra::Application.app_file
      ::Sinatra::Application.reset!
      stderr.puts "#{self.class}: reseting routes"
    end
    super
  end
end

configure(:development) { use Sinatra::Reloader }

get '/' do
  'foo'
end

Running with thin via thin start -R config.ru, but it only reloads newly added routes. When I change already existing route, it still runs the old code.

When I add new route, it correctly reloads it, so it is accessible, but it doesn't rel开发者_开发问答oad anything else.

For example, if I changed routes to

get '/' do
  'bar'
end

get '/foo' do
  'baz'
end

Than / would still serve foo, even though it has changed, but /foo would correctly reload and serve baz.

Is this normal behavior, or am I missing something? I'd expect whole source file to be reloaded. The only way around I can think of right now is restarting whole webserver when filesystem changes.

I'm running on Windows Vista x64, so I can't use shotgun because of fork().


You could try sinatra-reloader, which is known to work well on Windows (also, it's faster than shotgun).


This works:

# config.ru
require 'rubygems'
require 'app'

set :environment, :development
run Sinatra::Application

# app.rb  
require 'sinatra'

class Sinatra::Reloader < Rack::Reloader
  def safe_load(file, mtime, stderr = $stderr)
    if file == File.expand_path(Sinatra::Application.app_file)
      ::Sinatra::Application.reset!
      stderr.puts "#{self.class}: reseting routes"
    end
    super
  end
end

configure(:development) { use Sinatra::Reloader }

get '/' do
  'foo'
end

It matters from where you have the require statement. But I find the following solution more elegant and robust:

# config.ru
require 'rubygems'
require 'sinatra'
require 'rack/reloader'
require 'app'

set :environment, :development

use Rack::Reloader, 0 if development?
run Sinatra::Application

# app.rb  
Sinatra::Application.reset! 
get '/' do
  'foo'
end


Does Shotgun not work on Windows?

From the README:

                                Shotgun

This is an automatic reloading version of the rackup command that's shipped with Rack. It can be used as an alternative to the complex reloading logic provided by web frameworks or in environments that don't support application reloading.

The shotgun command starts one of Rack's supported servers (e.g., mongrel, thin, webrick) and listens for requests but does not load any part of the actual application. Each time a request is received, it forks, loads the application in the child process, processes the request, and exits the child process. The result is clean, application-wide reloading of all source files and templates on each request.


You can also try using Trinidad a JRuby Rack container based on Tomcat. In my experience it does change reloading by default without having to modify your source files. Bloody fast too. Obviously no good if you are using native libraries, but if you are deploying on Windows you are probably used to adopting a pure-ruby approach.

Its syntax is just as simple as the thin approach:

jruby -S trinidad -r config.ru

There is no Java specific yak shaving (i.e. creating web.xml or WARing up your Ruby app) and the gem is simple to install.

0

精彩评论

暂无评论...
验证码 换一张
取 消