@@ -5,11 +5,12 @@ class JsonapiCompliable::Util::Persistence
5
5
# @param [Hash] meta see (Deserializer#meta)
6
6
# @param [Hash] attributes see (Deserializer#attributes)
7
7
# @param [Hash] relationships see (Deserializer#relationships)
8
- def initialize ( resource , meta , attributes , relationships )
8
+ def initialize ( resource , meta , attributes , relationships , caller_model )
9
9
@resource = resource
10
10
@meta = meta
11
11
@attributes = attributes
12
12
@relationships = relationships
13
+ @caller_model = caller_model
13
14
end
14
15
15
16
# Perform the actual save logic.
@@ -37,7 +38,7 @@ def run
37
38
assign_temp_id ( persisted , @meta [ :temp_id ] )
38
39
associate_parents ( persisted , parents )
39
40
40
- children = process_has_many ( @relationships ) do |x |
41
+ children = process_has_many ( @relationships , persisted ) do |x |
41
42
update_foreign_key ( persisted , x [ :attributes ] , x )
42
43
end
43
44
@@ -49,7 +50,11 @@ def run
49
50
50
51
# The child's attributes should be modified to nil-out the
51
52
# foreign_key when the parent is being destroyed or disassociated
53
+ #
54
+ # This is not the case for HABTM, whose "foreign key" is a join table
52
55
def update_foreign_key ( parent_object , attrs , x )
56
+ return if x [ :sideload ] . type == :habtm
57
+
53
58
if [ :destroy , :disassociate ] . include? ( x [ :meta ] [ :method ] )
54
59
attrs [ x [ :foreign_key ] ] = nil
55
60
update_foreign_type ( attrs , x , null : true ) if x [ :is_polymorphic ]
@@ -72,33 +77,45 @@ def update_foreign_key_for_parents(parents)
72
77
73
78
def associate_parents ( object , parents )
74
79
parents . each do |x |
75
- x [ :sideload ] . associate ( x [ :object ] , object ) if x [ :object ] && object
80
+ if x [ :object ] && object
81
+ if x [ :meta ] [ :method ] == :disassociate
82
+ x [ :sideload ] . disassociate ( x [ :object ] , object )
83
+ else
84
+ x [ :sideload ] . associate ( x [ :object ] , object )
85
+ end
86
+ end
76
87
end
77
88
end
78
89
79
90
def associate_children ( object , children )
80
91
children . each do |x |
81
- x [ :sideload ] . associate ( object , x [ :object ] ) if x [ :object ] && object
92
+ if x [ :object ] && object
93
+ if x [ :meta ] [ :method ] == :disassociate
94
+ x [ :sideload ] . disassociate ( object , x [ :object ] )
95
+ else
96
+ x [ :sideload ] . associate ( object , x [ :object ] )
97
+ end
98
+ end
82
99
end
83
100
end
84
101
85
102
def persist_object ( method , attributes )
86
103
case method
87
104
when :destroy
88
- @resource . destroy ( attributes [ :id ] )
89
- when :disassociate , nil
90
- @resource . update ( attributes )
105
+ call_resource_method ( :destroy , attributes [ :id ] , @caller_model )
106
+ when :update , nil , :disassociate
107
+ call_resource_method ( :update , attributes , @caller_model )
91
108
else
92
- @resource . send ( method , attributes )
109
+ call_resource_method ( :create , attributes , @caller_model )
93
110
end
94
111
end
95
112
96
- def process_has_many ( relationships )
113
+ def process_has_many ( relationships , caller_model )
97
114
[ ] . tap do |processed |
98
115
iterate ( except : [ :polymorphic_belongs_to , :belongs_to ] ) do |x |
99
116
yield x
100
117
x [ :object ] = x [ :sideload ] . resource
101
- . persist_with_relationships ( x [ :meta ] , x [ :attributes ] , x [ :relationships ] )
118
+ . persist_with_relationships ( x [ :meta ] , x [ :attributes ] , x [ :relationships ] , caller_model )
102
119
processed << x
103
120
end
104
121
end
@@ -128,4 +145,23 @@ def iterate(only: [], except: [])
128
145
yield x
129
146
end
130
147
end
148
+
149
+ # In the Resource, we want to allow:
150
+ #
151
+ # def create(attrs)
152
+ #
153
+ # and
154
+ #
155
+ # def create(attrs, parent = nil)
156
+ #
157
+ # 'parent' is an optional parameter that should not be part of the
158
+ # method signature in most use cases.
159
+ def call_resource_method ( method_name , attributes , caller_model )
160
+ method = @resource . method ( method_name )
161
+ if [ 2 , -2 ] . include? ( method . arity )
162
+ method . call ( attributes , caller_model )
163
+ else
164
+ method . call ( attributes )
165
+ end
166
+ end
131
167
end
0 commit comments