callbacks.go
func VerifyReferencesValidator(pairs map[string]coal.Model) *Callback {
	return C("fire/VerifyReferencesValidator", Only(Create, Update), func(ctx *Context) error {
		// check all references
		for field, collection := range pairs {
			// read referenced id
			ref := ctx.Model.MustGet(field)

			// continue if reference is not set
			if oid, ok := ref.(*bson.ObjectId); ok && oid == nil {
				continue
			}

			// continue if slice is empty
			if ids, ok := ref.([]bson.ObjectId); ok && ids == nil {
				continue
			}

			// handle to-many relationships
			if ids, ok := ref.([]bson.ObjectId); ok {
				// prepare query
				query := bson.M{"_id": bson.M{"$in": ids}}

				// count entities in database
				ctx.Tracer.Push("mgo/Query.Count")
				ctx.Tracer.Tag("query", query)
				n, err := ctx.Store.DB().C(coal.C(collection)).Find(query).Count()
				if err != nil {
					return err
				}
				ctx.Tracer.Pop()

				// check for existence
				if n != len(ids) {
					return E("missing references for field " + field)
				}

				continue
			}

			// handle to-one relationships

			// count entities in database
			ctx.Tracer.Push("mgo/Query.Count")
			ctx.Tracer.Tag("id", ref)
			n, err := ctx.Store.DB().C(coal.C(collection)).FindId(ref).Limit(1).Count()
			if err != nil {
				return err
			}
			ctx.Tracer.Pop()

			// check for existence
			if n != 1 {
				return E("missing reference for field " + field)
			}
		}

		// pass validation
		return nil
	})
}
func VerifyReferencesValidator(pairs map[string]coal.Model) *Callback {
	return C("fire/VerifyReferencesValidator", Only(Create, Update), func(ctx *Context) error {
		// check all references
		for field, collection := range pairs {
			// read referenced id
			ref := ctx.Model.MustGet(field)

			// continue if reference is not set
			if oid, ok := ref.(*bson.ObjectId); ok && oid == nil {
				continue
			}

			// continue if slice is empty
			if ids, ok := ref.([]bson.ObjectId); ok && ids == nil {
				continue
			}

			// handle to-many relationships
			if ids, ok := ref.([]bson.ObjectId); ok {
				// prepare query
				query := bson.M{"_id": bson.M{"$in": ids}}

				// count entities in database
				ctx.Tracer.Push("mgo/Query.Count")
				ctx.Tracer.Tag("query", query)
				n, err := ctx.Store.DB().C(coal.C(collection)).Find(query).Count()
				if err != nil {
					return err
				}
				ctx.Tracer.Pop()

				// check for existence
				if n != len(ids) {
					return E("missing references for field " + field)
				}

				continue
			}

			// handle to-one relationships

			// count entities in database
			ctx.Tracer.Push("mgo/Query.Count")
			ctx.Tracer.Tag("id", ref)
			n, err := ctx.Store.DB().C(coal.C(collection)).FindId(ref).Limit(1).Count()
			if err != nil {
				return err
			}
			ctx.Tracer.Pop()

			// check for existence
			if n != 1 {
				return E("missing reference for field " + field)
			}
		}

		// pass validation
		return nil
	})
}
// VerifyReferencesValidator makes sure all references in the document are
// existing by counting the references on the related collections.
//
// References are defined by passing pairs of fields and models who might be
// referenced by the current model:
//
//	fire.VerifyReferencesValidator(map[string]coal.Model{
//		"Post": &Post{},
//		"Author": &User{},
//	})
//
// The callbacks supports to-one, optional to-one and to-many relationships.