One thing I really like about Sinatra is the incredibly simple router.
# app.rb
get '/' do
# show something
end
post '/' do
# create something
end
Did you know you can do something similar in Rails?
Simply map an incoming request to a Rack endpoint, which is a fancy way to say an object responding to the call
method that accepts the request environment and returns an array containing the status, headers, and response body.
Or a lambda.
# config/routes.rb
get 'rack', to: ->(env) {
response = 'hello world'
[200, {}, [response]]
}
Agreed, not as elegant as Sinatra, but still useful when you quickly want to try some Rails feature in the browser, and don't want to spin up a whole new controller and view.
Now you might wonder if we can do everything we can inside a Rails controller. The answer is no, as the controller classes include various modules to provide additional functionality.
However, the point of this post is 'not' to do everything we can with Rails controllers, but quickly try out something that you want to understand that doesn't necessarily need the controller and views.
A good example is playing with the routing itself. Whenever I want to understand how some feature of Rails Router works, say custom non-resourceful routes, I use the above lambda, put the breakpoint in it to ensure the route is getting hit, inspect the request, and so on.
Note: If you need access to the Rails request, just wrap the Rack env
hash inside the ActionDispatch::Request
class. This also gives you access to the params
hash.
get 'test', to: ->(env) {
req = ActionDispatch::Request.new(env)
puts req.params
[200, {}, ['response']]
}
A Reddit user also pointed out another excellent use case, which is for one-off health-check endpoints that simply return some 'success' response, and don't need any controller and view.
What do you think?
To learn more about routing in Rails, check out my in-depth article on the Rails Router.
To learn more about Rack interface, see this article: