On a recent Rails project I needed to handle incoming events from the Slack API. All Slack event notifications are sent to a single URL, so I wasn’t sure how best to structure this inside of a Rails application. In the past, I’ve used a single controller to handle events, but that never quite sat right with me. I wanted to try something different this time.
After reading up on request-based routing constraints in the
I decided to experiment with them. I really wanted to route
Link Shared events to different controllers, so I used constraint objects
to separate the requests.
# config/routes.rb post "slack", to: "slack/url_verifications#create", constraints: SlackUrlVerificationConstraint.new post "slack", to: "slack/unfurlings#create", constraints: SlackLinkSharedConstraint.new
# app/models/slack_url_verification_constraint.rb class SlackUrlVerificationConstraint def matches?(request) request.params[:type] == "url_verification" end end
# app/models/slack_link_shared_constraint.rb class SlackLinkSharedConstraint def matches?(request) event_callback?(request) && link_shared?(request) end private def event_callback?(request) request.params[:type] == "event_callback" end def link_shared?(request) request.params.dig(:event, :type) == "link_shared" end end
I’m not the biggest fan of the resulting routes, but I really like handling different event types in different controllers. I’m excited to keep experimenting with this approach!