ecnepsnai
ecnepsnai

Reputation: 2026

Define sinatra request routes in included files

I am using Sinatra and I would like to have my project structed in a way that keeps all requests for a specific action in separated files.

The problem I'm running into is that the routes aren't registered with sinatra, and it always 404s and runs my not_found handler, even though I've included a file with the route.

Here's an example of what I'm trying to achieve; Rackup would start the Info app which requires user and post. Info only contains a error and not found handler, and the related routes go in the corresponding required file.

config.ru:

require 'rubygems'
require 'bundler'

Bundler.require

require 'rack'
require './info.rb'
run Info

info.rb:

require 'rubygems'
require 'bundler'

require 'sinatra'

class Info < Sinatra::Base
    require './user.rb'
    require './post.rb'

    # 500 handler
    error StandardError do
        status 500
        content_type :json
        return '{"error": "Internal server error", "code": 500}'
    end

    not_found do
        status 404
        content_type :json
        return '{"error": "Page not found", "code": 404}'
    end
end

And user.rb (post.rb would look the same):

require 'rubygems'
require 'bundler'

require 'sinatra'

get '/1/user/:userid' do
    # request stuff
end

Upvotes: 1

Views: 130

Answers (1)

matt
matt

Reputation: 79723

require doesn’t work the way you seem to think it does. When you call require './user.rb', even though you do it inside the body of class Info < Sinatra::Base, its contents are not loaded as if they were inside that class. Instead they are parsed at the top level, and the routes are added to the default Sinatra::Application and not your application class.

You will have to have your user and post routes defined inside the same class body:

#info.rb
require 'sinatra/base' # Require 'sinatra/base' if you are using modular style.

class Info < Sinatra::Base
  # It's a bit unusual to have require inside a class, but not
  # wrong as such, and you might want to have the class defined
  # before loading the other files.
  require_relative 'user.rb' # require_relative is probably safer here.
  require_relative 'post.rb'

  # ... error handlers etc.
end
#user.rb
require 'sinatra/base'

# The routes need to be in the same class.
class Info < Sinatra::Base
  get '/1/user/:userid' do
    # request stuff
  end
end

Upvotes: 1

Related Questions