core/rails/app/controllers/application_controller.rb
# Given an object and list of permitted object attributes to update, extract the
# JSON patch that should be in the request body, apply it to the object cast as a
# JSON blob, and update the permitted attribs of the actual object.
# If the patch fails to apply, or if the patch tries to update an attribute not in
# the permitted list, fail.
#
# This method MUST be called within a transaction, and obj MUST be locked in order
# to guarantee that the requested changes happen atomically.
#
# This is REALLY BAD and MUST stop.  We have objects in the model that
# have derived values with the same named attribute in the database.  The
# values are DIFFERENT!!!  This breaks all patch operations. I'm looking
# at you Deployment.state.  IT IS BUSTED.  To avoid, changing the models to fix
# the issue everywhere we do this, I'm adding noset_attribs to force patch
# to never set them.
#
Given an object and list of permitted object attributes to update, extract the
JSON patch that should be in the request body, apply it to the object cast as a
JSON blob, and update the permitted attribs of the actual object.
If the patch fails to apply, or if the patch tries to update an attribute not in
the permitted list, fail.

This method MUST be called within a transaction, and obj MUST be locked in order
to guarantee that the requested changes happen atomically.

This is REALLY BAD and MUST stop.  We have objects in the model that
have derived values with the same named attribute in the database.  The
values are DIFFERENT!!.  This breaks all patch operations. I'm looking
at you Deployment.state.  IT IS BUSTED.  To avoid, changing the models to fix
the issue everywhere we do this, I'm adding noset_attribs to force patch
to never set them.
Given an object and list of permitted object attributes to update extract the JSON patch that should be in the request body apply it to the object cast as a JSON blob and update the permitted attribs of the actual object . If the patch fails to apply or if the patch tries to update an attribute not in the permitted list fail . This method MUST be called within a transaction and obj MUST be locked in order to guarantee that the requested changes happen atomically . This is REALLY BAD and MUST stop . We have objects in the model that have derived values with the same named attribute in the database . The values are DIFFERENT!! . This breaks all patch operations . I ' m looking at you Deployment . state . IT IS BUSTED . To avoid changing the models to fix the issue everywhere we do this I ' m adding noset_attribs to force patch to never set them .
def patch(obj, permitted_attribs, noset_attribs = [])
    patch = JSON.parse(request.raw_post)
    Rails.logger.debug(obj.as_json)
    Rails.logger.debug(request.raw_post)
    raise "Patch not formatted properly" unless patch.is_a?(Array)
    res = JSON::Patch.new(obj.as_json,patch).call
    res.keys.each do |k|
      next unless obj.has_attribute?(k)
      next if noset_attribs.member?(k)
      next if obj[k] == res[k]
      if permitted_attribs.member?(k)
        obj[k] = res[k]
      else
        raise "Cannot update attribute #{k} for #{obj.class.name}"
      end
    end
    obj.save!
  end
def patch ( obj , permitted_attribs , noset_attribs = [ ] ) patch = JSON . parse ( request . raw_post ) Rails . logger . debug ( obj . as_json ) Rails . logger . debug ( request . raw_post ) raise "Patch not formatted properly" unless patch . is_a? ( Array ) res = JSON :: Patch . new ( obj . as_json , patch ) . call res . keys . each do | k | next unless obj . has_attribute? ( k ) next if noset_attribs . member? ( k ) next if obj [ k ] == res [ k ] if permitted_attribs . member? ( k ) obj [ k ] = res [ k ] else raise "Cannot update attribute #{k} for #{obj.class.name}" end end obj . save! end
Given an object and list of permitted object attributes to update, extract the
JSON patch that should be in the request body, apply it to the object cast as a
JSON blob, and update the permitted attribs of the actual object.
Given an object and list of permitted object attributes to update extract the JSON patch that should be in the request body apply it to the object cast as a JSON blob and update the permitted attribs of the actual object .
# Now, sanity-check res to make sure it only updated the keys we wanted it to # Ignore synthetic keys # Skip noset attribs because STUPID! # Nothing changed, OK.
obj
<not_specific>
permitted_attribs
<not_specific>
noset_attribs
<not_specific>