Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reloading Sinatra app on every request on Windows

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 reload 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().

like image 260
Jakub Arnold Avatar asked Dec 17 '09 12:12

Jakub Arnold


2 Answers

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

like image 148
Konstantin Haase Avatar answered Oct 20 '22 15:10

Konstantin Haase


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
like image 40
Jan Berkel Avatar answered Oct 20 '22 16:10

Jan Berkel