github.com/Accefy/pop@v0.0.0-20230428174248-e9f677eab5b9/callbacks.go (about)

     1  package pop
     2  
     3  import (
     4  	"reflect"
     5  
     6  	"golang.org/x/sync/errgroup"
     7  )
     8  
     9  // AfterFindable callback will be called after a record, or records,
    10  // has been retrieved from the database.
    11  type AfterFindable interface {
    12  	AfterFind(*Connection) error
    13  }
    14  
    15  // AfterEagerFindable callback will be called after a record, or records,
    16  // has been retrieved from the database and their associations have been
    17  // eagerly loaded.
    18  type AfterEagerFindable interface {
    19  	AfterEagerFind(*Connection) error
    20  }
    21  
    22  func (m *Model) afterFind(c *Connection, eager bool) error {
    23  	if eager {
    24  		if x, ok := m.Value.(AfterEagerFindable); ok {
    25  			if err := x.AfterEagerFind(c); err != nil {
    26  				return err
    27  			}
    28  		}
    29  	} else {
    30  		if x, ok := m.Value.(AfterFindable); ok {
    31  			if err := x.AfterFind(c); err != nil {
    32  				return err
    33  			}
    34  		}
    35  	}
    36  
    37  	// if the "model" is a slice/array we want
    38  	// to loop through each of the elements in the collection
    39  	// and call AfterFind on them if they exist.
    40  	rv := reflect.Indirect(reflect.ValueOf(m.Value))
    41  	kind := rv.Kind()
    42  	if kind != reflect.Slice && kind != reflect.Array {
    43  		return nil
    44  	}
    45  
    46  	wg := &errgroup.Group{}
    47  	for i := 0; i < rv.Len(); i++ {
    48  		elem := rv.Index(i).Addr()
    49  
    50  		if eager {
    51  			if x, ok := elem.Interface().(AfterEagerFindable); ok {
    52  				wg.Go(func() error {
    53  					return x.AfterEagerFind(c)
    54  				})
    55  			}
    56  		} else {
    57  			if x, ok := elem.Interface().(AfterFindable); ok {
    58  				wg.Go(func() error {
    59  					return x.AfterFind(c)
    60  				})
    61  			}
    62  		}
    63  	}
    64  
    65  	return wg.Wait()
    66  }
    67  
    68  // BeforeSaveable callback will be called before a record is
    69  // either created or updated in the database.
    70  type BeforeSaveable interface {
    71  	BeforeSave(*Connection) error
    72  }
    73  
    74  func (m *Model) beforeSave(c *Connection) error {
    75  	if x, ok := m.Value.(BeforeSaveable); ok {
    76  		return x.BeforeSave(c)
    77  	}
    78  	return nil
    79  }
    80  
    81  // BeforeCreateable callback will be called before a record is
    82  // created in the database.
    83  type BeforeCreateable interface {
    84  	BeforeCreate(*Connection) error
    85  }
    86  
    87  func (m *Model) beforeCreate(c *Connection) error {
    88  	if x, ok := m.Value.(BeforeCreateable); ok {
    89  		return x.BeforeCreate(c)
    90  	}
    91  	return nil
    92  }
    93  
    94  // BeforeUpdateable callback will be called before a record is
    95  // updated in the database.
    96  type BeforeUpdateable interface {
    97  	BeforeUpdate(*Connection) error
    98  }
    99  
   100  func (m *Model) beforeUpdate(c *Connection) error {
   101  	if x, ok := m.Value.(BeforeUpdateable); ok {
   102  		return x.BeforeUpdate(c)
   103  	}
   104  	return nil
   105  }
   106  
   107  // BeforeDestroyable callback will be called before a record is
   108  // destroyed in the database.
   109  type BeforeDestroyable interface {
   110  	BeforeDestroy(*Connection) error
   111  }
   112  
   113  func (m *Model) beforeDestroy(c *Connection) error {
   114  	if x, ok := m.Value.(BeforeDestroyable); ok {
   115  		return x.BeforeDestroy(c)
   116  	}
   117  	return nil
   118  }
   119  
   120  // BeforeValidateable callback will be called before a record is
   121  // validated during
   122  // ValidateAndCreate, ValidateAndUpdate, or ValidateAndSave
   123  type BeforeValidateable interface {
   124  	BeforeValidate(*Connection) error
   125  }
   126  
   127  func (m *Model) beforeValidate(c *Connection) error {
   128  	if x, ok := m.Value.(BeforeValidateable); ok {
   129  		return x.BeforeValidate(c)
   130  	}
   131  	return nil
   132  }
   133  
   134  // AfterDestroyable callback will be called after a record is
   135  // destroyed in the database.
   136  type AfterDestroyable interface {
   137  	AfterDestroy(*Connection) error
   138  }
   139  
   140  func (m *Model) afterDestroy(c *Connection) error {
   141  	if x, ok := m.Value.(AfterDestroyable); ok {
   142  		return x.AfterDestroy(c)
   143  	}
   144  	return nil
   145  }
   146  
   147  // AfterUpdateable callback will be called after a record is
   148  // updated in the database.
   149  type AfterUpdateable interface {
   150  	AfterUpdate(*Connection) error
   151  }
   152  
   153  func (m *Model) afterUpdate(c *Connection) error {
   154  	if x, ok := m.Value.(AfterUpdateable); ok {
   155  		return x.AfterUpdate(c)
   156  	}
   157  	return nil
   158  }
   159  
   160  // AfterCreateable callback will be called after a record is
   161  // created in the database.
   162  type AfterCreateable interface {
   163  	AfterCreate(*Connection) error
   164  }
   165  
   166  func (m *Model) afterCreate(c *Connection) error {
   167  	if x, ok := m.Value.(AfterCreateable); ok {
   168  		return x.AfterCreate(c)
   169  	}
   170  	return nil
   171  }
   172  
   173  // AfterSaveable callback will be called after a record is
   174  // either created or updated in the database.
   175  type AfterSaveable interface {
   176  	AfterSave(*Connection) error
   177  }
   178  
   179  func (m *Model) afterSave(c *Connection) error {
   180  	if x, ok := m.Value.(AfterSaveable); ok {
   181  		return x.AfterSave(c)
   182  	}
   183  	return nil
   184  }