On Thursday, December 13, 2018 at 1:34:00 PM UTC-8, Ben Alavi wrote:
>
> Actually... do you know why the reciprocal object isn't just replaced
> *before* calling the setter?
>
> This works for my example and passes specs:
>
> remove_reciprocal_object(opts, a) if a
> add_reciprocal_object(opts, o) if o
> # Allow calling private _setter method
> send(opts[:_setter_method], o)
>
This would break symmetry with how the association caches are modified in
all other cases. Modifying the associations cache to set the new value
happens after the related add/remove code is run, and reciprocal
modifications happen after that. In the code posted, the associations
cache for the current object is modified after calling the _setter_method.
Other cases follow a similar pattern. add_associated_object runs the
add_method, then modifies the current association cache, then modifies the
reciprocal. remove_associated_object runs the remove_method, the modifies
the current associations cache, then modifies the reciprocal. Now, that
isn't a reason to reject this approach outright, but there would need to be
a compelling reason to make such a change.
In the general case (when nested attributes is not used), at the point the
save method is called on the associated object (o), the associated object
in o (the reciprocal) wouldn't match the current database value, which
would result in different behavior than in most other cases where at the
point the save method is called, the association object matches the
database value. While no specs currently fail with the change described, I
expect it may cause issues in some applications that rely on the current
order of operations.
Contrived Example:
DB.create_table(:nodes) do
primary_key :id
Integer :parent_id
end
class Node < Sequel::Model
many_to_one :parent, :class=>self
one_to_one :child, :key=>:parent_id, :class=>self
# Check existing parent to ensure new value is greater
def parent_id=(v)
if parent
raise "bad parent" unless v > parent.id
end
super
end
end
Node.import([:id], [[1], [2], [3]])
x = Node[1]
y = Node[2]
z = Node[3]
y.parent = x
y.parent = z
x = Node[1]
y = Node[2]
z = Node[3]
x.child = y
z.child = y
Thanks,
Jeremy
--
You received this message because you are subscribed to the Google Groups
"sequel-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sequel-talk.
For more options, visit https://groups.google.com/d/optout.