Plugins
FluxaORM's functionality can be extended by incorporating plugins.
Enabling Plugins
Activating plugins in FluxaORM is a simple process. To get started, register the desired plugin using the RegisterPlugin()
method, as demonstrated in the example below:
package main
import (
"github.com/latolukasz/fluxaorm"
"github.com/latolukasz/fluxaorm/plugins/modified"
)
func main() {
registry := fluxaorm.NewRegistry()
registry.RegisterPlugin(modified.New("Added", "Updated"))
}
FluxaORM offers a variety of built-in plugins, which can be explored further in the Plugins section.
Creating a Custom Plugin
To tailor FluxaORM to your specific needs, you have the flexibility to craft your own custom plugin by implementing at least one of the following interfaces.
ValidateRegistry Interface
type PluginInterfaceValidateRegistry interface {
ValidateRegistry(engine fluxaorm.EngineSetter, registry fluxaorm.Registry) error
}
The PluginInterfaceValidateRegistry
interface comes into play when the registry.Validate()
method is invoked. The first argument, EngineSetter
, empowers you to define additional parameters for the Engine
. These parameters can later be accessed in your code using the engine.Option()
method. The example below illustrates this concept:
type MyPlugin struct {}
func (p *MyPlugin) ValidateRegistry(engine fluxaorm.EngineSetter, registry fluxaorm.Registry) error {
// perform custom actions
engine.SetOptions("orm-started", time.Now())
return nil
}
Subsequently, in your code, you can retrieve this option from orm.Engine()
:
ormStarted := engine.Option("orm-started") // returns nil if not defined
This mechanism allows you to enrich the behavior of the Engine
during initialization by injecting and retrieving custom parameters.
InitRegistryFromYaml Interface
type PluginInterfaceInitRegistryFromYaml interface {
InitRegistryFromYaml(registry fluxaorm.Registry, yaml map[string]interface{}) error
}
The PluginInterfaceInitRegistryFromYaml
interface is invoked for each Entity when the registry.InitByYaml()
method is called. This interface provides access to both the orm.Registry
and the data loaded from a YAML file.
For instance:
type MyPlugin struct {}
func (p *MyPlugin) InitRegistryFromYaml(registry fluxaorm.Registry, yaml map[string]interface{}) error {
if yaml["MyPluginEnabled"] == true {
registry.SetOption("IsMyPluginEnabled", true)
}
return nil
}
Subsequently, in your code, you can retrieve registry options:
isEnabled := engine.Registry().Option("IsMyPluginEnabled") == true
This functionality allows you to customize the initialization process based on data loaded from YAML files, offering greater flexibility in configuring FluxaORM entities.
ValidateEntitySchema Interface
type PluginInterfaceValidateEntitySchema interface {
ValidateEntitySchema(schema fluxaorm.EntitySchemaSetter) error
}
The PluginInterfaceValidateEntitySchema
interface is executed for each entity registered with registry.RegisterEntity()
when registry.Validate()
is called:
type MyPlugin struct {}
func (p *MyPlugin) ValidateEntitySchema(schema fluxaorm.EntitySchemaSetter) error {
schema.SetOption("my-plugin-schema-option", "Some value")
return nil
}
Subsequently, in your code, you can access entity schema options:
schema := fluxaorm.GetEntitySchema[MyEntity](orm)
value := schema.Option("my-plugin-schema-option")
This interface empowers you to enhance the behavior of individual entity schemas during validation, providing a mechanism to inject custom options and retrieve them later in your code.
EntityFlush Interface
type PluginInterfaceEntityFlush interface {
EntityFlush(schema fluxaorm.EntitySchema, entity reflect.Value, before, after fluxaorm.Bind, engine fluxaorm.Engine) (orm.PostFlushAction, error)
}
The EntityFlush
interface plays a crucial role when entity data undergoes flushing via the Flush()
method. Code within this method executes just before data is poised for updating in MySQL. Optionally, you can return a function that executes immediately after the SQL queries are executed and data is stored in MySQL. The before
and after
maps contain entity data before and after changes:
- If
before
is nil andafter
is not nil, a new entity is slated for insertion into MySQL. - If both
before
andafter
are not nil, an entity is set to be updated in MySQL. - If
before
is not nil andafter
is nil, an entity is on the brink of being deleted from MySQL.
Here's an illustrative example:
type MyPlugin struct {}
func (p *MyPlugin) EntityFlush(schema fluxaorm.EntitySchema, entity reflect.Value, before, after fluxaorm.Bind, engine fluxaorm.Engine) (orm.PostFlushAction, error) {
now := time.Now().UTC()
if before == nil && after != nil { // INSERT
after["CreatedAt"] = now.Format(time.RFC3339)
}
return func(_ fluxaorm.ORM) {
entity.FieldByName("CreatedAt").Set(reflect.ValueOf(now))
}, nil
}
This example showcases how to utilize the EntityFlush
interface to manipulate entity data just before insertion, updating, or deletion in MySQL, demonstrating the flexibility it provides in customizing the flushing process.