lib/survey_gizmo/resource.rb in survey-gizmo-ruby-4.0.0 vs lib/survey_gizmo/resource.rb in survey-gizmo-ruby-4.1.0
- old
+ new
@@ -16,39 +16,67 @@
@descendants ||= Set.new
end
# These are methods that every API resource can use to access resources in SurveyGizmo
module ClassMethods
- # 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)))
- _collection = response.data.map { |datum| datum.is_a?(Hash) ? self.new(datum) : datum }
+ # Get an array of resources.
+ # @param [Hash] options - simple URL params at the top level, and SurveyGizmo "filters" at the :filters key
+ #
+ # example: { page: 2, filters: [{ field: "istestdata", operator: "<>", value: 1 }] }
+ #
+ # The top level keys (e.g. page, resultsperpage) get encoded in the url, while the
+ # contents of the array of hashes passed at the :filters key get turned into the format
+ # SurveyGizmo expects for its internal filtering, for example:
+ #
+ # filter[field][0]=istestdata&filter[operator][0]=<>&filter[value][0]=1
+ #
+ # Set all_pages: true if you want the gem to page through all the available responses
+ def all(conditions = {}, _deprecated_filters = {})
+ conditions = merge_params(conditions, _deprecated_filters)
+ fail ':all_pages and :page are mutually exclusive' if conditions[:page] && conditions[:all_pages]
+ all_pages = conditions.delete(:all_pages)
+ properties = conditions.dup
+ conditions[:resultsperpage] = SurveyGizmo.configuration.results_per_page unless conditions[:resultsperpage]
+
+ request_route = handle_route!(:create, conditions)
+ response = RestResponse.new(SurveyGizmo.get(request_route + filters_to_query_string(conditions)))
+ collection = response.data.map { |datum| datum.is_a?(Hash) ? new(datum) : datum }
+
+ while all_pages && response.current_page < response.total_pages
+ paged_filter = filters_to_query_string(conditions.merge(page: response.current_page + 1))
+ response = RestResponse.new(SurveyGizmo.get(request_route + paged_filter))
+ collection += response.data.map { |datum| datum.is_a?(Hash) ? new(datum) : datum }
+ 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] }
+ properties.each do |k,v|
+ if v && instance_methods.include?(k)
+ collection.each { |c| c[k] ||= v }
end
end
# 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
+ collection += collection.map { |question| question.sub_questions }.flatten
end
- _collection
+ collection
end
- # Retrieve a single resource.
- def first(conditions = {}, filters = nil)
- response = RestResponse.new(SurveyGizmo.get(handle_route(:get, conditions) + convert_filters_into_query_string(filters)))
+ # Retrieve a single resource. See usage comment on .all
+ def first(conditions, _deprecated_filters = {})
+ conditions = merge_params(conditions, _deprecated_filters)
+ properties = conditions.dup
+
+ response = RestResponse.new(SurveyGizmo.get(handle_route!(:get, conditions) + filters_to_query_string(conditions)))
# 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
- new(conditions.merge(response.data))
+ new(properties.merge(response.data))
end
# Create a new resource. Returns the newly created Resource instance.
def create(attributes = {})
resource = new(attributes)
@@ -56,70 +84,66 @@
resource
end
# Delete resources
def destroy(conditions)
- RestResponse.new(SurveyGizmo.delete(handle_route(:delete, conditions)))
+ RestResponse.new(SurveyGizmo.delete(handle_route!(:delete, conditions)))
end
# Define the path where a resource is located
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
+ # 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.
- def handle_route(key, interpolation_hash)
+ #
+ # This method has the SIDE EFFECT of deleting REST path related keys from interpolation_hash!
+ def handle_route!(key, interpolation_hash)
path = @paths[key]
- fail "No routes defined for `#{key}` in #{self.name}" unless path
+ fail "No routes defined for `#{key}` in #{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]
+ interpolation_hash.delete($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)
+ private
+
+ # Convert a [Hash] of params and internal surveygizmo style filters into a query string
+ def filters_to_query_string(filters = {})
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]}",
- )
+ params = {}
+ (filters.delete(:filters) || []).each_with_index do |filter, i|
+ fail "Bad filter params: #{filter}" unless filter.is_a?(Hash) && [:field, :operator, :value].all? { |k| filter[k] }
+
+ params["filter[field][#{i}]".to_sym] = "#{filter[:field]}"
+ params["filter[operator][#{i}]".to_sym] = "#{filter[:operator]}"
+ params["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_values = params.merge(filters)
"?#{uri.query}"
end
+
+ def merge_params(conditions, _deprecated_filters)
+ $stderr.puts('Use of the 2nd hash parameter is deprecated.') unless _deprecated_filters.empty?
+ conditions.merge(_deprecated_filters || {})
+ end
end
# Save the resource to SurveyGizmo
def save
if id
# Then it's an update, because we already know the surveygizmo assigned id
- RestResponse.new(SurveyGizmo.post(handle_route(:update), query: self.attributes_without_blanks))
+ RestResponse.new(SurveyGizmo.post(handle_route(:update), query: attributes_without_blanks))
else
create_record_in_surveygizmo
end
end
@@ -141,48 +165,34 @@
fail "Define #to_param_options in #{self.class.name}"
end
# 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))
+ rest_response = RestResponse.new(SurveyGizmo.put(handle_route(:create), query: attributes_without_blanks))
self.attributes = rest_response.data
self
end
def inspect
- if ENV['GIZMO_DEBUG']
- ap "CLASS: #{self.class}"
- end
-
attribute_strings = self.class.attribute_set.map do |attrib|
- if ENV['GIZMO_DEBUG']
- ap attrib
- ap attrib.name
- ap self.send(attrib.name)
- ap self.send(attrib.name).class
- end
+ value = self.send(attrib.name)
+ value = value.is_a?(Hash) ? value.inspect : value.to_s
- if self.send(attrib.name).class == Hash
- value = self.send(attrib.name).inspect
- else
- value = self.send(attrib.name).to_s
- end
-
" \"#{attrib.name}\" => \"#{value}\"\n" unless value.strip.blank?
end.compact
- "#<#{self.class.name}:#{self.object_id}>\n#{attribute_strings.join()}"
+ "#<#{self.class.name}:#{self.object_id}>\n#{attribute_strings.join}"
end
protected
def attributes_without_blanks
- self.attributes.reject { |k,v| v.blank? }
+ attributes.reject { |k,v| v.blank? }
end
private
def handle_route(key)
- self.class.handle_route(key, to_param_options)
+ self.class.handle_route!(key, to_param_options)
end
end
end