-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix missing nil
attributes in SObject.update
#79
Conversation
def prepare_for_update(id, attributes) | ||
new(attributes.merge(id: id)).tap do |obj| | ||
attributes.each do |name, value| | ||
obj.public_send("#{name}_will_change!") if value.nil? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this could be generalized to:
obj.public_send("#{name}_will_change!") unless object.public_send("#{name}_changed?")
in case there are other reasons that an attribute would be "unchanged". But this is more confusing and I think we should avoid those changed?
calls if not really needed.
@@ -34,8 +34,24 @@ class << self | |||
def_delegators :query, :not, :or, :where, :first, :last, :all, :find, :find!, :find_by, :find_by!, :sum, :count, :includes, :limit, :order, :select, :none | |||
def_delegators :mapping, :table, :table_name, :custom_table?, :mappings | |||
|
|||
def update(id, attributes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved these up here so I could easily create a shared private class method (viz., prepare_for_update
) and have them close together.
It's confusing that we have a class << self
block and also a bunch of class methods defined outside of it with def self.method
declarations. Might be better to migrate those into this block at some point.
@rferg Please update the |
Thank you! |
Previously, calling
SObject.update(id, a: nil)
orSObject.update!(id, a: nil)
would omit'A' => nil
from the Restforce request. Consequently, the field would not be updated toNULL
in Salesforce, despite the clear intention of the caller to do that.This is because
.update
creates an instance, passing in the given attributes, and then calls#update
on it. That method only includes changed attributes in the request. And since a new instance's attribute isnil
by default, setting it tonil
does not register it as changed.This PR fixes this by forcing any attributes given to
SObject.update
orSObject.update!
withnil
values to register a change on the model by using theActiveModel::Dirty#*_will_change!
method.