How to Mount a Sinatra Application Inside Another Sinatra App

How to mount a Sinatra application inside another Sinatra app?

Take a look at https://stackoverflow.com/a/15699791/335847 which has some ideas about namespacing.

Personally, I would use the config.ru with mapped routes. If you're really in that space between "should this be a separate app or is it just helpful to organize it like this" it allows that, and then later you can still farm off one of the apps on its own without changing the code (or only a little). If you're finding that there's a lot of duplicated set up code, I'd do something like this:

# base_controller.rb

require 'sinatra/base'
require "haml"
# now come some shameless plugs for extensions I maintain :)
require "sinatra/partial"
require "sinatra/exstatic_assets"

module MyAmazingApp
class BaseController < Sinatra::Base
register Sinatra::Partial
register Sinatra::Exstatic

end

class Blog < BaseController
# this gets all the stuff already registered.
end

class Foo < BaseController
# this does too!
end
end

# config.ru

# this is just me being lazy
# it'd add in the /base_controller route too, so you
# may want to change it slightly :)
MyAmazingApp.constants.each do |const|
map "/#{const.name.downcase}" do
run const
end
end

Here's a quote from Sinatra Up and Running:

Not only settings, but every aspect of a Sinatra class will be inherited by its subclasses. This includes defined routes, all the error handlers, extensions, middleware, and so on.

It has some good examples of using this technique (and others). Since I'm in shameless plug mode I recommend it, even though I've nothing to do with it! :)

Mount Sinatra app inside a rails app and sharing layout

You basically need to do two things:

You need to tell the Rails router that a certain URL path is to be handled by another Rack app (in your case a Sinata app). This can be done by adding this to your routes.rb:

match "/sinatra" => MySinatraApp, :anchor => false

Having done that, you can create your app like so:

class MySinatraApp < Sinatra::Base
get "/" do
"Hello Sinatra World"
end
end

The second step now is to tell your Sinatra app to use the rails layout which by default lives in app/views/layouts/application.html.erb for Rails 3.1. by default, Sinatra uses ./views/layout.ext (with ext being the extension of your chosen template system). So you basically, have to tell Sinatra to

  1. use another directory to find views and layouts instead of the default ./views
  2. use another template file as the default layout.

Both can be achieved by setting the following in your sinatra app:

set :views, "/path/to/your/railsapp/views"
set :erb, layout => :"layout/application" # or whatever rendering engine you chose

Multiple Sinatra apps using rack-mount

I think you'll prefer Rack::URLMap - it will probably look something like this:

run Rack::URLMap.new("/" => App.new, 
"/api" => Api.new)

That should go in your config.ru file.

Mounting a Sinatra app and all its routes in a Rails application

So the problem ended up being that I missed the leading / before widgets in the get route, so it wasn't being routed correctly.

Mounting Sinatra app on rails 5

I was able to resolve this with a newer version of sinatra.

gem 'sinatra', '2.0.0.beta2'

rackup mounting apps vs rails mounting for sinatra apps

Interesting there is any significant difference apart from the fact that in the latter part(application mounted using rackup)

any requests to

/url1

/url2

would be server directly from the mounted rack application without actually passing the request in the middleware stack of rails and then detect valid rack application for the given mounted path .

Which would happen in first part where your sinatra application is mounted inside Rails defined in routes.rb of your file

So I your are trying to mount your sinatra application in routes.rb instead of config.ru then consider the fact that your request would be passed all along rails middleware stack
where routing middleware detect the appropriate path as passed the request to desired sinatra application

A Simple check You can do for this is try hitting your path i.e /url1 or /url2 in both the technique and you would see sinatra application routes.rb would log the request in your rails application whereas the other one would not

Hope this help

How to split a Sinatra app with different scopes?

I don't think this is achievable in the way you are trying. If you have methods with similar names in different modules mixed into a single class the last just wins.

So in this case I would create a modular app combined with a config.ru to setup your application.

class OneRegister < Sinatra::Base
# helpers here
end

class SecondRegister < Sinatra::Base
# helpers here
end

In config.ru

app = Rack::URLMap.new(
'/one-endpoint' => OneRegister,
'/second-endpoint' => TwoRegister
)

run app

No you helpers are scoped to a single class.



Related Topics



Leave a reply



Submit