You ain't gonna need it. Just use methods instead:
module Api
# Avoid adding "Concern" to your module names
# it provides absolutely no information about what the object does
module AuthConcern
extend ActiveSupport::Concern
included do
rescue_from Unauthenticated { |e| respond_to_unauthenticated(e.error) }
rescue_from PermissionDenied { |e| respond_to_permission_denied(e.error) }
end
def respond_to_unauthenticated(message)
render status: 401, json: { error: message }
end
def respond_to_permission_denied(message)
render status: 403, json: { error: message }
end
end
end
This lets any class that includes the module customize the behavior by simply overriding the method:
module Api
class FooController < BaseController
# ...
private
def respond_to_unauthenticated(error)
render plain: 'Oh noes, you broke it!'
end
end
end
If you need to add more logic to to how a module augments the class with you can use the macro pattern. This is simply a class method that adds methods or behavior to the class:
module Api
module AuthConcern
extend ActiveSupport::Concern
# ....
module ClassMethods
def authenticate!(**kwargs)
before_action :authenticate!, **kwargs
end
end
end
end
module Api
class FooController < BaseController
authenticate! except: :index
end
end
This pattern is found all over Ruby in everything from attr_accessor to Rails callbacks and assocations.
rescue_fromis a class method used to handle exceptions. You have theif:andunless:options for callbacks (not the same thing as the ruby keyword) that take a lambda or a method name.