/
fkmode.go
104 lines (88 loc) · 2.59 KB
/
fkmode.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package internal
import (
"errors"
"strings"
"github.com/kenshaw/snaker"
)
// FkMode represents the different foreign key naming modes.
type FkMode int
const (
// FkModeSmart is the default FkMode.
//
// When there are no naming conflicts, FkModeSmart behaves the same
// FkModeParent, otherwise it behaves the same as FkModeField.
FkModeSmart FkMode = iota
// FkModeParent causes a foreign key field to be named in the form of
// "<type>.<ParentName>".
//
// For example, if you have an `authors` and `books` tables, then the
// foreign key func will be Book.Author.
FkModeParent
// FkModeField causes a foreign key field to be named in the form of
// "<type>.<ParentName>By<Field>".
//
// For example, if you have an `authors` and `books` tables, then the
// foreign key func will be Book.AuthorByAuthorID.
FkModeField
// FkModeKey causes a foreign key field to be named in the form of
// "<type>.<ParentName>By<ForeignKeyName>".
//
// For example, if you have an `authors` and `books` tables with a foreign
// key name of 'fk_123', then the foreign key func will be
// Book.AuthorByFk123.
FkModeKey
)
// UnmarshalText unmarshals FkMode from text.
func (f *FkMode) UnmarshalText(text []byte) error {
switch strings.ToLower(string(text)) {
case "smart", "default":
*f = FkModeSmart
case "parent":
*f = FkModeParent
case "field":
*f = FkModeField
case "key":
*f = FkModeKey
default:
return errors.New("invalid FkMode")
}
return nil
}
// String satisfies the Stringer interface.
func (f FkMode) String() string {
switch f {
case FkModeSmart:
return "smart"
case FkModeParent:
return "parent"
case FkModeField:
return "field"
case FkModeKey:
return "key"
}
return "unknown"
}
// fkName returns the name for the foreign key.
func fkName(mode FkMode, fkMap map[string]*ForeignKey, fk *ForeignKey) string {
switch mode {
case FkModeParent:
return fk.RefType.Name
case FkModeField:
return fk.RefType.Name + "By" + fk.Field.Name
case FkModeKey:
return fk.RefType.Name + "By" + snaker.SnakeToCamelIdentifier(fk.ForeignKey.ForeignKeyName)
}
// mode is FkModeSmart
// inspect all foreign keys and use FkModeField if conflict found
for _, f := range fkMap {
if fk != f && fk.Type.Name == f.Type.Name && fk.RefType.Name == f.RefType.Name {
return fkName(FkModeField, fkMap, fk)
}
}
// no conflict, so use FkModeParent
return fkName(FkModeParent, fkMap, fk)
}
// ForeignKeyName returns the foreign key name for the passed type.
func (a *ArgType) ForeignKeyName(fkMap map[string]*ForeignKey, fk *ForeignKey) string {
return fkName(*a.ForeignKeyMode, fkMap, fk)
}