Sinatra Modular Application not working - ruby

I am new to Sinatra, and am learning it by following the README file. My ultimate goal is to create a modular application as described on the Sinatra Serving Modular Application page. Unfortunately, my application doesn't work - if I use config.ru it generates an error:
uninitialized constant Object::MyClass (NameError)
and modifying the code to do:
run! if app_file == $0
is not working as well. Below is my code:
my_app.rb:
require 'sinatra/base'
class MyApp < Sinatra::Base
get '/' do
test
end
def test
return "Hello World!"
end
end
config.ru:
require File.dirname(__FILE__)+'/my_app'
run Myapp.new
The commands ruby config.ru and rackup -p 4567 are not working - I receive (NameError), as I mentioned before. Does anyone have any ideas? Thank you so much.

OK, I should not be so silly to post a problem which is a typo error.
:(
Sorry guys.
run MyApp.new

I have wrote a simple tutorial about this topic.
(no ads)3
http://codex.heroku.com/past/2011/2/15/sinatrabase_in_the_modulnd/

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.

Sinatra, modular style. What did I do wrong?

I use Sinatra modular style, i don't know what going bad. I serach google but didn't find anything
require 'sinatra/base'
class App < Sinatra::Base
get '/' do
haml '%h1 Test'
end
end
run App
And a see test.rb:12:in <main>': undefined methodrun' for main:Object (NoMethodError)
What going wrong?
did you run it via ruby -rubygems hi.rb (assuming this code is in hi.rb). If so, you don't need run App. Unless you are running it through another framework built on/with Sinatra.
Also might want to include haml...
You have a config.ru:
# config.ru
require 'my_app'
run MyApp
and a my_app.rb:
# my_app.rb
require 'sinatra/base'
require 'haml'
class MyApp < Sinatra::Base
get('/') { haml '%h1 Test' }
# start the server if ruby file executed directly
run! if app_file == $0
end
then in the folder where the my_app.rb is run this to start the app on localhost:4657:
rackup -p 4567
Regarding the comment above where the error below is displayed:
`start_tcp_server': no acceptor (RuntimeError)
This appears when you are trying to bind to an already bound port. Trying a different port number should resolve.

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

Using Cucumber With Modular Sinatra Apps

I'm building out a medium-sized application using Sinatra and all was well when I had a single app.rb file and I followed Aslak's guidance up on Github:
https://github.com/cucumber/cucumber/wiki/Sinatra
As the app grew a bit larger and the app.rb file started to bulge, I refactored out a lot of of the bits into "middleware" style modules using Sinatra::Base, mapping things using a rack-up file (config.ru) etc.
The app works nicely - but my specs blew up as there was no more app.rb file for webrat to run against (as defined in the link above).
I've tried to find examples on how to work this - and I think I'm just not used to the internal guts of Cuke just yet as I can't find a single way to have it cover all the apps. I tried just pointing to "config.ru" instead of app.rb - but that doesn't work.
What I ended up doing - which is completely hackish - is to have a separate app.rb file in my support directory, which has all the requires stuff so I can at least test the model stuff. I can also specify routes in there - but that's not at all what I want to do.
So - the question is: how can I get Cucumber to properly work with the modular app approach?
Update to include dealing with multiple Sinatra apps
Require the file where your app comes together and change
def app
Sinatra::Application
end
to
def app
Rack::Builder.new do
map '/a' { run MyAppA }
map '/b' { run MyAppB }
end
end
and just test the app proper.
eg, if you define middleware in your config.ru that you want to test, maybe move loading those into your app's definition.
Thanks to Mr. BaroqueBobcat - the answer now, of course, seems so damn obvious :). Here's the env.rb (/features/support/env.rb):
require 'sinatra'
require 'test/unit'
require 'spec/expectations'
require 'rack/test'
require 'webrat'
require 'app1'
require 'app2'
require 'app3'
Webrat.configure do |config|
config.mode = :rack
end
class MyWorld
require 'test/unit'
set :environment, :test
include Rack::Test::Methods
include Webrat::Methods
include Webrat::Matchers
Webrat::Methods.delegate_to_session :response_code, :response_body, :response
def app
Rack::Builder.new do
map '/' do
run App1 #important - this is the class name
end
map '/app1' do
run App2
end
map '/app2' do
run App3
end
end
end
end
World do
MyWorld.new
end
https://gist.github.com/28d510d9fc25710192bc
def app
eval "Rack::Builder.new {( " + File.read(File.dirname(__FILE__) + '/../config.ru') + "\n )}"
end

Resources