relationship

package
v0.300.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 3, 2025 License: Apache-2.0 Imports: 6 Imported by: 0

README

Modelling Relationships in Frameless

In frameless, you can model relationships between entities using different ID field types. Let's use a simple example to illustrate this.

Convention over Configuration Approach

Suppose we have two entities: User and Note. If we wish to express that a User has many Notes, we can do so by simply having a UserID field in the Note. This approach is inspired by the Hungarian notation, where the field name indicates its purpose.

type User struct {
    ID string
}

type Note struct {
    ID     string
    UserID string
}

Typed IDs Approach

Instead of relying on built-in types like string, you can achieve better readability by define your own types for IDs.

type UserID string
type NoteID string

type User struct {
    ID UserID
}

type Note struct {
    ID      NoteID
    OwnerID UserID
}

In this case, you also have more flexibility with the field name. Instead of UserID, we could use something more expressing such as OwnerID to indicate that the note belongs to a user. As long as the field type matches the ID type of the related entity, the relationship is easy to tell from the types.

One-to-Many Relationship

with BelongsTo

To clearly define relationships, consider using the BelongsTo function; this approach makes it explicit that one entity belongs to another by referencing its ID.

var _ = relationship.BelongsTo[Note, User](func(note *Note) *UserID {
    return &note.OwnerID
})

However, as long as you follow the convention of using meaningful field names and matching ID types, this step is optional.

By following these simple conventions and approaches, you can effectively model relationships between entities in frameless.

with ReferenceMany

You may need to model a one-to-many relationship where one entity links to multiple instances of another; for instance, a User can be associated with several Notes.

type UserID string
type NoteID string

type User struct {
    ID         UserID
    OwnedNotes []NoteID
}

type Note struct {
    ID NoteID

    Attachments []string
}

type Attachment struct {
    ID string
}

In this case, the OwnedNotes field in the User entity is a slice of NoteIDs, indicating which notes the user owns. This establishes a many-to-many relationship between User and Note.

Many-to-Many Relationship

You might find yourself that you need to model a Many to Many relationship.

You can do so by either haing both entities a reference list:

type UserID string
type NoteID string

type User struct {
    ID    UserID
    Notes []NoteID
}

type Note struct {
    ID    NoteID
    Users []UserID 
}

Or, using a separate entity to represent the relationship:

type UserID string
type NoteID string

type User struct {
    ID UserID
}

type Note struct {
    ID NoteID
}

type UserNote struct {
    UserID UserID
    NoteID NoteID
}

Using BelongsTo, and ReferencesMany

You can use the following functions to define relationships:

  • BelongsTo: Establishes a one-to-many relationship using a foreign key.
  • ReferencesMany: Establishes a one-to-many relationship using a slice of related IDs.
var _ = relationship.BelongsTo[Note, User](func(note *Note) *UserID {
    return &note.OwnerID
})

var _ = relationship.ReferencesMany[User, Note](func(user *User) *[]NoteID {
    return &user.OwnedNotes
})

Documentation

Overview

Package erm stands for Entity-Relationship Modeling

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Associate

func Associate(a, b any) error

func BelongsTo

func BelongsTo[Who, ToWhom any, ToWhomID comparable](accessor extid.Accessor[Who, ToWhomID]) func()

BelongsTo is a HasMany relationship, where "Who" belongs to "ToWhom" through the "ToWhomID".

Example
package main

import (
	"go.llib.dev/frameless/port/crud/relationship"
)

func main() {
	type AID string
	type A struct {
		ID AID
	}

	type BID string
	type B struct {
		ID     BID
		TheAID AID
	}

	// describe how the two Entity Type is in relationship
	// BelongsTo[B, A] -> "B" belongs to "A" through the "B"."TheAID"
	var _ = relationship.BelongsTo[B, A](func(b *B) *AID {
		return &b.TheAID
	})
}

func HasReference

func HasReference(from, to any) bool

func ReferencesMany

func ReferencesMany[A, B any, BID comparable](accessor extid.Accessor[A, []BID]) func()

ReferencesMany is a HasMany relationship, where A references many B by a slice of B IDs.

Example
package main

import (
	"go.llib.dev/frameless/port/crud/relationship"
)

func main() {
	type AID string
	type BID string

	type A struct {
		ID    AID
		BRefs []BID
	}

	type B struct {
		ID BID
	}

	// describe how the two Entity Type is in relationship
	// BelongsTo[B, A] -> "B" belongs to "A" through the "B"."TheAID"
	var _ = relationship.ReferencesMany[A, B](func(a *A) *[]BID {
		return &a.BRefs
	})
}
func Related(a, b any) bool

Types

This section is empty.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL