@@ -3,8 +3,10 @@ package changeset
33
44import (
55 "reflect"
6+ "time"
67
78 "github.com/Fs02/changeset/params"
9+ "github.com/Fs02/rel"
810)
911
1012// Changeset used to cast and validate data before saving it to the database.
@@ -19,48 +21,119 @@ type Changeset struct {
1921}
2022
2123// Errors of changeset.
22- func (changeset * Changeset ) Errors () []error {
23- return changeset .errors
24+ func (c Changeset ) Errors () []error {
25+ return c .errors
2426}
2527
2628// Error of changeset, returns the first error if any.
27- func (changeset * Changeset ) Error () error {
28- if changeset .errors != nil {
29- return changeset .errors [0 ]
29+ func (c Changeset ) Error () error {
30+ if c .errors != nil {
31+ return c .errors [0 ]
3032 }
33+
3134 return nil
3235}
3336
3437// Get a change from changeset.
35- func (changeset * Changeset ) Get (field string ) interface {} {
36- return changeset .changes [field ]
38+ func (c Changeset ) Get (field string ) interface {} {
39+ return c .changes [field ]
3740}
3841
3942// Fetch a change or value from changeset.
40- func (changeset * Changeset ) Fetch (field string ) interface {} {
41- if change , ok := changeset .changes [field ]; ok {
43+ func (c Changeset ) Fetch (field string ) interface {} {
44+ if change , ok := c .changes [field ]; ok {
4245 return change
4346 }
4447
45- return changeset .values [field ]
48+ return c .values [field ]
4649}
4750
4851// Changes of changeset.
49- func (changeset * Changeset ) Changes () map [string ]interface {} {
50- return changeset .changes
52+ func (c Changeset ) Changes () map [string ]interface {} {
53+ return c .changes
5154}
5255
5356// Values of changeset.
54- func (changeset * Changeset ) Values () map [string ]interface {} {
55- return changeset .values
57+ func (c Changeset ) Values () map [string ]interface {} {
58+ return c .values
5659}
5760
5861// Types of changeset.
59- func (changeset * Changeset ) Types () map [string ]reflect.Type {
60- return changeset .types
62+ func (c Changeset ) Types () map [string ]reflect.Type {
63+ return c .types
6164}
6265
6366// Constraints of changeset.
64- func (changeset * Changeset ) Constraints () Constraints {
65- return changeset .constraints
67+ func (c Changeset ) Constraints () Constraints {
68+ return c .constraints
69+ }
70+
71+ // Apply mutation.
72+ func (c * Changeset ) Apply (doc * rel.Document , mut * rel.Mutation ) {
73+ var (
74+ pField = doc .PrimaryField ()
75+ now = time .Now ().Truncate (time .Second )
76+ )
77+
78+ for field , value := range c .changes {
79+ switch v := value .(type ) {
80+ case * Changeset :
81+ if mut .Cascade {
82+ c .applyAssocOne (doc , field , mut , v )
83+ }
84+ case []* Changeset :
85+ if mut .Cascade {
86+ c .applyAssocMany (doc , field , mut , v )
87+ }
88+ default :
89+ if field != pField {
90+ c .set (doc , mut , field , v )
91+ }
92+ }
93+ }
94+
95+ // insert timestamp
96+ if doc .Flag (rel .HasCreatedAt ) {
97+ if value , ok := doc .Value ("created_at" ); ok && value .(time.Time ).IsZero () {
98+ c .set (doc , mut , "created_at" , now )
99+ }
100+ }
101+
102+ // update timestamp
103+ if doc .Flag (rel .HasUpdatedAt ) {
104+ c .set (doc , mut , "updated_at" , now )
105+ }
106+ }
107+
108+ func (c * Changeset ) set (doc * rel.Document , mut * rel.Mutation , field string , value interface {}) {
109+ if doc .SetValue (field , value ) {
110+ mut .Add (rel .Set (field , value ))
111+ }
112+ }
113+
114+ func (c * Changeset ) applyAssocOne (doc * rel.Document , field string , mut * rel.Mutation , ch * Changeset ) {
115+ var (
116+ assoc = doc .Association (field )
117+ assocDoc , _ = assoc .Document ()
118+ assocMut = rel .Apply (assocDoc , ch )
119+ )
120+
121+ mut .SetAssoc (field , assocMut )
122+ }
123+
124+ func (c * Changeset ) applyAssocMany (doc * rel.Document , field string , mut * rel.Mutation , chs []* Changeset ) {
125+ var (
126+ assoc = doc .Association (field )
127+ col , _ = assoc .Collection ()
128+ muts = make ([]rel.Mutation , len (chs ))
129+ )
130+
131+ // Reset assoc.
132+ col .Reset ()
133+
134+ for i := range chs {
135+ muts [i ] = rel .Apply (col .Add (), chs [i ])
136+ }
137+
138+ mut .SetAssoc (field , muts ... )
66139}
0 commit comments