goorment

Create base entity in go ent framework


I'm new to golang, and am using ent framework as an ORM. Every schema should have the fields created_at and updated_at, and I want to write it once rather then write it for every schema i.e:

func (User) Fields() []ent.Field {
    return []ent.Field{
        field.Int("id"),
        field.String("name").MaxLen(70),
        field.String("email"),
        field.Time("created_at").Default(time.Now).Immutable(),
        field.Time("updated_at").Default(time.Now).UpdateDefault(time.Now),
    }
}

.....

func (Product) Fields() []ent.Field {
    return []ent.Field{
        field.Int("id"),
        field.String("name").MaxLen(70),
        field.Float("price"),
        field.Time("created_at").Default(time.Now).Immutable(),
        field.Time("updated_at").Default(time.Now).UpdateDefault(time.Now),
    }
}

I came from OOP lagnageus where I can do that it with some kind of BaseEntity that all other entities inherits from it, but not sure how to do it in this case.


Solution

  • You can use MixIn which allows you to create reusable pieces of ent.Schema code that can be injected into other schemas using composition so, you can define your timestamp values in another schema and just mix it in the other schemas where you need it so your timestamp(base entity) mixin schema will look like this

    package schema
    
    import (
        "entgo.io/ent"
        "entgo.io/ent/schema/field"
        "entgo.io/ent/schema/mixin"
        "time"
    )
    
    type TimeStamp struct {
        mixin.Schema
    }
    
    func (TimeStamp) Fields() []ent.Field {
        return []ent.Field{
            field.Time("created_at").Default(time.Now).Immutable(),
            field.Time("updated_at").Default(time.Now).UpdateDefault(time.Now),
        }
    }
    

    Now when it is defined and you need to inject this timestamp schema into your other schema. For this what you have to do is to inject it in the MixIn() of that schema which will look like this

    
    func (User) Mixin() []ent.Mixin {
        return []ent.Mixin{
            TimeStamp{},
        }
    }
    ......
    
    func (Product) Mixin() []ent.Mixin {
        return []ent.Mixin{
            TimeStamp{},
        }
    }
    

    So you final schemas will look like this.

    
    func (User) Mixin() []ent.Mixin {
        return []ent.Mixin{
            TimeStamp{},
        }
    }
    
    func (User) Fields() []ent.Field {
        return []ent.Field{
            field.Int("id"),
            field.String("name").MaxLen(70),
            field.String("email"),
        }
    }
    
    .....
    
    
    func (Product) Mixin() []ent.Mixin {
        return []ent.Mixin{
            TimeStamp{},
        }
    }
    
    func (Product) Fields() []ent.Field {
        return []ent.Field{
            field.Int("id"),
            field.String("name").MaxLen(70),
            field.Float("price"),
        }
    }
    

    Also ent provides builtin time mixins that can be used for adding the create_time and update_time fields to the schema and it is defined as mixin.Time{}.

    For more details you can look into Mixin