Is it possible to bake feature-toggle-like functionality into a Sinatra application?
A bit about feature toggles, just in-case ;)
I've set up a modular Sinatra project, and I tend to implement a GET
/POST
/PUT
/DELETE
endpoint for all my resources; it makes it easier to test the app and manipulate the data while in development.
When I go into production I don't want the unneeded endpoints to exist (e.g DELETE '/users'
).
Can I annotate the methods with some kind of a :development
flag, or maybe intercept the request in a before block? Would you do this using a helper? I'm not sure if I'm heading down the right path here, I'm probably over complicating it(?)
How would one go about this?
If you've done something like this it would be great if you can share your findings with the nation.
You can use the current environment to decide whether you define an action. For example:
class MyApp < Sinatra::Application
if settings.development?
get '/admin' do
'VIPs only'
end
end
end
If you have a lot to toggle, you might want to isolate them in one file that you can decide to require or not:
# routes/init.rb
require_relative 'main'
require_relative 'debug' if settings.development?
# routes/main.rb
class MyApp < Sinatra::Application
get '/' do
'Hello!'
end
end
# routes/debug.rb
class MyApp < Sinatra::Application
get '/admin' do
'VIPs only'
end
end
Or if you want to list your development-only paths in one place, here's a filter version:
class MyApp < Sinatra::Application
DEVELOPMENT_PATHS = %w[
/admin
]
before do
unless settings.development? || !DEVELOPMENT_PATHS.include?(request.path)
halt 404
end
end
end
Then you could also build some decorator-like methods that add to the list:
class MyApp < Sinatra::Application
def self.development_only(path)
DEVELOPMENT_PATHS << path
end
get '/admin' do
'VIPs only'
end
development_only '/admin
end
In general, I'd recommend caution when introducing significant differences between the code that runs in development vs. production. Inevitably, the dev code is either left untested or becomes cumbersome to maintain properly. In this case, there's the danger that you miss a route you intended to hide and it becomes available to everyone in production. I'd tend towards not having these routes at all and manipulating my dev environment from a console, or going all the way to the other end and building fully-tested and production-ready user permissions with something like sinatra-authentication.