module RailsConnector # Provides an enumerator, to iterate over obj search results and return "real" objs. # This is done using the {http://ruby-doc.org/core-1.8.7/Enumerable.html Enumerable mixin}, which provided methods like map, select or take. # # This enumerator is lazy. Let's say, that when looking for Objs with the ObjClass Publication there are 123 objs in total. Now enum.take(10) will only fetch the first 10 objs, leaving the other 113 objs untouched. # This also means, that iterating multiple times over this enumerator, each time the search results and objs are fetched again. If you want to get all objs at once, use enum.to_a. # # For all possible query's and options have a look at the cms api documentation about objs/search. # There is one exception: To adjust how many search results should be fetch with one chunk, use the option :batch_size. The default is 10. The :size option will be silently ignored. # # @example All objs, which are Publications # enum = ObjSearchEnumerator([{:field => '_obj_class', :operator => 'equal', :value => 'Publication'}]) # enum.each { |obj| puts obj.path } class ObjSearchEnumerator include Enumerable attr_reader :query attr_reader :options # @param [Array] query # @param [Hash] options def initialize(query, options = {}) @query = query @query.freeze options.delete(:size) options.delete('size') if batch_size = options.delete(:batch_size) options[:size] = batch_size end @options = options @options.freeze end def each offset = 0 current_batch, total = fetch_next_batch(offset) loop do if current_batch.size == 0 if offset < total current_batch, total = fetch_next_batch(offset) else raise StopIteration end end offset += 1 hit = current_batch.shift yield Obj.find(hit['id']) end end # The total size of all results. # @return [Integer] def size if @size.blank? @size = CmsRestApi.get(resource_path, {:query => query, :size => 1})['total'].to_i end @size end alias_method :length, :size private def fetch_next_batch(offset) request_result = CmsRestApi.get(resource_path, search_dsl(offset)) [request_result['results'], request_result['total'].to_i] end def resource_path "revisions/#{Workspace.current.revision_id}/objs/search" end def search_dsl(offset) options.merge({ :offset => offset, :query => query, }) end end end