lib/survey_gizmo/resource.rb in survey-gizmo-ruby-3.0.3 vs lib/survey_gizmo/resource.rb in survey-gizmo-ruby-4.0.0
- old
+ new
@@ -14,189 +14,142 @@
# @return [Set] Every class that includes SurveyGizmo::Resource
def self.descendants
@descendants ||= Set.new
end
- # These are methods that every API resource has to access resources
- # in Survey Gizmo
+ # These are methods that every API resource can use to access resources in SurveyGizmo
module ClassMethods
-
- # Convert a [Hash] of filters into a query string
- # @param [Hash] filters - simple pagination or other options at the top level, and surveygizmo "filters" at the :filters key
- # @return [String]
- #
- # example input: { page: 2, filters: [{:field=>"istestdata", :operator=>"<>", :value=>1}] }
- #
- # The top level keys (e.g. page, resultsperpage) get simply encoded in the url, while the
- # contents of the array of hashes passed at filters[:filters] gets turned into the format
- # SurveyGizmo expects for its internal filtering, for example:
- #
- # filter[field][0]=istestdata&filter[operator][0]=<>&filter[value][0]=1
- def convert_filters_into_query_string(filters = nil)
- return '' unless filters && filters.size > 0
-
- output_filters = filters[:filters] || []
- filter_hash = {}
- output_filters.each_with_index do |filter,i|
- filter_hash.merge!(
- "filter[field][#{i}]".to_sym => "#{filter[:field]}",
- "filter[operator][#{i}]".to_sym => "#{filter[:operator]}",
- "filter[value][#{i}]".to_sym => "#{filter[:value]}",
- )
- end
- simple_filters = filters.reject { |k,v| k == :filters }
- filter_hash.merge!(simple_filters)
-
- uri = Addressable::URI.new
- uri.query_values = filter_hash
- "?#{uri.query}"
- end
-
- # Get a list of resources
- # @param [Hash] conditions
- # @param [Hash] filters
- # @return [Array] of objects of this class
+ # Get an array of resources
def all(conditions = {}, filters = nil)
response = RestResponse.new(SurveyGizmo.get(handle_route(:create, conditions) + convert_filters_into_query_string(filters)))
- if response.ok?
- _collection = response.data.map { |datum| datum.is_a?(Hash) ? self.new(datum) : datum }
+ _collection = response.data.map { |datum| datum.is_a?(Hash) ? self.new(datum) : datum }
- # Add in the properties from the conditions hash because many of the important ones (like survey_id) are
- # not often part of the SurveyGizmo returned data
- conditions.keys.each do |k|
- if conditions[k] && instance_methods.include?(k)
- _collection.each { |c| c[k] ||= conditions[k] }
- end
+ # Add in the properties from the conditions hash because many of the important ones (like survey_id) are
+ # not often part of the SurveyGizmo returned data
+ conditions.keys.each do |k|
+ if conditions[k] && instance_methods.include?(k)
+ _collection.each { |c| c[k] ||= conditions[k] }
end
+ end
- # Sub questions are not pulled by default so we have to retrieve them
- if self == SurveyGizmo::API::Question
- _collection += _collection.map { |question| question.sub_questions }.flatten
- end
-
- _collection
- else
- []
+ # Sub questions are not pulled by default so we have to retrieve them manually
+ # SurveyGizmo claims they will fix this bug and eventually all questions will be
+ # returned in one request.
+ if self == SurveyGizmo::API::Question
+ _collection += _collection.map { |question| question.sub_questions }.flatten
end
+
+ _collection
end
- # Get the first resource
- # @param [Hash] conditions
- # @param [Hash] filters
- # @return [Object, nil]
+ # Retrieve a single resource.
def first(conditions = {}, filters = nil)
response = RestResponse.new(SurveyGizmo.get(handle_route(:get, conditions) + convert_filters_into_query_string(filters)))
# Add in the properties from the conditions hash because many of the important ones (like survey_id) are
# not often part of the SurveyGizmo's returned data
- response.ok? ? new(conditions.merge(response.data)) : nil
+ new(conditions.merge(response.data))
end
- # Create a new resource
- # @param [Hash] attributes
- # @return [Resource]
- # The newly created Resource instance
+ # Create a new resource. Returns the newly created Resource instance.
def create(attributes = {})
resource = new(attributes)
resource.create_record_in_surveygizmo
resource
end
- # Copy a resource
- # @param [Integer] id
- # @param [Hash] attributes
- # @return [Resource]
- # The newly created resource instance
- def copy(attributes = {})
- attributes[:copy] = true
- resource = new(attributes)
- resource.__send__(:_copy)
- resource
- end
-
- # Deleted the Resource from Survey Gizmo
- # @param [Hash] conditions
- # @return [Boolean]
+ # Delete resources
def destroy(conditions)
- RestResponse.new(SurveyGizmo.delete(handle_route(:delete, conditions))).ok?
+ RestResponse.new(SurveyGizmo.delete(handle_route(:delete, conditions)))
end
# Define the path where a resource is located
- # @param [String] path
- # the path in Survey Gizmo for the resource
- # @param [Hash] options
- # @option options [Array] :via
- # which is `:get`, `:create`, `:update`, `:delete`, or `:any`
- # @scope class
def route(path, options)
methods = options[:via]
methods = [:get, :create, :update, :delete] if methods == :any
methods.is_a?(Array) ? methods.each { |m| @paths[m] = path } : (@paths[methods] = path)
end
# This method replaces the :page_id, :survey_id, etc strings defined in each model's URI routes with the
# values being passed in interpolation hash with the same keys.
- # @api private
def handle_route(key, interpolation_hash)
path = @paths[key]
- raise "No routes defined for `#{key}` in #{self.name}" unless path
- raise "User/password hash not setup!" if SurveyGizmo.default_params.empty?
+ fail "No routes defined for `#{key}` in #{self.name}" unless path
+ fail "User/password hash not setup!" if SurveyGizmo.default_params.empty?
path.gsub(/:(\w+)/) do |m|
raise(SurveyGizmo::URLError, "Missing RESTful parameters in request: `#{m}`") unless interpolation_hash[$1.to_sym]
interpolation_hash[$1.to_sym]
end
end
+
+ # Convert a [Hash] of filters into a query string
+ # @param [Hash] filters - simple pagination or other options at the top level, and surveygizmo "filters" at the :filters key
+ # @return [String]
+ #
+ # example input: { page: 2, filters: [{:field=>"istestdata", :operator=>"<>", :value=>1}] }
+ #
+ # The top level keys (e.g. page, resultsperpage) get simply encoded in the url, while the
+ # contents of the array of hashes passed in the filters hash get turned into the format
+ # SurveyGizmo expects for its internal filtering, for example:
+ #
+ # filter[field][0]=istestdata&filter[operator][0]=<>&filter[value][0]=1
+ def convert_filters_into_query_string(filters = nil)
+ return '' unless filters && filters.size > 0
+
+ output_filters = filters[:filters] || []
+ filter_hash = {}
+ output_filters.each_with_index do |filter,i|
+ filter_hash.merge!(
+ "filter[field][#{i}]".to_sym => "#{filter[:field]}",
+ "filter[operator][#{i}]".to_sym => "#{filter[:operator]}",
+ "filter[value][#{i}]".to_sym => "#{filter[:value]}",
+ )
+ end
+ simple_filters = filters.reject { |k,v| k == :filters }
+ filter_hash.merge!(simple_filters)
+
+ uri = Addressable::URI.new
+ uri.query_values = filter_hash
+ "?#{uri.query}"
+ end
end
- # Save the instance to Survey Gizmo
+ # Save the resource to SurveyGizmo
def save
if id
# Then it's an update, because we already know the surveygizmo assigned id
- handle_response(SurveyGizmo.post(handle_route(:update), query: self.attributes_without_blanks))
- @latest_response.ok?
+ RestResponse.new(SurveyGizmo.post(handle_route(:update), query: self.attributes_without_blanks))
else
create_record_in_surveygizmo
end
end
- # fetch resource from SurveyGizmo and reload the attributes
- # @return [self, false]
- # Returns the object, if saved. Otherwise returns false.
+ # Repopulate the attributes based on what is on SurveyGizmo's servers
def reload
- handle_response(SurveyGizmo.get(handle_route(:get)))
- if @latest_response.ok?
- self.attributes = @latest_response['data']
- self
- else
- false
- end
+ self.attributes = RestResponse.new(SurveyGizmo.get(handle_route(:get))).data
+ self
end
- # Deleted the Resource from Survey Gizmo
- # @return [Boolean]
+ # Delete the Resource from Survey Gizmo
def destroy
- if id
- handle_response(SurveyGizmo.delete(handle_route(:delete)))
- @latest_response.ok?
- else
- false
- end
+ fail "No id; can't delete #{self.inspect}!" unless id
+ RestResponse.new(SurveyGizmo.delete(handle_route(:delete)))
end
# Sets the hash that will be used to interpolate values in routes. It needs to be defined per model.
# @return [Hash] a hash of the values needed in routing
def to_param_options
- raise "Define #to_param_options in #{self.class.name}"
+ fail "Define #to_param_options in #{self.class.name}"
end
- # Any errors returned by Survey Gizmo
- # @return [Array]
- def errors
- @errors ||= []
+ # Returns itself if successfully saved, but with attributes added by SurveyGizmo
+ def create_record_in_surveygizmo(attributes = {})
+ rest_response = RestResponse.new(SurveyGizmo.put(handle_route(:create), query: self.attributes_without_blanks))
+ self.attributes = rest_response.data
+ self
end
- # @visibility private
def inspect
if ENV['GIZMO_DEBUG']
ap "CLASS: #{self.class}"
end
@@ -218,52 +171,18 @@
end.compact
"#<#{self.class.name}:#{self.object_id}>\n#{attribute_strings.join()}"
end
- # Returns itself if successfully saved, but with attributes added by SurveyGizmo
- def create_record_in_surveygizmo(attributes = {})
- http = RestResponse.new(SurveyGizmo.put(handle_route(:create), query: self.attributes_without_blanks))
- handle_response(http)
- if http.ok?
- self.attributes = http.data
- self
- else
- false
- end
- end
-
protected
def attributes_without_blanks
self.attributes.reject { |k,v| v.blank? }
end
private
def handle_route(key)
self.class.handle_route(key, to_param_options)
- end
-
- def handle_response(rest_response, &block)
- @latest_response = rest_response
- if @latest_response.ok?
- self.errors.clear
- true
- else
- errors << @latest_response.message
- false
- end
- end
-
- def _copy(attributes = {})
- http = RestResponse.new(SurveyGizmo.post(handle_route(:update), query: self.attributes_without_blanks))
- handle_response(http) do
- if http.ok?
- self.attributes = http.data
- else
- false
- end
- end
end
end
end