@@ -5,11 +5,12 @@ class JsonapiCompliable::Util::Persistence
55 # @param [Hash] meta see (Deserializer#meta)
66 # @param [Hash] attributes see (Deserializer#attributes)
77 # @param [Hash] relationships see (Deserializer#relationships)
8- def initialize ( resource , meta , attributes , relationships )
8+ def initialize ( resource , meta , attributes , relationships , caller_model )
99 @resource = resource
1010 @meta = meta
1111 @attributes = attributes
1212 @relationships = relationships
13+ @caller_model = caller_model
1314 end
1415
1516 # Perform the actual save logic.
@@ -37,7 +38,7 @@ def run
3738 assign_temp_id ( persisted , @meta [ :temp_id ] )
3839 associate_parents ( persisted , parents )
3940
40- children = process_has_many ( @relationships ) do |x |
41+ children = process_has_many ( @relationships , persisted ) do |x |
4142 update_foreign_key ( persisted , x [ :attributes ] , x )
4243 end
4344
@@ -49,7 +50,11 @@ def run
4950
5051 # The child's attributes should be modified to nil-out the
5152 # 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
5255 def update_foreign_key ( parent_object , attrs , x )
56+ return if x [ :sideload ] . type == :habtm
57+
5358 if [ :destroy , :disassociate ] . include? ( x [ :meta ] [ :method ] )
5459 attrs [ x [ :foreign_key ] ] = nil
5560 update_foreign_type ( attrs , x , null : true ) if x [ :is_polymorphic ]
@@ -72,33 +77,45 @@ def update_foreign_key_for_parents(parents)
7277
7378 def associate_parents ( object , parents )
7479 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
7687 end
7788 end
7889
7990 def associate_children ( object , children )
8091 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
8299 end
83100 end
84101
85102 def persist_object ( method , attributes )
86103 case method
87104 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 )
91108 else
92- @resource . send ( method , attributes )
109+ call_resource_method ( :create , attributes , @caller_model )
93110 end
94111 end
95112
96- def process_has_many ( relationships )
113+ def process_has_many ( relationships , caller_model )
97114 [ ] . tap do |processed |
98115 iterate ( except : [ :polymorphic_belongs_to , :belongs_to ] ) do |x |
99116 yield x
100117 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 )
102119 processed << x
103120 end
104121 end
@@ -128,4 +145,23 @@ def iterate(only: [], except: [])
128145 yield x
129146 end
130147 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
131167end
0 commit comments