lib/zendesk_api/collection.rb in zendesk_api-0.2.6 vs lib/zendesk_api/collection.rb in zendesk_api-0.3.0
- old
+ new
@@ -25,36 +25,25 @@
# Additional options are: verb (default: GET), path (default: resource param), page, per_page.
# @param [Client] client The {Client} to use.
# @param [String] resource The resource being collected.
# @param [Hash] options Any additional options to be passed in.
def initialize(client, resource, options = {})
- @client, @resource = client, resource.resource_name
+ @client, @resource_class, @resource = client, resource, resource.resource_name
@options = Hashie::Mash.new(options)
- @verb = @options.delete(:verb)
- @collection_path = @options.delete(:collection_path)
+ set_association_from_options
+ join_special_params
- association_options = { :path => @options.delete(:path) }
- association_options[:path] ||= @collection_path.join("/") if @collection_path
- @association = @options.delete(:association) || Association.new(association_options.merge(:class => resource))
-
- # some params use comma-joined strings instead of query-based arrays for multiple values
- @options.each do |k, v|
- if SPECIALLY_JOINED_PARAMS.include?(k.to_sym) && v.is_a?(Array)
- @options[k] = v.join(',')
- end
- end
-
- @collection_path ||= [@resource]
- @resource_class = resource
- @fetchable = true
+ @verb = @options.delete(:verb)
@includes = Array(@options.delete(:include))
# Used for Attachments, TicketComment
if @resource_class.is_a?(Class) && @resource_class.superclass == ZendeskAPI::Data
@resources = []
@fetchable = false
+ else
+ @fetchable = true
end
end
# Passes arguments and the proper path to the resource class method.
# @param [Hash] attributes Attributes to pass to Create#create
@@ -156,43 +145,20 @@
end
# Executes actual GET from API and loads resources into proper class.
# @param [Boolean] reload Whether to disregard cache
def fetch(reload = false)
- return @resources if @resources && (!@fetchable || !reload)
-
- if association && association.options.parent && association.options.parent.new_record?
+ if @resources && (!@fetchable || !reload)
+ return @resources
+ elsif association && association.options.parent && association.options.parent.new_record?
return @resources = []
end
- if @query
- path = @query
- @query = nil
- else
- path = self.path
- end
+ @response = get_response(@query || self.path)
+ handle_response(@response.body.dup)
- @response = @client.connection.send(@verb || "get", path) do |req|
- opts = @options.delete_if {|k, v| v.nil?}
-
- req.params.merge!(:include => @includes.join(",")) if @includes.any?
-
- if %w{put post}.include?(@verb.to_s)
- req.body = opts
- else
- req.params.merge!(opts)
- end
- end
-
- body = @response.body.dup
-
- results = body.delete(@resource_class.model_key) || body.delete("results")
- @resources = results.map {|res| @resource_class.new(@client, res)}
-
- set_page_and_count(body)
- set_includes(@resources, @includes, body)
-
+ @query = nil
@resources
end
rescue_client_error :fetch, :with => lambda { Array.new }
@@ -236,12 +202,11 @@
# * Otherwise, returns an empty array.
def next
if @options["page"]
clear_cache
@options["page"] += 1
- elsif @next_page
- @query = @next_page
+ elsif @query = @next_page
fetch(true)
else
clear_cache
@resources = []
end
@@ -253,12 +218,11 @@
# * Otherwise, returns an empty array.
def prev
if @options["page"] && @options["page"] > 1
clear_cache
@options["page"] -= 1
- elsif @prev_page
- @query = @prev_page
+ elsif @query = @prev_page
fetch(true)
else
clear_cache
@resources = []
end
@@ -275,20 +239,16 @@
# @private
def to_ary; nil; end
# Sends methods to underlying array of resources.
def method_missing(name, *args, &block)
- methods = @resource_class.singleton_methods(false).map(&:to_sym)
-
- if methods.include?(name)
- @resource_class.send(name, @client, *args, &block)
+ if resource_methods.include?(name)
+ collection_method(name, *args, &block)
elsif Array.new.respond_to?(name)
- to_a.send(name, *args, &block)
+ array_method(name, *args, &block)
else
- opts = args.last.is_a?(Hash) ? args.last : {}
- opts.merge!(:collection_path => @collection_path.dup.push(name))
- self.class.new(@client, @resource_class, @options.merge(opts))
+ next_collection(name, *args, &block)
end
end
# @private
def to_s
@@ -313,8 +273,73 @@
if @next_page =~ /page=(\d+)/
@options["page"] = $1.to_i - 1
elsif @prev_page =~ /page=(\d+)/
@options["page"] = $1.to_i + 1
end
+ end
+
+ ## Initialize
+
+ def join_special_params
+ # some params use comma-joined strings instead of query-based arrays for multiple values
+ @options.each do |k, v|
+ if SPECIALLY_JOINED_PARAMS.include?(k.to_sym) && v.is_a?(Array)
+ @options[k] = v.join(',')
+ end
+ end
+ end
+
+ def set_association_from_options
+ @collection_path = @options.delete(:collection_path)
+
+ association_options = { :path => @options.delete(:path) }
+ association_options[:path] ||= @collection_path.join("/") if @collection_path
+ @association = @options.delete(:association) || Association.new(association_options.merge(:class => @resource_class))
+
+ @collection_path ||= [@resource]
+ end
+
+ ## Fetch
+
+ def get_response(path)
+ @response = @client.connection.send(@verb || "get", path) do |req|
+ opts = @options.delete_if {|_, v| v.nil?}
+
+ req.params.merge!(:include => @includes.join(",")) if @includes.any?
+
+ if %w{put post}.include?(@verb.to_s)
+ req.body = opts
+ else
+ req.params.merge!(opts)
+ end
+ end
+ end
+
+ def handle_response(body)
+ results = body.delete(@resource_class.model_key) || body.delete("results")
+ @resources = results.map {|res| @resource_class.new(@client, res)}
+
+ set_page_and_count(body)
+ set_includes(@resources, @includes, body)
+ end
+
+ ## Method missing
+
+ def array_method(name, *args, &block)
+ to_a.send(name, *args, &block)
+ end
+
+ def next_collection(name, *args, &block)
+ opts = args.last.is_a?(Hash) ? args.last : {}
+ opts.merge!(:collection_path => @collection_path.dup.push(name))
+ self.class.new(@client, @resource_class, @options.merge(opts))
+ end
+
+ def collection_method(name, *args, &block)
+ @resource_class.send(name, @client, *args, &block)
+ end
+
+ def resource_methods
+ @resource_methods ||= @resource_class.singleton_methods(false).map(&:to_sym)
end
end
end