Arturo Herrero
Arturo Herrero

Reputation: 13122

How to split a Sinatra app with different scopes?

I'm splitting a large Sinatra file into different files using registers. This is one way to have a modular Sinatra app using extensions.

I'm ending up with something like the following code:

MyApp < Sinatra::Base
  register OneRegister
  register SecondRegister
end

module OneRegister
  def self.registered(app)
    app.helpers OneRegisterHelper

    app.get "/one-endpoint" do
      do_stuff
    end
  end

  module OneRegisterHelper
    def do_stuff
      # Some code
    end
  end
end

module SecondRegister
  def self.registered(app)
    app.helpers SecondRegisterHelper

    app.get "/second-endpoint" do
      do_stuff
    end
  end

  module SecondRegisterHelper
    def do_stuff
      # Different code
    end
  end
end

The problem is how Sinatra works with registers and helpers. Every time I create a new helper for a register I'm polluting the main Sinatra app scope with the methods in the helpers.

So, the method do_stuff is going to be overwritten by the SecondRegisterHelper (this is how Ruby works when including a module) but I'd like to have different implementations for the methods without worry if I'm using the same method name or a different one (image an app with 25 registers with small methods in each one).

Basically, I'd like to have different registers with private methods because I usually write very small private methods with a single responsibility. Any ideas, how I can achieve this?

Upvotes: 1

Views: 278

Answers (1)

Lars Vonk
Lars Vonk

Reputation: 46

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.

Upvotes: 1

Related Questions