class Tilia::Dav::PropPatch
This class represents a set of properties that are going to be updated.
Usually this is simply a PROPPATCH request, but it can also be used for internal updates.
Property updates must always be atomic. This means that a property update must either completely succeed, or completely fail.
Attributes
This property will be set to true if the operation failed.
@var bool
Properties that are being updated.
This is a key-value list. If the value is null, the property is supposed to be deleted.
@var array
This is the list of callbacks when we're performing the actual update.
@var array
A list of properties and the result of the update. The result is in the form of a HTTP status code.
@var array
Public Class Methods
Constructor
@param array mutations A list of updates
# File lib/tilia/dav/prop_patch.rb, line 38 def initialize(mutations) self.mutations = mutations self.result = {} self.failed = false self.property_update_callbacks = [] end
Public Instance Methods
Performs the actual update, and calls all callbacks.
This method returns true or false depending on if the operation was successful.
@return bool
# File lib/tilia/dav/prop_patch.rb, line 164 def commit # First we validate if every property has a handler mutations.keys.each do |property_name| unless result.key? property_name self.failed = true result[property_name] = 403 end end property_update_callbacks.each do |callbackInfo| break if failed if callbackInfo[0].is_a? String do_callback_single_prop(callbackInfo[0], callbackInfo[1]) else do_callback_multi_prop(callbackInfo[0], callbackInfo[1]) end end # If anywhere in this operation updating a property failed, we must # update all other properties accordingly. if failed result.each do |property_name, status| if status == 202 # Failed dependency result[property_name] = 424 end end end !failed end
Call this function if you wish to handle updating certain properties. For instance, your class may be responsible for handling updates for the {DAV:}displayname property.
In that case, call this method with the first argument “{DAV:}displayname” and a second argument that's a method that does the actual updating.
It's possible to specify more than one property as an array.
The callback must return a boolean or an it. If the result is true, the operation was considered successful. If it's false, it's consided failed.
If the result is an integer, we'll use that integer as the http status code associated with the operation.
@param string|string[] properties @param callable callback @return void
# File lib/tilia/dav/prop_patch.rb, line 65 def handle(properties, callback) used_properties = [] [properties].flatten.each do |property_name| next unless mutations.key?(property_name) && !result.key?(property_name) used_properties << property_name # HTTP Accepted result[property_name] = 202 end # Only registering if there's any unhandled properties. return nil unless used_properties.any? property_update_callbacks << [ # If the original argument to this method was a string, we need # to also make sure that it stays that way, so the commit function # knows how to format the arguments to the callback. properties.is_a?(String) ? properties : used_properties, callback] end
Call this function if you wish to handle all properties that haven't been handled by anything else yet. Note that you effectively claim with this that you promise to process all properties that are coming in.
@param callable callback @return void
# File lib/tilia/dav/prop_patch.rb, line 91 def handle_remaining(callback) properties = remaining_mutations unless properties.any? # Nothing to do, don't register callback return end properties.each do |property_name| # HTTP Accepted result[property_name] = 202 property_update_callbacks << [ properties, callback] end end
Returns the list of properties that don't have a result code yet.
This method returns a list of property names, but not its values.
@return string[]
# File lib/tilia/dav/prop_patch.rb, line 137 def remaining_mutations remaining = [] mutations.keys.each do |property_name| remaining << property_name unless result.key? property_name end remaining end
Sets the result code for all properties that did not have a result yet.
@param int result_code @return void
# File lib/tilia/dav/prop_patch.rb, line 125 def remaining_result_code=(result_code) update_result_code( remaining_mutations, result_code ) end
Returns the list of properties that don't have a result code yet.
This method returns list of properties and their values.
@return array
# File lib/tilia/dav/prop_patch.rb, line 150 def remaining_values remaining = {} mutations.each do |property_name, prop_value| remaining[property_name] = prop_value unless result.key? property_name end remaining end
Sets the result code for one or more properties.
@param string|string[] properties @param int result_code @return void
# File lib/tilia/dav/prop_patch.rb, line 113 def update_result_code(properties, result_code) [properties].flatten.each do |property_name| result[property_name] = result_code end self.failed = true if result_code >= 400 end
Private Instance Methods
Executes a property callback with the multi-property syntax.
@param array property_list @param callable callback @return void
# File lib/tilia/dav/prop_patch.rb, line 242 def do_callback_multi_prop(property_list, callback) argument = {} property_list.each do |property_name| argument[property_name] = mutations[property_name] end result = callback.call(argument) if result.is_a? Hash property_list.each do |property_name| unless result.key? property_name result_code = 500 else result_code = result[property_name] end self.failed = true if result_code >= 400 self.result[property_name] = result_code end elsif result == true # Success argument.each do |property_name, property_value| self.result[property_name] = property_value.nil? ? 204 : 200 end elsif result == false # Fail :( self.failed = true property_list.each do |property_name| self.result[property_name] = 403 end else fail 'A callback sent to handle() did not return an array or a bool' end end
Executes a property callback with the single-property syntax.
@param string property_name @param callable callback @return void
# File lib/tilia/dav/prop_patch.rb, line 213 def do_callback_single_prop(property_name, callback) result = callback.call(mutations[property_name]) if result.is_a?(TrueClass) || result.is_a?(FalseClass) if result if mutations[property_name].nil? # Delete result = 204 else # Update result = 200 end else # Fail result = 403 end end unless result.is_a? Fixnum fail 'A callback sent to handle() did not return an int or a bool' end self.result[property_name] = result self.failed = true if result >= 400 end