Skip a callback from inherited action

Hey hey
I cannot find this info in docs or in source code
Let’s say we have a base action:

class Action < Hanami::Action
    include Dry::Monads[:result]

    before do |request, response|
      authenticate_user(request, response)
    end

So that all our actions inheriting from this, are authenticated

But we might not want to do it on ALL actions that inherit the base Action (but still want to inherit the rest of the logic, like for example LoginAction).
One solution is something like:


    def skip_authenticate_user
      false
    end

    def authenticate_user(request, _response)
      return if skip_authenticate_user
      return if current_user(request)

      halt 401, { errors: { login: "Unauthorized" } }.to_json
    end

Or just overwriting authenticate_user in actions you want to skip, but is there some more natural way, like skip_before_action? Do you think it makes sense to have it, or overwriting callback methods or doing stuff like above makes more sense?

2 Likes

What do you think about adding an intermediate Action-class (i.e AuthenticatedAction).

class AuthenticatedAction < MyApp::Action
  before do |request, response|
    authenticate_user(request, response)
  end
  
  def authenticate_user(req, res)
    #...
  end
end
# Login doesn't require authentication
class LoginAction < MyApp::Action
  def handle(request, response)
  end
end

# Action which uses authentication
class AnotherAction < AuthenticatedAction
  def handle(request, response)
    # only accessible when authenticated
  end
end

Yea that is good too, but I was wondering if a built-in approach makes sense in hanami?

Another option could be to override authenticate_user in the inheriting class. In Ruby 3 it would be more concise: def authenticate_user = nil

I guess it’s a matter of taste. I’ve always felt dirty when using skip_before_action, as if my code was saying one thing at high level (this class inherits from X) and doing a different one (well, actually…), so I like the lack if skip_before_action as it won’t encourage that pattern.

1 Like

Yea I would agree in general. I was asking the question cause I was leaning towards not having those skip_ things either, good to see other think alike :v

1 Like

Yea, I don’t think we should add any skip callbacks functionality. There are better ways to solve that problem, and developers should pick the one that suits their situation best.

In my app, I just use before :require_authentication! in all the actions that need authentication. It’s ~50% though, if it were 90%+, then I’d likely just do it for all actions, then override the method as a no-op like @raul suggested.

3 Likes