Пример #1
0
// BelongsTo signifies a relationship between this model and a
// Parent.  The Parent has the child, and the Child belongs
// to the Parent.
// Usage:  BelongsTo("User")
func BelongsTo(parent string) {
	if r, ok := relationalModelDefinition(false); ok {
		idfield := &gorma.RelationalFieldDefinition{
			Name:              codegen.Goify(inflect.Singularize(parent), true) + "ID",
			Description:       "Belongs To " + codegen.Goify(inflect.Singularize(parent), true),
			Parent:            r,
			Datatype:          gorma.BelongsTo,
			DatabaseFieldName: SanitizeDBFieldName(codegen.Goify(inflect.Singularize(parent), true) + "ID"),
		}

		r.RelationalFields[idfield.Name] = idfield
		bt, ok := r.Parent.RelationalModels[codegen.Goify(inflect.Singularize(parent), true)]
		if ok {
			r.BelongsTo[bt.Name] = bt
		} else {
			models := &gorma.RelationalModelDefinition{
				Name:             codegen.Goify(inflect.Singularize(parent), true),
				Parent:           r.Parent,
				RelationalFields: make(map[string]*gorma.RelationalFieldDefinition),
				BelongsTo:        make(map[string]*gorma.RelationalModelDefinition),
				HasMany:          make(map[string]*gorma.RelationalModelDefinition),
				HasOne:           make(map[string]*gorma.RelationalModelDefinition),
				ManyToMany:       make(map[string]*gorma.ManyToManyDefinition),
			}
			r.BelongsTo[models.Name] = models
		}
	}
}
Пример #2
0
func pluralize(c int, s string, format bool) string {
	if c == 1 {
		if format {
			return fmt.Sprintf("1 %s", inflect.Singularize(s))
		}

		return fmt.Sprintf("%s", inflect.Singularize(s))
	}

	if format {
		return fmt.Sprintf("%d %s", c, inflect.Pluralize(s))
	}

	return fmt.Sprintf("%s", inflect.Pluralize(s))
}
Пример #3
0
// HasMany signifies a relationship between this model and a
// set of Children.  The Parent has the children, and the Children belong
// to the Parent.  The first parameter becomes the name of the
// field in the model struct, the second parameter is the name
// of the child model.  The Child model will have a ParentID field
// appended to the field list.  The Parent model definition will use
// the first parameter as the field name in the struct definition.
// Usage:  HasMany("Orders", "Order")
// Struct field definition:  Children	[]Child
func HasMany(name, child string) {
	if r, ok := relationalModelDefinition(false); ok {
		field := &gorma.RelationalFieldDefinition{
			Name:        codegen.Goify(name, true),
			HasMany:     child,
			Description: "has many " + inflect.Pluralize(child),
			Datatype:    gorma.HasMany,
			Parent:      r,
		}
		r.RelationalFields[field.Name] = field
		var model *gorma.RelationalModelDefinition
		model, ok := r.Parent.RelationalModels[child]
		if ok {
			r.HasMany[child] = model
			// create the fk field
			f := &gorma.RelationalFieldDefinition{
				Name:              codegen.Goify(inflect.Singularize(r.Name), true) + "ID",
				HasMany:           child,
				Description:       "has many " + child,
				Datatype:          gorma.HasManyKey,
				Parent:            model,
				DatabaseFieldName: SanitizeDBFieldName(codegen.Goify(inflect.Singularize(r.Name), true) + "ID"),
			}
			model.RelationalFields[f.Name] = f
		} else {
			model = &gorma.RelationalModelDefinition{
				Name:             child,
				Parent:           r.Parent,
				RelationalFields: make(map[string]*gorma.RelationalFieldDefinition),
				BelongsTo:        make(map[string]*gorma.RelationalModelDefinition),
				HasMany:          make(map[string]*gorma.RelationalModelDefinition),
				HasOne:           make(map[string]*gorma.RelationalModelDefinition),
				ManyToMany:       make(map[string]*gorma.ManyToManyDefinition),
			}
			r.HasMany[child] = model
			// create the fk field
			f := &gorma.RelationalFieldDefinition{
				Name:              codegen.Goify(inflect.Singularize(r.Name), true) + "ID",
				HasMany:           child,
				Description:       "has many " + child,
				Datatype:          gorma.HasManyKey,
				Parent:            model,
				DatabaseFieldName: SanitizeDBFieldName(codegen.Goify(inflect.Singularize(r.Name), true) + "ID"),
			}
			model.RelationalFields[f.Name] = f
		}
	}
}
Пример #4
0
func createDescriptor(iface interface{}, router *ResourceRouter) descriptor {
	pv := reflect.ValueOf(iface)
	v := reflect.Indirect(pv)
	t := v.Type()

	var varName string
	if nameGetter, hasVarName := iface.(interface {
		VarName() string
	}); hasVarName {
		varName = nameGetter.VarName()
	} else {
		varName = inflect.Singularize(t.Name())
	}

	var routeName string
	if nameGetter, hasRouteName := iface.(interface {
		RouteName() string
	}); hasRouteName {
		routeName = nameGetter.RouteName()
	} else {
		routeName = strings.ToLower(t.Name())
	}

	return descriptor{
		obj:       iface,
		router:    router,
		t:         t,
		varName:   varName,
		routeName: routeName,
	}
}
Пример #5
0
// singularize returns the singular form of a single word.
func singularize(in interface{}) (string, error) {
	word, err := cast.ToStringE(in)
	if err != nil {
		return "", err
	}
	return inflect.Singularize(word), nil
}
Пример #6
0
func parseReturn(kind, resName, contentType string) string {
	switch kind {
	case "show":
		return refType(resName)
	case "index":
		return fmt.Sprintf("[]%s", refType(resName))
	case "create":
		if _, ok := noMediaTypeResources[resName]; ok {
			return "map[string]interface{}"
		}
		return "*" + inflect.Singularize(resName) + "Locator"
	case "update", "destroy":
		return ""
	case "current_instances":
		return "[]*Instance"
	default:
		switch {
		case len(contentType) == 0:
			return ""
		case strings.Index(contentType, "application/vnd.rightscale.") == 0:
			if contentType == "application/vnd.rightscale.text" {
				return "string"
			}
			elems := strings.SplitN(contentType[27:], ";", 2)
			name := refType(inflect.Camelize(elems[0]))
			if len(elems) > 1 && elems[1] == "type=collection" {
				name = "[]" + refType(inflect.Camelize(elems[0]))
			}
			return name
		default: // Shouldn't be here
			panic("api15gen: Unknown content type " + contentType)
		}
	}

}
Пример #7
0
// HasOne signifies a relationship between this model and another model.
// If this model HasOne(OtherModel), then OtherModel is expected
// to have a ThisModelID field as a Foreign Key to this model's
// Primary Key.  ThisModel will have a field named OtherModel of type
// OtherModel.
// Usage:  HasOne("Proposal")
func HasOne(child string) {
	if r, ok := relationalModelDefinition(false); ok {
		field := &gorma.RelationalFieldDefinition{
			Name:        codegen.Goify(inflect.Singularize(child), true),
			HasOne:      child,
			Description: "has one " + child,
			Datatype:    gorma.HasOne,
			Parent:      r,
		}
		r.RelationalFields[field.Name] = field
		bt, ok := r.Parent.RelationalModels[child]
		if ok {
			r.HasOne[child] = bt
			// create the fk field
			f := &gorma.RelationalFieldDefinition{
				Name:              codegen.Goify(inflect.Singularize(r.Name), true) + "ID",
				HasOne:            child,
				Description:       "has one " + child,
				Datatype:          gorma.HasOneKey,
				Parent:            bt,
				DatabaseFieldName: SanitizeDBFieldName(codegen.Goify(inflect.Singularize(r.Name), true) + "ID"),
			}
			bt.RelationalFields[f.Name] = f
		} else {
			models := &gorma.RelationalModelDefinition{
				Name:             child,
				Parent:           r.Parent,
				RelationalFields: make(map[string]*gorma.RelationalFieldDefinition),
				BelongsTo:        make(map[string]*gorma.RelationalModelDefinition),
				HasMany:          make(map[string]*gorma.RelationalModelDefinition),
				HasOne:           make(map[string]*gorma.RelationalModelDefinition),
				ManyToMany:       make(map[string]*gorma.ManyToManyDefinition),
			}
			r.HasOne[child] = models
			// create the fk field
			f := &gorma.RelationalFieldDefinition{
				Name:              codegen.Goify(inflect.Singularize(r.Name), true) + "ID",
				HasOne:            child,
				Description:       "has one " + child,
				Datatype:          gorma.HasOneKey,
				Parent:            bt,
				DatabaseFieldName: SanitizeDBFieldName(codegen.Goify(inflect.Singularize(r.Name), true) + "ID"),
			}
			models.RelationalFields[f.Name] = f
		}
	}
}
Пример #8
0
// Name of go type for resource with given name
// It should always be the same (camelized) but there are some resources that don't have a media
// type so for these we use a map.
func resourceType(resName string) string {
	if resName == "ChildAccounts" {
		return "Account"
	}
	if _, ok := noMediaTypeResources[resName]; ok {
		return "map[string]interface{}"
	}
	return inflect.Singularize(resName)
}
Пример #9
0
func serviceResource(svc *Service, resource string, w http.ResponseWriter) (*Resource, error) {
	res, ok := svc.Resources[inflect.Singularize(resource)]
	if !ok {
		return nil, httpError(w, 404,
			"Sorry, %s does not have resource %s, available resources: %+v",
			svc.Name, resource, svc.ResourceNames())
	}
	return res, nil
}
Пример #10
0
func serviceResource(svc *Service, resource string, w http.ResponseWriter) (*Resource, error) {
	res, ok := svc.Resources[inflect.Singularize(resource)]
	if !ok {
		w.WriteHeader(404)
		fmt.Fprintf(w, "Sorry, %s does not have resource %s, available resources: %+v",
			svc.Name, resource, svc.ResourceNames())
		return nil, fmt.Errorf("%s does not have resource %s", svc.Name, resource)
	}
	return res, nil
}
Пример #11
0
// build the path that precedes the controller name
func buildParentPath(parentControllers []string) (string, error) {
	path := "/"
	for i := len(parentControllers) - 1; i >= 0; i-- {
		c := parentControllers[i]
		name, err := getResourceName(c)
		if err != nil {
			return "", err
		}
		path += strings.ToLower(name) + "/:" + inflect.Singularize(name) + "Id/"
	}
	return path, nil
}
Пример #12
0
// Create API descriptor from raw resources and types
func (a *ApiAnalyzer) AnalyzeResource(name string, res map[string]interface{}, desc *gen.ApiDescriptor) error {
	name = inflect.Singularize(name)
	resource := gen.Resource{Name: name, ClientName: a.ClientName}

	// Description
	if d, ok := res["description"]; ok {
		resource.Description = removeBlankLines(d.(string))
	}

	// Attributes
	hasHref := false
	attributes := []*gen.Attribute{}
	m, ok := res["media_type"].(string)
	if ok {
		t, ok := a.RawTypes[m]
		if ok {
			attrs, ok := t["attributes"].(map[string]interface{})
			if ok {
				attributes = make([]*gen.Attribute, len(attrs))
				for idx, n := range sortedKeys(attrs) {
					if n == "href" {
						hasHref = true
					}
					param, err := a.AnalyzeAttribute(n, n, attrs[n].(map[string]interface{}))
					if err != nil {
						return err
					}
					attributes[idx] = &gen.Attribute{n, inflect.Camelize(n), param.Signature()}
				}
			}
		}
	}
	resource.Attributes = attributes
	if hasHref {
		resource.LocatorFunc = locatorFunc(name)
	}

	// Actions
	actions, err := a.AnalyzeActions(name, res)
	if err != nil {
		return err
	}
	resource.Actions = actions

	// Name and done
	resName := toGoTypeName(name, false)
	desc.Resources[resName] = &resource
	desc.ResourceNames = append(desc.ResourceNames, resName)

	return nil
}
Пример #13
0
func init() {
	funcMap = template.FuncMap{
		"urlize":       helpers.URLize,
		"sanitizeURL":  helpers.SanitizeURL,
		"sanitizeurl":  helpers.SanitizeURL,
		"eq":           Eq,
		"ne":           Ne,
		"gt":           Gt,
		"ge":           Ge,
		"lt":           Lt,
		"le":           Le,
		"dict":         Dictionary,
		"in":           In,
		"slicestr":     Slicestr,
		"substr":       Substr,
		"split":        Split,
		"intersect":    Intersect,
		"isSet":        IsSet,
		"isset":        IsSet,
		"echoParam":    ReturnWhenSet,
		"safeHTML":     SafeHTML,
		"safeCSS":      SafeCSS,
		"safeURL":      SafeURL,
		"absURL":       func(a string) template.HTML { return template.HTML(helpers.AbsURL(a)) },
		"relURL":       func(a string) template.HTML { return template.HTML(helpers.RelURL(a)) },
		"markdownify":  Markdownify,
		"first":        First,
		"last":         Last,
		"after":        After,
		"where":        Where,
		"delimit":      Delimit,
		"sort":         Sort,
		"highlight":    Highlight,
		"add":          func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '+') },
		"sub":          func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '-') },
		"div":          func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '/') },
		"mod":          Mod,
		"mul":          func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '*') },
		"modBool":      ModBool,
		"lower":        func(a string) string { return strings.ToLower(a) },
		"upper":        func(a string) string { return strings.ToUpper(a) },
		"title":        func(a string) string { return strings.Title(a) },
		"partial":      Partial,
		"ref":          Ref,
		"relref":       RelRef,
		"apply":        Apply,
		"chomp":        Chomp,
		"replace":      Replace,
		"trim":         Trim,
		"dateFormat":   DateFormat,
		"getJSON":      GetJSON,
		"getCSV":       GetCSV,
		"readDir":      ReadDir,
		"seq":          helpers.Seq,
		"getenv":       func(varName string) string { return os.Getenv(varName) },
		"base64Decode": Base64Decode,
		"base64Encode": Base64Encode,
		"pluralize": func(in interface{}) (string, error) {
			word, err := cast.ToStringE(in)
			if err != nil {
				return "", err
			}
			return inflect.Pluralize(word), nil
		},
		"singularize": func(in interface{}) (string, error) {
			word, err := cast.ToStringE(in)
			if err != nil {
				return "", err
			}
			return inflect.Singularize(word), nil
		},
	}
}
Пример #14
0
// writeSchema writes SQL statements to CREATE, INSERT,
// UPDATE and DELETE values from Table t.
func writeSchema(w io.Writer, d schema.Dialect, t *schema.Table) {

	writeConst(w,
		d.Table(t),
		"create", inflect.Singularize(t.Name), "stmt",
	)

	writeConst(w,
		d.Insert(t),
		"insert", inflect.Singularize(t.Name), "stmt",
	)

	writeConst(w,
		d.Select(t, nil),
		"select", inflect.Singularize(t.Name), "stmt",
	)

	writeConst(w,
		d.SelectRange(t, nil),
		"select", inflect.Singularize(t.Name), "range", "stmt",
	)

	writeConst(w,
		d.SelectCount(t, nil),
		"select", inflect.Singularize(t.Name), "count", "stmt",
	)

	if len(t.Primary) != 0 {
		writeConst(w,
			d.Select(t, t.Primary),
			"select", inflect.Singularize(t.Name), "pkey", "stmt",
		)

		writeConst(w,
			d.Update(t, t.Primary),
			"update", inflect.Singularize(t.Name), "pkey", "stmt",
		)

		writeConst(w,
			d.Delete(t, t.Primary),
			"delete", inflect.Singularize(t.Name), "pkey", "stmt",
		)
	}

	for _, ix := range t.Index {

		writeConst(w,
			d.Index(t, ix),
			"create", ix.Name, "stmt",
		)

		writeConst(w,
			d.Select(t, ix.Fields),
			"select", ix.Name, "stmt",
		)

		if !ix.Unique {

			writeConst(w,
				d.SelectRange(t, ix.Fields),
				"select", ix.Name, "range", "stmt",
			)

			writeConst(w,
				d.SelectCount(t, ix.Fields),
				"select", ix.Name, "count", "stmt",
			)

		} else {

			writeConst(w,
				d.Update(t, ix.Fields),
				"update", ix.Name, "stmt",
			)

			writeConst(w,
				d.Delete(t, ix.Fields),
				"delete", ix.Name, "stmt",
			)
		}
	}
}
Пример #15
0
// singularize returns singular version of a word
func singularize(s string) string {
	return inflect.Singularize(s)
}
Пример #16
0
// AnalyzeResource analyzes the given resource and updates the Resources and ParamTypes analyzer
// fields accordingly
func (a *APIAnalyzer) AnalyzeResource(name string, resource interface{}, descriptor *gen.APIDescriptor) {
	var res = resource.(map[string]interface{})

	// Compute description
	var description string
	if d, ok := res["description"].(string); ok {
		description = d
	}

	// Compute attributes
	var attributes []*gen.Attribute
	var atts map[string]interface{}
	if m, ok := res["media_type"].(map[string]interface{}); ok {
		atts = m["attributes"].(map[string]interface{})
		attributes = make([]*gen.Attribute, len(atts))
		for idx, n := range sortedKeys(atts) {
			at, ok := a.attributeTypes[n+"#"+name]
			if !ok {
				at = a.attributeTypes[n]
			}
			attributes[idx] = &gen.Attribute{n, inflect.Camelize(n), at}
		}
	} else {
		attributes = []*gen.Attribute{}
	}

	// Compute actions
	var methods = res["methods"].(map[string]interface{})
	var actionNames = sortedKeys(methods)
	var actions = []*gen.Action{}
	for _, actionName := range actionNames {
		var m = methods[actionName]
		var meth = m.(map[string]interface{})
		var params map[string]interface{}
		if p, ok := meth["parameters"]; ok {
			params = p.(map[string]interface{})
		}
		var description = "No description provided for " + actionName + "."
		if d, _ := meth["description"]; d != nil {
			description = d.(string)
		}
		var pathPatterns = ParseRoute(fmt.Sprintf("%s#%s", name, actionName),
			meth["route"].(string))
		if len(pathPatterns) == 0 {
			// Custom action
			continue
		}
		var allParamNames = make([]string, len(params))
		var i = 0
		for n := range params {
			allParamNames[i] = n
			i++
		}
		sort.Strings(allParamNames)

		var contentType string
		if c, ok := meth["content_type"].(string); ok {
			contentType = c
		}
		var paramAnalyzer = NewAnalyzer(params)
		paramAnalyzer.Analyze()

		// Record new parameter types
		var paramTypeNames = make([]string, len(paramAnalyzer.ParamTypes))
		var idx = 0
		for n := range paramAnalyzer.ParamTypes {
			paramTypeNames[idx] = n
			idx++
		}
		sort.Strings(paramTypeNames)
		for _, name := range paramTypeNames {
			var pType = paramAnalyzer.ParamTypes[name]
			if _, ok := a.rawTypes[name]; ok {
				a.rawTypes[name] = append(a.rawTypes[name], pType)
			} else {
				a.rawTypes[name] = []*gen.ObjectDataType{pType}
			}
		}

		// Update description with parameter descriptions
		var mandatory []string
		var optional []string
		for _, p := range paramAnalyzer.Params {
			if p.Mandatory {
				desc := p.Name
				if p.Description != "" {
					desc += ": " + strings.TrimSpace(p.Description)
				}
				mandatory = append(mandatory, desc)
			} else {
				desc := p.Name
				if p.Description != "" {
					desc += ": " + strings.TrimSpace(p.Description)
				}
				optional = append(optional, desc)
			}
		}
		if len(mandatory) > 0 {
			sort.Strings(mandatory)
			if !strings.HasSuffix(description, "\n") {
				description += "\n"
			}
			description += "Required parameters:\n\t" + strings.Join(mandatory, "\n\t")
		}
		if len(optional) > 0 {
			sort.Strings(optional)
			if !strings.HasSuffix(description, "\n") {
				description += "\n"
			}
			description += "Optional parameters:\n\t" + strings.Join(optional, "\n\t")
		}

		// Sort parameters by location
		actionParams := paramAnalyzer.Params
		leafParams := paramAnalyzer.LeafParams
		var pathParamNames []string
		var queryParamNames []string
		var payloadParamNames []string
		for _, p := range leafParams {
			n := p.Name
			if isQueryParam(n) {
				queryParamNames = append(queryParamNames, n)
				p.Location = gen.QueryParam
			} else if isPathParam(n, pathPatterns) {
				pathParamNames = append(pathParamNames, n)
				p.Location = gen.PathParam
			} else {
				payloadParamNames = append(payloadParamNames, n)
				p.Location = gen.PayloadParam
			}
		}
		for _, p := range actionParams {
			done := false
			for _, ap := range leafParams {
				if ap == p {
					done = true
					break
				}
			}
			if done {
				continue
			}
			n := p.Name
			if isQueryParam(n) {
				p.Location = gen.QueryParam
			} else if isPathParam(n, pathPatterns) {
				p.Location = gen.PathParam
			} else {
				p.Location = gen.PayloadParam
			}
		}

		// Mix in filters information
		if filters, ok := meth["filters"]; ok {
			var filterParam *gen.ActionParam
			for _, p := range actionParams {
				if p.Name == "filter" {
					filterParam = p
					break
				}
			}
			if filterParam != nil {
				values := sortedKeys(filters.(map[string]interface{}))
				ivalues := make([]interface{}, len(values))
				for i, v := range values {
					ivalues[i] = v
				}
				filterParam.ValidValues = ivalues
			}
		}

		// Record action
		action := gen.Action{
			Name:              actionName,
			MethodName:        inflect.Camelize(actionName),
			Description:       removeBlankLines(description),
			ResourceName:      inflect.Singularize(name),
			PathPatterns:      pathPatterns,
			Params:            actionParams,
			LeafParams:        paramAnalyzer.LeafParams,
			Return:            parseReturn(actionName, name, contentType),
			ReturnLocation:    actionName == "create" && name != "Oauth2",
			PathParamNames:    pathParamNames,
			QueryParamNames:   queryParamNames,
			PayloadParamNames: payloadParamNames,
		}
		actions = append(actions, &action)
	}

	// We're done!
	name = inflect.Singularize(name)
	descriptor.Resources[name] = &gen.Resource{
		Name:        name,
		ClientName:  "API",
		Description: removeBlankLines(description),
		Actions:     actions,
		Attributes:  attributes,
		LocatorFunc: LocatorFunc(attributes, name),
	}
}
Пример #17
0
func fieldAssignmentModelToType(model *RelationalModelDefinition, ut *design.ViewDefinition, v, mtype, utype string) string {
	tmp := 1
	var fieldAssignments []string

	if !strings.Contains(ut.Name, "link") {
		for ln, lnd := range ut.Parent.Links {
			ln = codegen.Goify(ln, true)
			s := inflect.Singularize(ln)
			var ifb string
			if lnd.MediaType().IsArray() {
				mt := codegen.Goify(lnd.MediaType().ToArray().ElemType.Type.(*design.MediaTypeDefinition).TypeName, true) + "LinkCollection"
				fa := make([]string, 4)
				fa[0] = fmt.Sprintf("tmp%d := make(app.%s, len(%s.%s))", tmp, mt, v, ln)
				fa[1] = fmt.Sprintf("for i, elem := range %s.%s {", v, ln)
				fa[2] = fmt.Sprintf("	tmp%d[i] = elem.%sTo%sLink()", tmp, s, s)
				fa[3] = fmt.Sprintf("}")
				ifb = strings.Join(fa, "\n")
			} else {
				ifb = fmt.Sprintf("tmp%d := %s.%s.%sTo%sLink()", tmp, v, ln, s, s)
			}

			fieldAssignments = append(fieldAssignments, ifb)
			ifd := fmt.Sprintf("%s.Links = &app.%sLinks{%s: tmp%d}", utype, codegen.Goify(utype, true), codegen.Goify(ln, true), tmp)
			fieldAssignments = append(fieldAssignments, ifd)
			tmp++
		}
	}

	// Get a sortable slice of field names
	var keys []string
	for k := range model.RelationalFields {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	for _, fname := range keys {
		field := model.RelationalFields[fname]

		var mpointer, upointer bool
		mpointer = field.Nullable
		obj := ut.Type.ToObject()
		definition := ut.Parent.Definition()

		if field.Datatype == "" {
			continue
		}

		for key := range obj {
			gfield := obj[key]
			if field.Underscore() == key || field.DatabaseFieldName == key {
				// this is our field
				if gfield.Type.IsObject() || definition.IsPrimitivePointer(key) {
					upointer = true
				} else {
					// set it explicitly because we're reusing the same bool
					upointer = false
				}

				if field.Datatype == HasOne {
					fa := fmt.Sprintf("%s.%s = %s.%s.%sTo%s()", utype, codegen.Goify(field.FieldName, true), v, codegen.Goify(field.FieldName, true), codegen.Goify(field.FieldName, true), codegen.Goify(field.FieldName, true))
					fieldAssignments = append(fieldAssignments, fa)
					continue
				}

				prefix := ""
				if upointer && !mpointer {
					// ufield = &mfield
					prefix = "&"
				} else if mpointer && !upointer {
					// ufield = *mfield (rare if never?)
					prefix = "*"
				} else if !upointer && !mpointer {
					prefix = ""
				}
				/// test to see if it's a go object here and add the appending stuff

				if gfield.Type.IsObject() || gfield.Type.IsArray() {
					tmp++
					ifa := fmt.Sprintf("for i%d := range %s.%s {", tmp, v, codegen.Goify(fname, true))
					fieldAssignments = append(fieldAssignments, ifa)
					ifd := fmt.Sprintf("tmp%d := &%s.%s[i%d]", tmp, v, codegen.Goify(fname, true), tmp)
					fieldAssignments = append(fieldAssignments, ifd)
					ifb := fmt.Sprintf("%s.%s = append(%s.%s, tmp%d.%sTo%s())", utype, codegen.Goify(key, true), utype, codegen.Goify(key, true), tmp, inflect.Singularize(codegen.Goify(key, true)), inflect.Singularize(codegen.Goify(key, true)))
					fieldAssignments = append(fieldAssignments, ifb)
					ifc := fmt.Sprintf("}")
					fieldAssignments = append(fieldAssignments, ifc)

				} else {
					fa := fmt.Sprintf("\t%s.%s = %s%s.%s", utype, codegen.Goify(key, true), prefix, v, codegen.Goify(fname, true))
					fieldAssignments = append(fieldAssignments, fa)
				}
			} else {
				fn := codegen.Goify(strings.Replace(field.FieldName, "ID", "", -1), false)
				if fn == key {
					gfield, ok := obj[fn]
					if ok {
						fa := fmt.Sprintf("tmp%d := &%s.%s", tmp, mtype, codegen.Goify(fn, true))
						fieldAssignments = append(fieldAssignments, fa)
						var view string
						if gfield.View != "" {
							view = gfield.View
						}
						fa = fmt.Sprintf("%s.%s = tmp%d.%sTo%s%s() // %s", utype, codegen.Goify(fn, true), tmp, codegen.Goify(fn, true), codegen.Goify(fn, true), codegen.Goify(view, true))

						fieldAssignments = append(fieldAssignments, fa)
						tmp++
					}
				}
			}
		}
	}
	return strings.Join(fieldAssignments, "\n")
}