supabase-rb-rb
Controllers

BaseController

Supabase::Rails::BaseController — the common parent class for every gem-shipped controller.

Supabase::Rails::BaseController is the common parent class every gem-shipped controller inherits from. It does two things — inherit from the host's ::ApplicationController and include Supabase::Rails::Authentication — so the host's layouts, helpers, CSRF posture, and global before_actions flow through into sessions/registrations/passwords/OTP/OAuth without re-declaration.

# app/controllers/supabase/rails/base_controller.rb (in the gem)
module Supabase
  module Rails
    class BaseController < ::ApplicationController
      include Supabase::Rails::Authentication
    end
  end
end

Why inherit from ::ApplicationController?

The host's ::ApplicationController typically declares:

  • protect_from_forgery with: :exception (CSRF protection).
  • Layout choices (layout "application" or per-controller overrides).
  • Global before-action hooks (analytics, locale switching, tenant scoping).
  • Helper-method registrations and helper_method exposures.
  • Rate limiting, request logging, or audit-trail concerns.

Inheriting from ::ApplicationController means every one of those host conventions applies unchanged to Supabase::Rails::SessionsController#create and friends. The gem deliberately does not declare protect_from_forgery itself — host posture wins. See Engine note for why Supabase::Rails::Engine skips isolate_namespace (which is what makes this ::ApplicationController hop possible).

The host's `ApplicationController` must exist

BaseController resolves ::ApplicationController at class-definition time. A host that has renamed or removed ApplicationController will see a NameError at gem load. Add a tiny shim (e.g. ApplicationController = ::ActionController::Base) before the gem boots if you have intentionally removed it.

What the Authentication concern installs

Including Supabase::Rails::Authentication on every gem-shipped controller installs the full Rails-8-shape auth surface — before_action :require_authentication, before_action :populate_current_attributes, helper_method :authenticated?, the allow_unauthenticated_access class macro, and the full supabase_* helper set.

Sessions, Registrations, Passwords, Otp, and Oauth all inherit from BaseController so they pick up this surface without re-declaring it. Each one declares allow_unauthenticated_access only: %i[...] for its public actions; everything else stays gated.

Do not include the concern twice

Authentication is included once at BaseController. Re-including it in a host subclass (include Supabase::Rails::Authentication) re-runs the included block and re-registers helpers and before_actions. The generator-emitted host ApplicationController already mixes in Authentication for non-Supabase controllers; the gem-shipped controllers inherit from BaseController and do not need a second include.

When to use it in your own controllers

You usually do not need to subclass Supabase::Rails::BaseController directly. The install generator wires the Authentication concern into your host's ApplicationController, so every controller in the host app already has authenticated?, current_user, require_authentication, and the supabase_* helpers — no extra inheritance step required.

BaseController exists primarily as a hook the five gem-shipped controllers inherit from. Two scenarios where direct subclassing is reasonable:

  1. Adding a new auth-adjacent controller (e.g. a "Confirm new email" flow) that wants the same parent-class shape — layouts via ::ApplicationController, Authentication concern already included, allow_unauthenticated_access available — as the gem's controllers.

    class EmailConfirmationsController < Supabase::Rails::BaseController
      allow_unauthenticated_access only: %i[show]
    
      def show
        result = supabase_verify_otp(
          token: params[:token],
          type: "email_change",
          email: params[:email],
        )
        if result.success?
          redirect_to root_path, notice: t(".email_updated")
        else
          redirect_to root_path, alert: result.error.message
        end
      end
    end
  2. Replacing one of the shipped controllers wholesale by rewriting the host's 3-line subclass to inherit from BaseController instead of the gem's per-domain class:

    # app/controllers/sessions_controller.rb
    class SessionsController < Supabase::Rails::BaseController
      allow_unauthenticated_access only: %i[new create]
    
      def new; end
    
      def create
        # Fully custom sign-in flow.
      end
    
      def destroy
        terminate_session
        redirect_to root_path
      end
    end

    This keeps Authentication available but discards every action body the gem ships. See the per-controller pages for the action bodies you would be giving up.

See also

  • Controllers overview — the routing DSL, the six controllers, and the override pattern.
  • Authentication concern — every method BaseController makes available to its subclasses.
  • supabase:install generator — writes the 3-line host subclasses that inherit from the gem's per-domain controllers (themselves inheriting from BaseController).
  • Engine note — why Supabase::Rails::Engine is non-isolate_namespace, which is what lets BaseController reach ::ApplicationController.

On this page