Sinatra method `development?` undefined - ruby

The Sinatra docs say that development? will return true when the environment is development, but I receive an error stating that the method development? is undefined.
I tried skipping the shorthand and testing the ENV['RAKE_ENV'] variable itself, but it was just nil.
This is the error I'm getting:
undefined method `development?' for main:Object (NoMethodError)
and this is the code that is triggering the error:
require 'dm-sqlite-adapter' if development?
I am using the modular style app. The line above is an separate file that only manages the model. What's going on?

I struggled with this one, too. Here's what I discovered along the way.
You need to be "inside" a class that inherits from Sinatra::Base (such as Sinatra::Application, which inherits from Base) to be able to use the development? method, which is defined in base.rb.
In a classic Sinatra app you are already coding "inside" a class that inherits from Sinatra::Base. So development? will just work "anywhere".
In modular Sinatra the development? will only work in Sinatra::Base sub-classes, such as:
require 'sinatra/base'
# Placing
# require 'dm-sqlite-adapter' if development?
# here will not work.
class ApplicationController < Sinatra::Base
require 'dm-sqlite-adapter' if development? # But here it works
...
end
# Placing
# require 'dm-sqlite-adapter' if development?`
# AFTER the above class will still not work
class SomethingElse
# nor will `development?` work here, since it is called inside
# a class without Sinatra::Base inheritance
...
end
So basically you can use an ApplicationController class that inherits from Sinatra::Base and inside here check for development?. The same goes for sub-classes that inherits from your ApplicationController class:
class UserController < ApplicationController
require 'dotenv' if development?
...
end
For modular Sinatra, in the (main:Object) code text "outside" Sinatra::Base sub-classes, you need to follow Arup's instructions:
if Sinatra::Base.environment == :development
require 'awesome_print'
require 'dotenv'
Dotenv.load
...
end

Since you are using the modular style, you need to add the module namespace Sinatra::Base before the method.
So you will be able to access Sinatra::Base.development? anywhere in the app.

Related

Error handlers don't run in modular Sinatra app

I have a Sinatra application that uses the modular style. Everything works fine apart from my error handler blocks which don't get invoked. Here's the relevant code:
app.rb
require_relative './routes/base'
require_relative './routes/routing'
module Example
class App < Sinatra::Application
use Routes::Base
use Routes::Routing
end
end
base.rb
require 'sinatra/base'
module Example
module Routes
class Base < Sinatra::Application
configure do
# etc.
end
# Error pages.
error 404 do # <- Doesn't get invoked.
erb :not_found
end
error 500 do # <- Doesn't get invoked.
erb :internal_server_error
end
end
end
end
routing.rb
module Example
module Routes
class Routing < Base
get '/?' do
erb :home
end
end
end
end
Why don't my error handlers work?
Thanks in advance.
The use method is for adding middleware to an app, you can’t use it to compose an app like this.
In your example you actually have three different Sinatra applications, two of which are being run as middleware. When a Sinatra app is run as middleware then any request that matches one of its routes is handled by that app, otherwise the request is passed to the next component in the Rack stack. Error handlers will only apply if the request has been handled by the same app. The app that you have defined the error handlers in has no routes defined, so all requests will be passed on down the stack — the error handlers will never be used.
One way to organise a large app like this would be to simply use the same class and reopen it in the different files. This other question has an example that might be useful: Using Sinatra for larger projects via multiple files.

Sinatra routes not working in modular app?

I've converted a classic Sinatra application to a modular application. Now suddenly my put, patch and delete routes stopped working. get and post work fine. Is there something I need to do to get these to work in a modular app that is different from classic?
%form{action: "/addsomething", method: 'post'}
%input{type: 'hidden', name: '_method', value: 'put'}
I get a 404 now when I attempt to access one of the above mentioned routes.
require 'sinatra/base'
class MyClass < Sinatra::Base
put '/addsomething' do
'HELLO WORLD!'
end
get '/hello' do
'hello world'
end
end
The method_override setting (that allows the _method field to override the HTTP method) is false by default in modular style. You need to enable it with:
enable :method_override
You can still inherit from Sinatra::Application in the modular style to keep the default settings:
require 'sinatra/base'
class MyClass < Sinatra::Application
put '/addsomething' do
'HELLO WORLD!'
end
get '/hello' do
'hello world'
end
end

Can't load my custom module in Sinatra

I am trying to load my custom module in Sinatra but when loading the app I get
'include' : Wrong argument type String (expected Module)
So in my app.rb I have
require './config/config.rb'
include 'MyConfig'
and my Module looks like so
module MyConfig
def config
environment = ENV["RACK_ENV"] || "development"
YAML.load_file("/config/config.yml")[environment]
end
end
I am trying to use the config.yml file to load some variables (i.e email credentials).
What am I doing wrong?
include is not like require. Include must be part of another class or Module body.
Do this:
require './config/config.rb'
class App
include MyConfig
# more code here
end
Include basically functions as an inline extension of the class or module that is currently in scope. It allows you to mix functionality into objects from external code without extending that external code.

Why is "url_for" undefined in my application?

I'm trying to use the url_for extension so my app can accurately find my static assets (tried the static assets extension as well, but it also complained of this same problem).
The problem is this:
undefined method `url_for' for Sinatra::Raffler:Class (NoMethodError)
Now, I've got the required modules listed, as per the url_for README:
require 'rubygems'
require 'sinatra/base'
require 'data_mapper'
require 'lib/authorization'
require 'pony'
gem 'emk-sinatra-url-for'
require 'sinatra/url_for'
But I'm still getting the NoMethodError when I try to call url_for
I have tried a couple of different things in regards to helpers. First, I have a helpers block for an authorization extension:
helpers do
include Sinatra::Authorization
end
So, I thought I could include the url_for helper in there:
helpers do
include Sinatra::Authorization
include Sinatra::UrlForHelper
end
But that didn't resolve the issue, so I just added the line:
helpers Sinatra::UrlForHelper
after that initial helpers do block, but still no resolution.
If you are subclassing Sinatra::Base, you need to include the helpers explicitly:
class Foobar < Sinatra::Base
helpers Sinatra::UrlForHelper
end

Scaffolding Extensions: NoMethodError

Not sure if many people are familiar with Scaffolding Extensions for Ruby, but I've looked through their docs, forums, and even the source code of the Heroku test site, and not found an answer.
I made a basic Sinatra app and followed right from the RDoc's instructions:
require 'scaffolding_extensions'
require 'sinatra/base'
class Thingy < Sinatra::Base
scaffold_all_models
end
gives
undefined method 'scaffold_all_models' for Thingy:Class (NoMethodError)
and I know Scaffolding Extensions is loadable because I can successfully set some config variables in its classes.
This works for me:
require 'sinatra/base'
require 'scaffolding_extensions'
class Thingy < Sinatra::Base
scaffold_all_models
end

Resources