hooks

A simple event-driven package that allows you to register hooks (listeners) and subscribers for specific events. Inspired by Symfony’s event system, this package provides an easy way to implement hooks and event subscribers.

Static Badge

GoDoc GitHub stars Go Report Card codecov

Versions

Stable Version GitHub Release GitHub Release

Installation

To install the hooks package, use the following Go command:

go get -u github.com/gouef/hooks

Features

  • Register hooks to events using event names (e.g., User::create).
  • Subscribers can listen for specific events and execute their corresponding handlers.
  • Supports multiple hooks for a single event.
  • Allows easy testing using mocks.

Example Usage

Define Your Event Interface

You need to define an event that implements the Event interface. This interface should have a GetName() string method to return the name of the event.

package app

// UserCreatedEvent represents an event triggered when a user is created
type UserCreatedEvent struct {
    UserID string
}

// GetName returns the name of the event
func (e *UserCreatedEvent) GetName() string {
    return "User::create"
}

Create a Subscriber

A subscriber will listen for specific events and handle them when triggered.

package app

import "fmt"

// Subscriber listens for events and handles them
type Subscriber struct {
    Name string
}

// OnUserCreated is called when the User::create event is triggered
func (s *Subscriber) OnUserCreated(event interface{}) {
    if userEvent, ok := event.(*UserCreatedEvent); ok {
        fmt.Printf("%s: User %s was created\n", s.Name, userEvent.UserID)
    }
}

Define a User with Event Triggering

package app

import (
	"fmt"
	"github.com/gouef/hooks"
)

// User model
type User struct {
    Name string
}

// Create is a method that triggers the User::create event
func (u *User) Create() {
    fmt.Printf("User %s created\n", u.Name)

    // Trigger the event after user creation
    hooks.Trigger(&UserCreatedEvent{UserID: u.Name})
}

Using the Event System

Now you can use the event system to add hooks and trigger events.

package main

import (
    "fmt"
    "app"
    "github.com/gouef/hooks"
)

func main() {
    // Create a subscriber
    subscriber := &app.Subscriber{Name: "Subscriber 1"}

    // Register a hook for the User::create event
    hooks.AddHook("User::create", func(event interface{}) {
        subscriber.OnUserCreated(event)
    })

    // Create a user, which will trigger the event
    user := &app.User{Name: "John"}
    user.Create() // This will automatically trigger the callback
}

Testing

You can write tests for the events and subscribers using the testify package. Here’s an example test for the user creation event.

package main

import (
    "testing"
    "app"
    "github.com/stretchr/testify/mock"
    "github.com/gouef/hooks"
)

// MockSubscriber is a mock for the subscriber
type MockSubscriber struct {
    mock.Mock
}

// OnUserCreated is a mocked method for testing
func (m *MockSubscriber) OnUserCreated(event interface{}) {
    m.Called(event)
}

func TestUserCreationTriggersEvent(t *testing.T) {
    // Create a mock subscriber
    mockSubscriber := new(MockSubscriber)

    // Register a hook for the User::create event
    hooks.AddHook("User::create", func(event interface{}) {
        mockSubscriber.OnUserCreated(event)
    })

    // Create a user
    user := &app.User{Name: "John"}

    // Expect that the OnUserCreated method will be called once with any event
    mockSubscriber.On("OnUserCreated", mock.Anything).Once()

    // Trigger the Create method, which should trigger the event
    user.Create()

    // Assert that the expected method was called
    mockSubscriber.AssertExpectations(t)
}

Contributing

Read Contributing

Contributors

JanGalek actions-user

Join our Discord Community! 🎉

Discord

Click above to join our community on Discord!