1

All was well with my app until I refactored it into multiple controllers/server.

I believe I am using the modular set up with Sinatra-Base. I believe I have defined my Rack ENVs right.

I have a problem. I cannot run rspec without starting up Sinatra in my command line. When I fix this problem by commenting out the 'run!' command at the bottom of my server file, obviously Sinatra will not start up when I try and run my app from the command line.

Here is my file structure:

app
   app.rb
   server.rb
   datamapper_setup.rb
    controllers
      new_users.rb
      sessions.rb
    views
      various.erb
      files.erb
    models
      user.rb
spec
   features
       feature_test_spec.rb
       other_feature_test_spec.rb
   units
       unit_test_spec.rb
   spec_helper.rb
config.ru
.rspec
Gemfile
Rakefile

Here is my config.ru file

require './app/app.rb'

run MyApp

Here is my app.rb file

ENV['RACK_ENV'] ||= 'development'
require 'rack'
require 'sinatra/base'
require 'sinatra/flash'
require 'sinatra/partial'


require_relative 'data_mapper_setup'

require_relative 'server'
require_relative 'controllers/new_users'
require_relative 'controllers/sessions'

Here is my server file

class App < Sinatra::Base
  register Sinatra::Flash
  register Sinatra::Partial
  enable :sessions
  set :session_secret, 'super secret'
  set :partial_template_engine, :erb


  helpers do
    def session_user
      @session_user ||= User.get(session[:user_id])
    end
  end


  get '/' do
    @new_user = User.new
    erb :'user/index'
  end
#Here is where I am commenting out run! in order to be able to run rspec without starting Sinatra. 
# It doesn't work at all if I have => run! if app_file == $0 now, but used to work before the refactor when this line was in my app file.  

run!
end

In my spec helper:

ENV['RACK_ENV'] = 'test'

require File.join(File.dirname(__FILE__), '..', 'app/app.rb')
require './app/app.rb'

require 'capybara'
require 'capybara/rspec'
require 'rspec'

require 'database_cleaner'

require 'coveralls'
require 'simplecov'
require './app/data_mapper_setup.rb'
require './spec/web_helpers.rb'

SimpleCov.formatters = [
  SimpleCov::Formatter::HTMLFormatter,
  Coveralls::SimpleCov::Formatter
]
Coveralls.wear!


Capybara.app = App



RSpec.configure do |config|

  config.include SessionHelpers

  config.before(:suite) do
    DatabaseCleaner.strategy = :transaction
    DatabaseCleaner.clean_with(:truncation)
  end

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end

  config.include Capybara::DSL

  config.expect_with :rspec do |expectations|

    expectations.include_chain_clauses_in_custom_matcher_descriptions = true
  end


  config.mock_with :rspec do |mocks|

    mocks.verify_partial_doubles = true
  end

end

All my rspec tests are passing.

What I have tried...

  1. Various different config.ru set ups
  2. Spec_helper with require 'rack' differently
  3. Checking my rack environments are isolated in my database
  4. Trying to understand the difference between Sinatra Modular and Sinatra Classical styles (with limited success)
Viola Crellin
  • 61
  • 2
  • 8
  • Could you expand on why you need the call to `run!` in the first place? When you comment it out, what are you unable to do? – georgebrock Feb 14 '16 at 14:35
  • Hi @georgebrock - need the run! to be able to run Sinatra from my command line and gain access to my localhost port. However, having this there causes Rspec to run Sinatra every time I run my tests. – Viola Crellin Feb 14 '16 at 16:14

1 Answers1

4

Calling .run! every time the app.rb file is what's causing you problems.

There are two good solutions to this:

Only call .run when you run app.rb directly

You could avoid calling .run! when you don't need to by wrapping it in a conditional to check that the app.rb file has been run directly and not loaded by some other file. That would look something like this:

class App < Sinatra::Base
  # …

  if __FILE__ == $0
    run!
  end
end

Let's break this down:

  • __FILE__ is the path to the current file.
  • $0 is the path to the Ruby script you ran from the command line.

With this conditional in place, running ruby app.rb from the command line will trigger the call to .run!, but running other commands (like rackup or rspec) will mean $0 doesn't match __FILE__, so .run! will never be called.

Run the local server via rackup

An alternative solution to the problem would be to remove the call to .run! completely, and start your local development server using the rackup command.

Since you already have a config.ru file, you should be able to run rackup with no arguments to get a running development server.

This would be my preferred method, because it means that if you want to add more rack middleware to the application (e.g. to authenticate users, or serve static files) you can add them to your config.ru file you you'll be running them in both development and production.

More reading

Community
  • 1
  • 1
georgebrock
  • 28,393
  • 13
  • 77
  • 72
  • Hi George, Thanks for your answer. The problem is that when I put the if clause in there Rspec will start up sinatra from my command line when I try to run my tests. – Viola Crellin Feb 15 '16 at 21:23