Sinatra and Grape API together?
Asked Answered
S

1

9

I've been reading around and I found this micro-framework called Grape for ruby. I am currently using Sinatra to handle the web interface but I would also like to implement Grape to handle the API aspect of the app. I can't find any helpful suggestions to this topic. The grape documentation says "Grape is a REST-like API micro-framework for Ruby. It's designed to run on Rack or complement existing web application frameworks such as Rails and Sinatra by providing a simple DSL to easily develop RESTful APIs." So it sounds like there should be an official way of combining both right? This app will also be run on Heroku.

Schilling answered 27/2, 2013 at 0:52 Comment(1)
I came across this, which might be slightly useful perhapsTurbulence
T
21

The phrases you're looking for are:

  • multiple rack apps
  • rack middleware
  • mapping urls rack sinatra

That kind of thing. Grape, Sinatra and Rails are all Rack apps. What this means is that you can build your Grape app, your Sinatra app, and your Rails app, and then you can use Rack to run them as they're all Rack compliant because they share an interface.

What this means in practice is you write the applications, and then you put them in a rackup file to run them. A short example using 2 Sinatra apps (but they could be any number of any kind of Rack apps) :

# app/frontend.rb
require 'sinatra/base'
# This is a rack app.
class Frontend < Sinatra::Base
  get "/"
    haml :index
  end
end

__END__

@@ layout
%html
  = yield

@@ index
%div.title This is the frontend.


# app/api.rb
# This is also a rack app.
class API < Sinatra::Base

  # when this is mapped below,
  # it will mean it gets called via "/api/"
  get "/" do
    "This is the API"
  end
end

# config.ru
require_relative "./app/frontend.rb"
require_relative "./app/api.rb"

# Here base URL's are mapped to rack apps.
run Rack::URLMap.new("/" => Frontend.new, 
                     "/api" => Api.new) 

If you wanted to add the Twitter API example from the Grape README:

# app/twitter_api.rb
module Twitter
  # more code follows

# config.ru
require_relative "./app/twitter_api.rb" # add this

# change this to:
run Rack::URLMap.new("/" => Frontend, 
                     "/api" => API,
                     "/twitter" => Twitter::API)

Hopefully that's enough to get you started. There are plenty of examples once you know where to look. You can also run other apps inside a Sinatra app by using use (see http://www.sinatrarb.com/intro#Rack%20Middleware) and I see that Grape offers the mount keyword too. There are lots of ways available, which may be a bit confusing at first, but just try them out and see what they do and what you like best. A big part of it is preference, so don't be afraid to go with what feels right. Ruby is for the human more than the computer :)


Edit: A Sinatra app with a Grape app "inside"

class App < Sinatra::Base
  use Twitter::API
  # other stuff…
end

# config.ru
# instead of URLMap…
map "/" do
  run App
end

I believe it will be something like that.

Tachylyte answered 27/2, 2013 at 19:19 Comment(5)
Hello thank you for your answer. How can I use this method but have my API run off of the root / also?Schilling
@CristianRivera I've added an example I believe will be how to do it. It's how it would work with other Rack apps and Sinatra.Tachylyte
Hi i tried what you suggested and i got "Internal server error" in my browser, in the server logs i got "!! Unexpected error while processing request: wrong number of arguments (1 for 0)"Schilling
@CristianRivera you need to outline what you did exactly, and what the error message was exactly, in your question as an edit or it will be difficult to fix via the comments.Tachylyte
Hi i did get your method to work but i ended up using another method and running them as two separate heroku apps. I will also mark this as the answer.Schilling

© 2022 - 2024 — McMap. All rights reserved.