Skip to content

Add the concept of attribute modifiers

Compare
Choose a tag to compare
@VinGarcia VinGarcia released this 13 Nov 17:38
· 124 commits to master since this release

This release adds the concept of a modifier.

What is a KSQL Modifier?

A KSQL modifier is a special tag you can add to any of the attributes of your struct to alter the behavior of KSQL when reading or writing that attribute into the database. To use it, it is necessary to add the name of the modifier on the ksql tag after a comma, e.g.:

`ksql:"column_name,json"`

Before this release, the json modifier was the only one available in KSQL, and it would help the user by converting the attribute to JSON before writing to the database and back from JSON when reading from the database.

Adding Custom Modifiers

This release improves on this idea of modifiers by making it possible for users to add their own user-created modifiers. This release also adds 4 new built-in modifiers so users can use out of the box, namely:

  • timeNowUTC: It only works if on attributes of type time.Time and it sets this attribute to time.Now().UTC() every time before insertions and updates. This modifier was created to be used on UpdatedAt timestamp fields.
  • timeNowUTC/skipUpdates: Does the same as the above but only on insertions. This is useful for CreatedAt fields where you only want them to be set once on Insert().
  • skipUpdates: Will ignore fields on updates.
  • skipInserts: Will ignore fields on inserts.

Here is an example of how a User struct might look like using some of these modifiers:

type user struct {
	ID   uint   `ksql:"id"`
	Name string `ksql:"name"`
	Age  int    `ksql:"age"`

	Address Address `ksql:"address,json"`

	UpdatedAt time.Time `ksql:"updated_at,timeNowUTC"`
	CreatedAt time.Time `ksql:"created_at,timeNowUTC/skipUpdates"`
}

We also have plans on releasing some modifiers for saving time.Time instances as UNIX timestamps on the database in the future.

Registering new Modifiers

Registering new modifiers is done by instantiating a struct like the below:

func init() {
	ksqlmodifiers.RegisterAttrModifier("my_modifier_name", ksqlmodifiers.AttrModifier{
		SkipInserts: false, // set it to true if you want this modifier to cause the field to be ignored on inserts.

		SkipUpdates: false, // set it to true if you want this modifier to cause the field to be ignored on updates.
	
		Scan: func(ctx context.Context, opInfo ksqlmodifiers.OpInfo, attrPtr interface{}, dbValue interface{}) error {
			// Read the dbValue, modify it and then save it into the attrPtr argument using reflection.
		},

		Value: func(ctx context.Context, opInfo ksqlmodifiers.OpInfo, inputValue interface{}) (outputValue interface{}, _ error) {
			// Read the inputValue, modify it and then return it so the database can save it.
		},
	})
}

This registration should be performed inside your code before making any calls to the KSQL library. I recommend doing it inside a init() function since then it will run before main() starts.