Rack/Sinatra Method Not Allowed - ruby

I am developing a simple web app using Sinatra and using rack as the middleware and hence have a config.ru.
To run the application I use shotgun config.ru.
I have no problem when the application does a GET request. But my app has a couple of POST requests, and when I submit a form via POST method, I get this strange error:
Method Not Allowed
Following is the content of my config.ru:
require "rack"
require 'rack/contrib/try_static'
require File.expand_path("app", File.dirname(__FILE__))
use Rack::TryStatic, :root => File.join(App::SETTINGS.source, App::SETTINGS.site.config['destination']), :urls => %w[/]
run App
Any idea what could resolve the issue?
Thank You

The following will not respond to posts:
get '/hi' do
"Hello World!"
end
It is quite possible that you will need to do something like this:
post '/hi' do
# do post stuff
end

I solved the issue.
It was a problem with rack.
I replaced
use Rack::TryStatic,
:root => File.join(App::SETTINGS.source, App::SETTINGS.site.config['destination']),
:urls => %w[/]
with:
use Rack::Static,
:urls => ["/#{App::SETTINGS.site.config['destination']}"],
:root => File.join(App::SETTINGS.source, App::SETTINGS.site.config['destination'])

Related

Redis not working in sinatra rake tasks

I would like to user Redis in my Sinatra app. Though I can access Redis instance in the console on local and remote (heroku), when I want to use it in a rake task, an error is triggered and I don t seem to get why is that.
app.rb:
class MyApp < Sinatra::Base
configure do
uri = URI.parse(ENV["REDISCLOUD_URL"])
$redis = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
end
end
config.ru:
require 'rubygems'
require 'sinatra'
require './app'
run MyApp
Gemfile
gem 'redis'
Rakefile.rb
desc 'Try Redis'
task :try_redis do
puts $redis.set("try", 0)
end
rake aborted! NoMethodError: undefined method `set' for nil:NilClass
I am not really used to Sinatra, and nothing looks particularly wrong to me. I do not understand why my global variable $redis would not be accessible from everywhere in my app...
If you can enlighten me, thank you by advance!
I do not understand why my global variable $redis would not be
accessible from everywhere in my app
Your rake task is not related to your app. The $redis variable available only when you run sinatra server and not available when you run your rake task. The rake task run in own thread.

Sinatra app with multiple controllers: how do I tell rspec what the routes are?

I'm working on an existing sinatra app that spans a number of controllers. These are currently routed in the config.ru file like so:
require 'bundler'
Bundler.require(:default)
=begin
# The gem file includes these:
gem 'rack' , '1.5.2', :groups => [:default, :test]
gem 'rack-accept' , '0.4.5'
gem 'rack-mount' , '0.8.3'
gem 'rack-protection' , '1.5.1'
gem 'rack-test' , '0.6.2', :groups => [:test]
=end
use Rack::ContentType
maps = {
'/' => RootController,
'/users' => UsersController,
'/animals' => AnimalsController,
}
maps.each do |path, controller|
map(path){ run controller}
end
This file is launched via config.ru (under Thin). But test files don't run under rackup (or Thin).
How do I load the controllers under rspec?
The problem is that when I put a 'get "/PATH"' or 'post' in my tests, Ruby complains about an
argument mismatch (2 for 0). If the 'get' has no argument, Ruby gives a different argument
mismatch (0 for 1). They're both sort of wrong -- get takes a path, an optional hash, and an optional block.
So something is clearly not wired up correctly.
Some of the code is here:
config.ru: http://pastie.org/8673836
spec_helper.rb at http://pastie.org/8673835
Error message at http://pastie.org/8673793
Simple controller at http://pastie.org/8673785
The names are slightly different in the pasties, but the gist is the same.
How do you wire up the controllers when you don't have the environment
config.ru gives you?
Thanks for any help.
The problem is somewhere in the code base, but rack doesn't make it easy to determine where.
I filed a bug on this at
https://github.com/rack/rack/issues/652

Setting Sinatra template options works locally, broken on Heroku

My Sinatra web site uses an admittedly ghetto way of switching between two languages, which works perfectly on my local machine, but not on Heroku.
My app.rb is as follows:
require 'sinatra'
get '/' do
set :erb, :views => settings.views + "/en"
erb :index, :layout => false, :views => settings.views
end
get '/tr' do
set :erb, :views => settings.views + "/tr"
redirect to('/home')
end
get '/en' do
set :erb, :views => settings.views + "/en"
redirect to('/home')
end
get '/home' do
erb :home
end
get '/products' do
erb :products
end
...
When I click on the links that go to the /en and /tr urls, I am correctly redirected to the /home link, but the views folder does not change.
My gems are the same versions in both environments:
rack (1.4.1)
rack-protection (1.2.0)
tilt (1.3.3)
sinatra (1.3.3)
bundler (1.3.2)
Link to the site
Help, please.
I suggest replacing your admittedly ghetto way with something more robust like the i18n gem
here is a tutorial
And instead of using the browser's language (in example) you could do something like this in a before filter
before do
case request.path_info
when /^\/tr/ then set :locale, "tr"
else set :locale, "en"
end
end
and in helpers
helpers do
def get_locale
settings.locale
end
# other helpers from example
end
That way you only need one copy of your view templates, reducing the complication of changing all views when you only need to change one element (for example)
If you want to test your sinatra app like it will act on heroku you can throw on a RACK_ENV=production before starting your server. Ex. RACK_ENV=production ruby my_app.rb

reload rails.root/app/resources/* per request

I have a rails app with a folder rails.root/app/resources where I keep some library code.
This library code is used in a rack app that I mount in routes.rb in my Rails application
# rails.root/app/resources/file_resource.rb
# routes.rb
mount DAV4Rack::Handler.new(
:root => Rails.root.to_s,
:resource_class => FileResource
), :at => '/', :constraints => {:subdomain => "w"}
How can I make the FileResource reload on each request in development?
I tried autoload_paths, reload_plugin, none seem to work.
I think it has something to do with the code in routes.rb.
If I make a file rails.root/app/resources/my_helper.rb and use MyHelper.test() inside FileResource, the MyHelper gets reloaded.
No, I don't want to move this in 'lib' folder.
I am currently using the following hack, if anyone has a better solution please do share!
# config/environments/development.rb
root = config.root
config.to_prepare do
load "#{root}/app/resources/file_resource.rb"
end

Rails namespaces with only numbers

I'm building an api in rails, and I have been told that I need to scope the site so it has versions.
Something like /1.0/do_something.
From what I've read, I do this by making a routes.rb that looks like the following:
API::Application.routes.draw do
scope :path => "1.0", :module => "1.0" do
post "do_something" => "controller#method"
# Everything else. Glob is saved in params[:r]
match '*r', :to => 'errors#e404'
end
end
But when I rake routes, I get the following error:
rake aborted!
missing :action
What am I doing wrong?
You cannot have a module called "1.0" for obvious reasons. Consider calling this V1 instead.

Resources