Пример #1
0
// Run generates model templates.
func (c *generateModelCommand) Run(args []string) error {
	if len(args) < 1 || args[0] == "" {
		return fmt.Errorf("no NAME given")
	}
	name := args[0]
	if c.option.ORM == "" {
		c.option.ORM = defaultORM
	}
	mt, exists := modelTypeMap[c.option.ORM]
	if !exists {
		return fmt.Errorf("unsupported ORM: `%v'", c.option.ORM)
	}
	m := mt.FieldTypeMap()
	var fields []modelField
	for _, arg := range args[1:] {
		input := strings.Split(arg, ":")
		if len(input) != 2 {
			return fmt.Errorf("invalid argument format is specified: `%v'", arg)
		}
		name, t := input[0], input[1]
		if name == "" {
			return fmt.Errorf("field name isn't specified: `%v'", arg)
		}
		if t == "" {
			return fmt.Errorf("field type isn't specified: `%v'", arg)
		}
		ft, found := m[t]
		if !found {
			return fmt.Errorf("unsupported field type: `%v'", t)
		}
		fields = append(fields, modelField{
			Name:       util.ToCamelCase(name),
			Type:       ft.Name,
			Column:     util.ToSnakeCase(name),
			OptionTags: ft.OptionTags,
		})
	}
	camelCaseName := util.ToCamelCase(name)
	snakeCaseName := util.ToSnakeCase(name)
	data := map[string]interface{}{
		"Name":   camelCaseName,
		"Fields": fields,
	}
	templatePath, configTemplatePath := mt.TemplatePath()
	if err := util.CopyTemplate(templatePath, filepath.Join("app", "model", snakeCaseName+".go"), data); err != nil {
		return err
	}
	initPath := filepath.Join("db", "config.go")
	if _, err := os.Stat(initPath); os.IsNotExist(err) {
		if err := util.CopyTemplate(configTemplatePath, initPath, nil); err != nil {
			return err
		}
	}
	return nil
}
Пример #2
0
// Run generates the controller templates.
func (c *generateControllerCommand) Run(args []string) error {
	if len(args) < 1 || args[0] == "" {
		return fmt.Errorf("no NAME given")
	}
	name := args[0]
	camelCaseName := util.ToCamelCase(name)
	snakeCaseName := util.ToSnakeCase(name)
	receiverName := strings.ToLower(name)
	if len(receiverName) > 1 {
		receiverName = receiverName[:2]
	} else {
		receiverName = receiverName[:1]
	}
	data := map[string]interface{}{
		"Name":     camelCaseName,
		"Receiver": receiverName,
	}
	if err := util.CopyTemplate(
		filepath.Join(skeletonDir("controller"), "controller.go"+util.TemplateSuffix),
		filepath.Join("app", "controller", snakeCaseName+".go"), data); err != nil {
		return err
	}
	if err := util.CopyTemplate(
		filepath.Join(skeletonDir("controller"), "view.html"+util.TemplateSuffix),
		filepath.Join("app", "view", snakeCaseName+".html"), data); err != nil {
		return err
	}
	return addRouteToFile(name)
}
Пример #3
0
func addRouteToFile(name string) error {
	routeFilePath := filepath.Join("config", "routes.go")
	fset := token.NewFileSet()
	f, err := parser.ParseFile(fset, routeFilePath, nil, 0)
	if err != nil {
		return fmt.Errorf("failed to read file: %v", err)
	}
	routeStructName := util.ToCamelCase(name)
	routeName := util.ToSnakeCase(name)
	routeTableAST, err := findRouteTableAST(f)
	if err != nil {
		return err
	}
	if routeTableAST == nil {
		return nil
	}
	routeASTs := findRouteASTs(routeTableAST)
	if routeASTs == nil {
		return nil
	}
	if isRouteDefined(routeASTs, routeStructName) {
		return nil
	}
	routeFile, err := os.OpenFile(routeFilePath, os.O_RDWR, 0644)
	if err != nil {
		return fmt.Errorf("failed to open file: %v", err)
	}
	defer routeFile.Close()
	lastRouteAST := routeASTs[len(routeASTs)-1]
	offset := int64(fset.Position(lastRouteAST.End()).Offset)
	var buf bytes.Buffer
	if _, err := io.CopyN(&buf, routeFile, offset); err != nil {
		return fmt.Errorf("failed to read file: %v", err)
	}
	buf.WriteString(fmt.Sprintf(`, {
	Name:       "%s",
	Path:       "/%s",
	Controller: &controller.%s{},
}`, routeName, routeName, routeStructName))
	if _, err := io.Copy(&buf, routeFile); err != nil {
		return fmt.Errorf("failed to read file: %v", err)
	}
	formatted, err := format.Source(buf.Bytes())
	if err != nil {
		return fmt.Errorf("failed to format file: %v", err)
	}
	if _, err := routeFile.WriteAt(formatted, 0); err != nil {
		return fmt.Errorf("failed to update file: %v", err)
	}
	return nil
}
Пример #4
0
// Run generates unit skeleton files.
func (c *generateUnitCommand) Run(args []string) error {
	if len(args) < 1 || args[0] == "" {
		return fmt.Errorf("no NAME given")
	}
	name := args[0]
	camelCaseName := util.ToCamelCase(name)
	snakeCaseName := util.ToSnakeCase(name)
	data := map[string]interface{}{
		"Name": camelCaseName,
	}
	if err := util.CopyTemplate(
		filepath.Join(skeletonDir("unit"), "unit.go"+util.TemplateSuffix),
		filepath.Join("app", "unit", snakeCaseName+".go"), data); err != nil {
		return err
	}
	return nil
}
Пример #5
0
// Run generates migration templates.
func (c *generateMigrationCommand) Run(args []string) error {
	if len(args) < 1 || args[0] == "" {
		return fmt.Errorf("no NAME given")
	}
	name := args[0]
	if c.option.ORM == "" {
		c.option.ORM = defaultORM
	}
	orm, exists := ORM[c.option.ORM]
	if !exists {
		return fmt.Errorf("unsupported ORM: `%v'", c.option.ORM)
	}
	now := _time.Now().Format("20060102150405")
	data := map[string]interface{}{
		"Name":       util.ToCamelCase(name),
		"TimeStamp":  now,
		"ImportPath": orm.ImportPath(),
		"TxType":     reflect.TypeOf(orm.TransactionType()).String(),
	}
	if err := util.CopyTemplate(
		filepath.Join(skeletonDir("migration"), "migration.go"+util.TemplateSuffix),
		filepath.Join("db", "migration", fmt.Sprintf("%v_%v.go", now, util.ToSnakeCase(name))),
		data,
	); err != nil {
		return err
	}
	initPath := filepath.Join("db", "migration", "init.go")
	if _, err := os.Stat(initPath); os.IsNotExist(err) {
		appDir, err := util.FindAppDir()
		if err != nil {
			return err
		}
		if err := util.CopyTemplate(
			filepath.Join(skeletonDir("migration"), "init.go"+util.TemplateSuffix),
			initPath, map[string]interface{}{
				"typeName":     c.option.ORM,
				"tx":           strings.TrimSpace(util.GoString(orm)),
				"dbImportPath": path.Join(appDir, "db"),
			},
		); err != nil {
			return err
		}
	}
	return nil
}
Пример #6
0
func (params *Params) findFieldIndex(rtype reflect.Type, name string, index []int) []int {
	var embeddedFieldInfos []*embeddefFieldInfo
	for i := 0; i < rtype.NumField(); i++ {
		field := rtype.Field(i)
		if util.IsUnexportedField(field) {
			continue
		}
		if field.Anonymous {
			embeddedFieldInfos = append(embeddedFieldInfos, &embeddefFieldInfo{field, name, append(index, i)})
			continue
		}
		if field.Name == util.ToCamelCase(name) {
			return append(index, i)
		}
	}
	for _, fi := range embeddedFieldInfos {
		if index := params.findFieldIndex(fi.field.Type, fi.name, fi.index); len(index) > 0 {
			return index
		}
	}
	return nil
}
Пример #7
0
// Bind binds form values of fieldNames to obj.
// obj must be a pointer of struct. If obj isn't a pointer of struct, it returns error.
// Note that it in the case of errors due to a form value binding error, no error is returned.
// Binding errors will set to map of returned from Controller.Errors().
func (params *Params) Bind(obj interface{}, fieldNames ...string) error {
	rvalue := reflect.ValueOf(obj)
	if rvalue.Kind() != reflect.Ptr {
		return fmt.Errorf("kocha: Bind: first argument must be a pointer, but %v", rvalue.Type().Kind())
	}
	for rvalue.Kind() == reflect.Ptr {
		rvalue = rvalue.Elem()
	}
	if rvalue.Kind() != reflect.Struct {
		return fmt.Errorf("kocha: Bind: first argument must be a pointer of struct, but %T", obj)
	}
	rtype := rvalue.Type()
	for _, name := range fieldNames {
		index := params.findFieldIndex(rtype, name, nil)
		if len(index) < 1 {
			_, filename, line, _ := runtime.Caller(1)
			params.c.App.Logger.Warnf(
				"kocha: Bind: %s:%s: field name `%s' given, but %s.%s is undefined",
				filepath.Base(filename), line, name, rtype.Name(), util.ToCamelCase(name))
			continue
		}
		fname := params.prefixedName(params.prefix, name)
		values, found := params.Values[fname]
		if !found {
			continue
		}
		field := rvalue.FieldByIndex(index)
		for field.Kind() == reflect.Ptr {
			field = field.Elem()
		}
		value, err := params.parse(field.Interface(), values[0])
		if err != nil {
			params.c.Errors[name] = append(params.c.Errors[name], NewParamError(name, err))
		}
		field.Set(reflect.ValueOf(value))
	}
	return nil
}