forked from gobuffalo/pop
-
Notifications
You must be signed in to change notification settings - Fork 0
/
model.go
124 lines (108 loc) · 2.72 KB
/
model.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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package pop
import (
"fmt"
"reflect"
"time"
"github.com/markbates/inflect"
)
var tableMap = map[string]string{}
// MapTableName allows for the customize table mapping
// between a name and the database. For example the value
// `User{}` will automatically map to "users".
// MapTableName would allow this to change.
//
// m := &pop.Model{Value: User{}}
// m.TableName() // "users"
//
// pop.MapTableName("user", "people")
// m = &pop.Model{Value: User{}}
// m.TableName() // "people"
func MapTableName(name string, tableName string) {
tableMap[name] = tableName
}
type Value interface{}
// Model is used throughout Pop to wrap the end user interface
// that is passed in to many functions.
type Model struct {
Value
tableName string
}
// func (m *Model) Validate(*Connection) (*validate.Errors, error) {
// return validate.NewErrors(), nil
// }
//
// func (m *Model) ValidateNew(*Connection) (*validate.Errors, error) {
// return validate.NewErrors(), nil
// }
//
// func (m *Model) ValidateUpdate(*Connection) (*validate.Errors, error) {
// return validate.NewErrors(), nil
// }
// ID returns the ID of the Model. All models must have an `ID` field this is
// of type `int`.
func (m *Model) ID() int {
fbn, err := m.fieldByName("ID")
if err != nil {
return 0
}
return int(fbn.Int())
}
// TableName returns the corresponding name of the underlying database table
// for a given `Model`. See also `MapTableName` to change the default name of
// the table.
func (m *Model) TableName() string {
if m.tableName != "" {
return m.tableName
}
t := reflect.TypeOf(m.Value)
name := m.typeName(t)
if tableMap[name] == "" {
m.tableName = inflect.Tableize(name)
tableMap[name] = m.tableName
}
return tableMap[name]
}
func (m *Model) typeName(t reflect.Type) string {
kind := t.Kind().String()
switch kind {
case "ptr":
st := reflect.ValueOf(m.Value).Elem()
return m.typeName(st.Type())
case "string":
return m.Value.(string)
case "slice":
return t.Elem().Name()
default:
return t.Name()
}
}
func (m *Model) fieldByName(s string) (reflect.Value, error) {
el := reflect.ValueOf(m.Value).Elem()
fbn := el.FieldByName(s)
if !fbn.IsValid() {
return fbn, fmt.Errorf("Model does not have a field named %s", s)
}
return fbn, nil
}
func (m *Model) associationName() string {
tn := inflect.Singularize(m.TableName())
return fmt.Sprintf("%s_id", tn)
}
func (m *Model) setID(i int) {
fbn, err := m.fieldByName("ID")
if err == nil {
fbn.SetInt(int64(i))
}
}
func (m *Model) touchCreatedAt() {
fbn, err := m.fieldByName("CreatedAt")
if err == nil {
fbn.Set(reflect.ValueOf(time.Now()))
}
}
func (m *Model) touchUpdatedAt() {
fbn, err := m.fieldByName("UpdatedAt")
if err == nil {
fbn.Set(reflect.ValueOf(time.Now()))
}
}