How to test modular Sinatra apps with Rack::Test
Let’s say you have this in your config.ru:
1 run Rack::URLMap.new \ 2 "/" => HomeController.new, 3 "/user" => UserController.new
and you want to test both / and /user at the same time.
The solution is to return an instance of Rack::Builder instead of, for example, HomeController, which this snippet does by reading config.ru and evaluating it:
1 def app 2 eval "Rack::Builder.new {( " + File.read(File.dirname(__FILE__) + '/../config.ru') + "\n )}" 3 end
The code was found on the internets.
How to create a JSONP cross-domain webservice with Sinatra and Ruby
Your Sinatra app:
1 get '/' do 2 callback = params.delete('callback') # jsonp 3 json = {'your' => 'data'}.to_json 4 5 if callback 6 content_type :js 7 response = "#{callback}(#{json})" 8 else 9 content_type :json 10 response = json 11 end 12 response 13 end
Your HTML:
1 <script type="text/javascript"> 2 function parseResponse(json) { 3 // Do something with the data 4 } 5 </script> 6 <script type="text/javascript" src="http://xxx.com/?callback=parseResponse"></script>
You can also do the same with jQuery:
1 $.ajax({ 2 type: 'get', 3 url: '/', 4 dataType: 'jsonp', 5 success: function(data) { 6 parseResponse(data); 7 } 8 })
How to fix "can't activate rack (= 0.9.1, runtime), already activated rack-1.0.0"
The current version of Sinatra (0.9.2) requires Rack version 0.9.1:
1 require 'rubygems' 2 gem "rack", "0.9.1" 3 require 'sinatra'
My Sinatra+Capistrano+Capinatra deployment recipe
1 require 'capistrano/version' 2 require 'rubygems' 3 require 'capinatra' 4 load 'deploy' if respond_to?(:namespace) # cap2 differentiator 5 6 # set an app_class if you're using the more recent style of creating 7 # Sinatra apps, where app_class would be the name of your subclass 8 # of Sinatra::Base. if you're just requiring 'sinatra' and using the 9 # more traditional DSL style of Sinatra, then comment this line out. 10 set :app_class, 'xxx' 11 12 # standard settings 13 set :app_file, "xxx.rb" 14 set :application, "xxx" 15 set :domain, "xxx.com" 16 role :app, domain 17 role :web, domain 18 role :db, domain, :primary => true 19 20 set :ssh_options, { :forward_agent => true } 21 22 #set :use_sudo, false 23 24 # environment settings 25 set :user, "xxx" 26 set :group, "www-data" 27 set :deploy_to, "/var/www/#{application}" 28 set :deploy_via, :copy #:remote_cache 29 default_run_options[:pty] = true 30 31 # scm settings 32 set :repository, "git@xxx.com:xxx.git" 33 #set :repository, "file:///home/git/repositories/xxx.git" 34 set :scm, "git" 35 set :branch, "master" 36 set :git_enable_submodules, 1 37 38 # where the apache vhost will be generated 39 set :apache_vhost_dir, "/etc/apache2/sites-enabled/" 40 41 namespace :deploy do 42 task :restart do 43 run "touch #{current_path}/tmp/restart.txt" 44 end 45 end
Testing sessions with Sinatra and Rack::Test
You need support for testing sessions when, for example, testing authentication. The only way I’ve managed to get sessions to work with Sinatra and Rack::Test is by going through the whole stack, in other words calling the authentication controller as shown here:
1 @user = Factory(:user) # create a dummy user 2 User.expects(:authenticate).with(any_parameters).returns(@user) # make authenticate return the dummy user 3 post "/sign-in", {:email => @user.email, :password => @user.password} # login to the application and set a session variable.
After this the session populated and we’re logged in when accessing the application again:
1 post "/articles", {:title => 'Sessions suck', :body => '...'}
On a side note, there are two ways of specifying sessions that used to work, but which no longer work with Sinatra 1.0:
1 get '/', :env => { :session => {:abc => 'adf'} } 2 get '/', {}, :session => {:abc => 'adf'} 3 get '/', {}, "rack.session" => {:abc => 'adf'}
The session is always empty.
There are many discussions about sessions and Rack::Test, but not one of them has a solution that works for me: