Per-slice sessions

This came up in chat today, but it’s a nice little standalone nugget of info, so I’ve blogged it, and now I’m sharing it with you here!


One of the things I do in Hanami-land is provide support. I love doing this because it helps me understand all the contours of our framework as it meets the real world. Bringing your questions is seriously one of the most helpful things you can do for Hanami right now. (At this moment, @aaronmallen would be telling you to join our Discord!)

A question that came up this week was about how to have separate Rack cookie sessions per slice.

You can achieve this by using the session middleware inside each slice in your routes:

# config/routes.rb

module MyApp
  class Routes < Hanami::Routes
    slice :main, at: "/main" do
      use Rack::Session::Cookie,
        key: "my_app.session.main",
        secret: "YOUR_SECRET_HERE"
        expire_after: 60 * 60 * 24 * 365

      # Your slice routes here
      root to: "home.show"
    end

    slice :admin, at: "/admin" do
      use Rack::Session::Cookie,
        key: "my_app.session.admin",
        secret: "YOUR_SECRET_HERE"
        expire_after: 60 * 60 * 24 * 365

      # Your slice routes here
      root to: "home.show"
    end
  end
end

We’ve put a lot of care into allowing slices to be as independent as possible in Hanami apps. This is one such example!

You can see that I have some ”home.show” actions in the routes above. I used these in my test app to confirm this works. Here’s how they look.

# slices/admin/actions/home/show.rb

# The "main" slice version of this looks exactly the same,
# just inside the `Main` namespace.
module Admin
  module Actions
    module Home
      class Show < Admin::Action
        def handle(request, response)
          if request.params[:set]
            request.session[:current_user] = request.params[:set]
            response.redirect "/admin"
          end

          response.body = "Current user: #{request.session[:current_user]}"
        end
      end
    end
  end
end

With this done, I can visit /admin?set=admin-user and /main?set=main-user, and observe that when visiting /admin and /main I see different values for their current user, because each one has an entirely independent session!

We can do better

Currently, there’s one caveat to this arrangement. You also need to enable cookie sessions inside your app.

# config/app.rb

module MyApp
  class App < Hanami::App
    config.actions.sessions = :cookie, {
      secret: "YOUR_SECRET_HERE",
      expire_after: 60 * 60 * 24 * 365
    }
  end
end

This session won’t be used, because we explicitly use the middleware inside each slice’s routes, but it’s necessary for Hanami actions to enable their session support in the first place.

I want us to fix this! I’ve filed three items on our roadmap to look at this:

This is a good example of where Hanami is right now. Really powerful foundational structures, but some rough edges that we need to smooth over. If you’re a Rubyist looking to contribute your energies to something good, we’d love to support you pitching in on this. Better session handling could be your opportunity! :cherry_blossom:

3 Likes