How to mount a Sinatra app in a Padrino app? - ruby

Resque/Sidekiq come with a web frontend, which is a Sinatra app.
The way to mount this in a Rails app is to add this to routes (http://railscasts.com/episodes/366-sidekiq?view=asciicast):
mount Sidekiq::Web, at: "/sidekiq"
How do i mount this in a Padrino app?
Mapping it in config.ru like other Rack apps does not work
map '/sidekiq' do
run Sidekiq::Web
end

Padrino uses Padrino.mount which expects apps to respond to dependencies and setup_application. This hack (https://gist.github.com/1718723) allows you to mount a Sinatra application inside a Padrino application

Padrino app is a rack app and in config.ru you would see
require ::File.dirname(__FILE__) + '/config/boot.rb'
run Padrino.application
You can change this to use Rack::URLMap
require ::File.dirname(__FILE__) + '/config/boot.rb'
run Rack::URLMap.new("/sidekiq" => Sidekiq::Web.new, "/app" => Padrino.application.new)

Add gem 'sidekiq' to Gemfile
bundle install
Add following lines to config/boot.rb
Padrino.before_load do
Padrino.dependency_paths << Padrino.root('app/workers/*.rb')
end
Add following lines to config/apps.rb
require 'sidekiq/web'
Padrino.mount('Sidekiq', app_class: 'Sidekiq::Web', app_root: Sidekiq::Web.root).to('/sidekiq')
Create any worker in app/workers/
Run bundle exec sidekiq -r ./config/boot.rb

Related

Sinatra Routing - Separate Files

I'm going through a recently released book on Sinatra that demonstrates this way of setting up routes in different files:
# app.rb
require "sinatra"
require "slim"
class Todo < Sinatra::Base
# ...
Dir[File.join(File.dirname(__FILE__), "lib", "*.rb")].each { |lib| require lib }
end
# lib/routes.rb
get "/test" do
"The application is running"
end
# config.ru
require "sinatra"
require "bundler/setup"
Bundler.require
ENV["RACK_ENV"] = "development"
require File.join(File.dirname(__FILE__), "app.rb")
Todo.start!
However, it fails to find the route at http://localhost:4567/test. It would make sense to me that this should work when I run ruby config.ru or bundle exec rackup -p 4567. But coming from Rails development where all this configuration is built-in, I don't have a complete understanding of how everything gets wired together. The server is running on that port and I get the Sinatra doesn't know this ditty 404 page. If I reopen the class as suggested by this SO answer, the /test route is found.
# lib/routes.rb
class Todo < Sinatra::Base
get "/test" do
"The application is running"
end
end
Is there something I'm missing about this suggested way to include routes without reopening the class?
Try ruby app.rb, it should work.
You'll need to restart the webserver to load routes that were added while it was running. Routes are loaded into memory when app.rb is invoked and Sinatra is launched. The route itself looks fine and it appears routes.rb is being imported successfully via Dir[File.join(File.dirname(__FILE__), "lib", "*.rb")].each { |lib| require lib }.
If you're running the server directly through terminal Ctrl+X, Ctrl+C should shut it down, then restart it via rackup config.ru* or ruby app.rb. You may confirm the route is recognized by making a get request through your browser to: http://127.0.0.1:4567/test.
For the rackup config.ru command to work, you can change config.ru to something like:
# config.ru
require './app'
run Sinatra::Application
This is just a deployment convenience.
Edit: #shaun, because Todo extends Sinatra::Base it's fine to use run Todo in your case.
The book suggested Todo.start! to run the application from the config.ru file, but the Sinatra documentation example uses run Sinatra::Application. So I just changed the line from Todo.start! to
run Todo
That seems to work, but I'll have to look into the consequences.

Sinatra exits without error

I'm very new to Sinatra, and I'm trying to get asset management & compiling working according to this article. Here is my main file so far:
require 'sinatra/base'
require 'sinatra/assetpack'
require 'sass'
class App < Sinatra::Base
register Sinatra::AssetPack
assets do
css :application, [
'/css/main.scss'
]
css_compression :sass
end
get '/hi' do
erb "Hello World!"
end
end
but, for some reason, when I run ruby main.rb, it just exits without failure or anything. Is there a special keyword to get the application to serve files?
Using the modular style of Sinatra application, as you are doing, running ruby main.rb is going to exit without error because it is being treated as a standard ruby application and no webserver is ever created.
You have two options.
1 Add run! if app_file == $0 just before the final end statement in your example.
This will allow you to run the app with ruby main.rb
2 (This is the preferred method) Create a rackup file config.ru with the following contents.
require './main.rb'
run App
Now you can serve the application with the command rackup -p 4567 where 4567 is whatever port number you want to use.
You need to start the application
require 'sinatra/base'
require 'sinatra/assetpack'
require 'sass'
class App < Sinatra::Base
register Sinatra::AssetPack
assets do
css :application, [
'/css/main.scss'
]
css_compression :sass
end
get '/hi' do
erb "Hello World!"
end
run! if app_file == $0
end
one observation, erb should point to a template, example:
get '/hi' do
erb :home
end
should look for a file in ../views/home.erb
Also Assuming you already did gem install sinatra. I would also use the rerun gem while developing in sinatra, gem install rerun then rerun ruby app.rb. Rerun will reload your project when you make changes to your code so you won't have to restart the app when ever you make a change.

Sidekiq error on required ruby file

I'm trying to start my application. Is a unicorn + foreman + sinatra application.
This is my config.ru file:
require "rubygems"
require "sinatra"
Bundler.require
require File.expand_path '../twitter_module.rb', __FILE__
run TwitterModule
require File.expand_path '../lib/tweet_streamer.rb', __FILE__
require 'sidekiq/web'
run Rack::URLMap.new('/' => Sinatra::Application, '/sidekiq' => Sidekiq::Web)
this is my sidekiq.yml:
---
:pidfile: tmp/pids/sidekiq.pid
development:
:verbose: true
:logfile: log/sidekiq_development.log
and this is my Procfile:
unicorn: bundle exec unicorn -c config/unicorn.rb
sidekiq: bundle exec sidekiq -C config/sidekiq.yml -e development -r lib/workers
The problem now is that I always give this error:
2013-10-12T15:30:23Z 28234 TID-ov4rh38wo INFO: Please point sidekiq to a Rails 3/4 application or a Ruby file
2013-10-12T15:30:23Z 28234 TID-ov4rh38wo INFO: to load your worker classes with -r [DIR|FILE].
What am I missing?
Instead of specifying the lib/workers/ directory as the -r option for sidekiq, it's necessary to point it to some file which will deal with the necessary requires and setup for your workers. For example, you might have an environment.rb file in the root of your project, requiring all the workers within the lib/workers/ directory; you'd specify this with Sidekiq by using -r ./environment.rb. It might perhaps be useful to note that Sidekiq won't load your config.ru file by itself as it doesn't use Rackup; instead, you might like to extract anything necessary to an environment.rb file or similar, and require that from within config.ru.

How to start and stop a Sinatra application using Thin on Windows?

class App < Sinatra::Base
def hello
"world"
end
end
From documentation I found that I can start the application like this:
App.run
Although this does not return the control.
How do I start the application in the background and how can I then stop it.
My environment is: Windows, Ruby 1.9.2
Use a config.ru file like Dmitry Maksimov suggested:
#config.ru
require './your_app_file'
run YourApp
And then start with rackup -D which means deamonize and therefore it runs in the background.
I wouldn't recommend this for development though. Better have a look at Shotgun
Create in the top directory of your application rackup file - config.ru - with the following content:
# config.ru
$: << File.expand_path(File.dirname(__FILE__))
require 'your app'
run Sinatra::Application
Then just run your app with the thin start

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

Resources