Ready to get started?

Join Adocasts Plus for $8/mo, or sign into an existing Adocasts Plus account, to get access to all of our lessons.

robot mascot smiling

Logging Out Users

@tomgobich
Published by
@tomgobich
In This Lesson

We'll hook up our logout user menu button to a POST route to logout an authenticated user.

Chapters

00:00 - Creating Our Files
00:50 - Defining Our Route, Controller, and Action
03:02 - Testing Our User Logout
03:32 - Adding Toast Messages

Join the Discussion 4 comments

Create a free account to join in on the discussion
  1. @kite

    What's the benefit of using actions instead of keeping that logic in the controllers? I personally would prefer to keep it in the controllers like I've seen in the docs as those additional directories seem a bit burdensome to me. What would I lose/gain from keeping that content which honestly seems fairly short inside my controllers?

    I also understand the benefits of separating concerns, I'm just curious as to the reasoning to go down this extra level.

    1
    1. Responding to kite
      @tomgobich

      As a whole, by using actions you're:

      • Giving the operation a name & scope, which improves the ability to scan your controllers.

      • Gives us the ability to easily reuse the code if needed. It is considered bad practice to call one controller method from another, as controllers are meant to handle routes.

      • On top of reusability, if we need to update an operation later on, we only have to perform that update in one spot rather than each spot it is performed in the controllers.

      • As you said, it gives us a separation of concerns. If we're performing an action, we know we can find it within our actions folder, under the resource/section it is for.

      Note that actions are very similar to services. To compare, you can think of each subfolder within actions as a service class and each file within the subfolder as a service class method. The main difference here though is actions allow us to easily define steps within the actions whereas that'd need to be additional methods inside a service, which can make things a little messy.

      A good example, though the code for this is from a future lesson releasing soon, is the account deletion controller & action. The controller is easy to scan. The operations have a designated location & scope and can make use of subactions. We're reusing our webLogout method, meaning we can easily update just the webLogout method if we ever need to adjust how we handle logouts. For example, if you're tracking user sessions, you might need to mark that session record in the database as logged out in addition to actually logging out the user.

      @inject()
      async destroy({ request, response, session, auth }: HttpContext, webLogout: WebLogout) {
        const user = auth.use('web').user!
        const validator = vine.compile(
          vine.object({
            email: vine.string().in([user.email]),
          })
        )
      
        await request.validateUsing(validator)
      
        await DestroyUserAccount.handle({ user })
      
        await webLogout.handle()
      
        session.flash('success', 'Your account has been deleted')
      
        return response.redirect().toRoute('register.show')
      }
      Copied!

      I've worked with code, and written my fair share, where the controller method gets unwieldy large because all the operations are done directly in the controller. It might seem small at first, but requirements change, time gets crunched, and things slowly grow over time.

      Hope this helps!

      1
      1. Responding to tomgobich
        @kite

        Thanks for that explanation. I got an idea in 5.3 of how large a controller could get with the StoreOrganization action lol

        1
        1. Responding to kite
          @tomgobich

          Anytime!! Yeah, they grow pretty easily & quickly!! lol 😅

          0