2

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?

Community
  • 1
  • 1
Shaun
  • 2,012
  • 20
  • 44
  • Is that code straight from the book? There are quite a few issues with it. – matt Jun 24 '16 at 16:26
  • (Off topic: your SSL cert has expired.) – matt Jun 24 '16 at 16:31
  • @matt The code in the first block is all from the book, except the `require "slim"` line. Other than the lines omitted in the `app.rb` file (at `# ...`), that's everything that is given for those three files. I'd be interested to hear what the other issues with it are. Thanks for the heads up on the SSL cert. – Shaun Jun 24 '16 at 17:01
  • 1
    Wow, my opinion of Packt has gone down (another) level. Some problems: it’s mixing up [classic and modular style apps](http://www.sinatrarb.com/intro.html#Sinatra::Base%20-%20Middleware,%20Libraries,%20and%20Modular%20Apps) (this is the main issue you’re facing); having `require 'sinatra'` before setting up Bundler will give you an error if you happen to have a version of Sinatra installed newer than the one in your Gemfile; ... – matt Jun 24 '16 at 19:50
  • 1
    `Todo.start!` is the wrong way to specify the app in the `config.ru`, you should use `run Todo` (`start!` starts Sinatra’s built-in server, with the given code it might _appear_ to work with `rackup` but it won’t be doing what you think it would be doing and you will see errors after stopping the server); setting the `RACK_ENV` from the code doesn’t make much sense, the reason that’s an environment variable is so you can configure your app for different environments without changing the code. – matt Jun 24 '16 at 19:53
  • I suspected there might be some errors. I've had problems with Packt books in the past. In this one I had already come a few typos in the code and the text, plus the code files provided where actually just the same snippets included in the text, not functional applications. I was hoping to learn Sinatra and Sequel in one nice package, but I'll abandon this book spend some more time with their respective docs. Thanks for the info. – Shaun Jun 24 '16 at 20:45

3 Answers3

2

Try ruby app.rb, it should work.

delta
  • 3,778
  • 15
  • 22
  • That does work, but I think I need it to go through the `config.ru` file in order to deploy the app with passenger. – Shaun Jun 24 '16 at 15:34
1

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.

Shaun
  • 2,012
  • 20
  • 44
1

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.

Cam
  • 921
  • 7
  • 13