From cdc418bd956b8fb318596681bef4dfcee46f485e Mon Sep 17 00:00:00 2001 From: Tanel Jakobsoo Date: Mon, 8 Feb 2016 16:47:19 +0200 Subject: [PATCH] Added auto pagination option for listing endpoints Allow allow to set default "per_page" value Example usage: client = Voog::Client.new('example.com', 'afcf30182aecfc8155d390d7d4552d14', auto_paginate: true, per_page: 250) Closes #3 --- README.markdown | 4 ++- lib/voog_api.rb | 2 +- lib/voog_api/api/articles.rb | 2 +- lib/voog_api/api/assets.rb | 2 +- lib/voog_api/api/comments.rb | 2 +- lib/voog_api/api/content_partials.rb | 2 +- lib/voog_api/api/contents.rb | 2 +- lib/voog_api/api/element_definitions.rb | 2 +- lib/voog_api/api/elements.rb | 2 +- lib/voog_api/api/forms.rb | 2 +- lib/voog_api/api/languages.rb | 2 +- lib/voog_api/api/layout_assets.rb | 2 +- lib/voog_api/api/layouts.rb | 2 +- lib/voog_api/api/media_sets.rb | 2 +- lib/voog_api/api/nodes.rb | 2 +- lib/voog_api/api/pages.rb | 2 +- lib/voog_api/api/people.rb | 2 +- lib/voog_api/api/tags.rb | 2 +- lib/voog_api/api/texts.rb | 2 +- lib/voog_api/api/tickets.rb | 2 +- lib/voog_api/client.rb | 37 +++++++++++++++++++++++-- 21 files changed, 56 insertions(+), 23 deletions(-) diff --git a/README.markdown b/README.markdown index 0efa971..7025fd7 100644 --- a/README.markdown +++ b/README.markdown @@ -35,7 +35,7 @@ To generate your personal **API token** for your site, go to `Account` -> `My pr All requests to the Voog API are done through the `Voog::Client` class, which takes two parameters: site host and API token. ```ruby -client = Voog::Client.new('example.com', 'afcf30182aecfc8155d390d7d4552d14', protocol: :http, raise_on_error: false) +client = Voog::Client.new('example.com', 'afcf30182aecfc8155d390d7d4552d14', protocol: :http, auto_paginate: true, raise_on_error: false) ``` Making an API request is as simple as calling a single method on the client: @@ -59,4 +59,6 @@ puts layout[:title] ### Optional parameters for client * `protocol` - endpoint protocol (`http` or `https` default is `http`). +* `auto_paginate` - enable auto pagination for list requests. Defaults to `false`. +* `per_page` - set default `per_page` value for list requests. Defaults to `nil` (API default is `50`). * `raise_on_error` - interrupts program with error (`Faraday::Error`) when request response code is between `400` and `600` (default is `false`). diff --git a/lib/voog_api.rb b/lib/voog_api.rb index da835d5..01292e2 100644 --- a/lib/voog_api.rb +++ b/lib/voog_api.rb @@ -5,7 +5,7 @@ module Voog class << self - attr_accessor :host, :api_token + attr_accessor :host, :api_token, :auto_paginate, :per_page def client(options = {}) unless host.nil? && api_token.nil? diff --git a/lib/voog_api/api/articles.rb b/lib/voog_api/api/articles.rb index 00438c1..e2f015e 100644 --- a/lib/voog_api/api/articles.rb +++ b/lib/voog_api/api/articles.rb @@ -4,7 +4,7 @@ module Articles # List articles def articles(params = {}) - get 'articles', {query: params} + paginate 'articles', {query: params} end # Get a single article diff --git a/lib/voog_api/api/assets.rb b/lib/voog_api/api/assets.rb index 39af83f..3542dcd 100644 --- a/lib/voog_api/api/assets.rb +++ b/lib/voog_api/api/assets.rb @@ -4,7 +4,7 @@ module Assets # List assets def assets(params = {}) - get 'assets', {query: params} + paginate 'assets', {query: params} end # Get a single asset diff --git a/lib/voog_api/api/comments.rb b/lib/voog_api/api/comments.rb index 2f9a562..b514cc8 100644 --- a/lib/voog_api/api/comments.rb +++ b/lib/voog_api/api/comments.rb @@ -4,7 +4,7 @@ module Comments # List article comments def comments(article_id, params = {}) - get "articles/#{article_id}/comments", {query: params} + paginate "articles/#{article_id}/comments", {query: params} end # Get a single comment for article diff --git a/lib/voog_api/api/content_partials.rb b/lib/voog_api/api/content_partials.rb index deafdda..72ef33e 100644 --- a/lib/voog_api/api/content_partials.rb +++ b/lib/voog_api/api/content_partials.rb @@ -4,7 +4,7 @@ module ContentPartials # List content partials contents def content_partials(params = {}) - get 'content_partials', {query: params} + paginate 'content_partials', {query: params} end # Get a single content partial content diff --git a/lib/voog_api/api/contents.rb b/lib/voog_api/api/contents.rb index 6c64e23..3c4fa51 100644 --- a/lib/voog_api/api/contents.rb +++ b/lib/voog_api/api/contents.rb @@ -11,7 +11,7 @@ module ParentKind # List contents def contents(parent_name, parent_id, params = {}) - get "#{parent_name}/#{parent_id}/contents", {query: params} + paginate "#{parent_name}/#{parent_id}/contents", {query: params} end # Get a single content diff --git a/lib/voog_api/api/element_definitions.rb b/lib/voog_api/api/element_definitions.rb index 1e87243..9a15185 100644 --- a/lib/voog_api/api/element_definitions.rb +++ b/lib/voog_api/api/element_definitions.rb @@ -4,7 +4,7 @@ module ElementDefinitions # List element_definitions def element_definitions(params = {}) - get 'element_definitions', {query: params} + paginate 'element_definitions', {query: params} end # Get a single element_definition diff --git a/lib/voog_api/api/elements.rb b/lib/voog_api/api/elements.rb index 88cb901..1cddb0c 100644 --- a/lib/voog_api/api/elements.rb +++ b/lib/voog_api/api/elements.rb @@ -4,7 +4,7 @@ module Elements # List elements def elements(params = {}) - get 'elements', {query: params} + paginate 'elements', {query: params} end # Get a single element diff --git a/lib/voog_api/api/forms.rb b/lib/voog_api/api/forms.rb index f97d91a..26ddf5f 100644 --- a/lib/voog_api/api/forms.rb +++ b/lib/voog_api/api/forms.rb @@ -4,7 +4,7 @@ module Forms # List forms def forms(params = {}) - get 'forms', {query: params} + paginate 'forms', {query: params} end # Get a single form diff --git a/lib/voog_api/api/languages.rb b/lib/voog_api/api/languages.rb index 43b838d..a9c61ee 100644 --- a/lib/voog_api/api/languages.rb +++ b/lib/voog_api/api/languages.rb @@ -4,7 +4,7 @@ module Languages # List languages def languages(params = {}) - get 'languages', {query: params} + paginate 'languages', {query: params} end # Get a single language diff --git a/lib/voog_api/api/layout_assets.rb b/lib/voog_api/api/layout_assets.rb index 1fac889..38d2a1a 100644 --- a/lib/voog_api/api/layout_assets.rb +++ b/lib/voog_api/api/layout_assets.rb @@ -4,7 +4,7 @@ module LayoutAssets # List layouts assets def layout_assets(params = {}) - get 'layout_assets', {query: params} + paginate 'layout_assets', {query: params} end # Get a single layout asset diff --git a/lib/voog_api/api/layouts.rb b/lib/voog_api/api/layouts.rb index c3ccf01..3855097 100644 --- a/lib/voog_api/api/layouts.rb +++ b/lib/voog_api/api/layouts.rb @@ -4,7 +4,7 @@ module Layouts # List layouts def layouts(params = {}) - get 'layouts', {query: params} + paginate 'layouts', {query: params} end # Get a single layout diff --git a/lib/voog_api/api/media_sets.rb b/lib/voog_api/api/media_sets.rb index 2a9086a..94389fe 100644 --- a/lib/voog_api/api/media_sets.rb +++ b/lib/voog_api/api/media_sets.rb @@ -4,7 +4,7 @@ module MediaSets # List media_sets def media_sets(params = {}) - get 'media_sets', {query: params} + paginate 'media_sets', {query: params} end # Get a single media_set diff --git a/lib/voog_api/api/nodes.rb b/lib/voog_api/api/nodes.rb index b1b7784..7041c87 100644 --- a/lib/voog_api/api/nodes.rb +++ b/lib/voog_api/api/nodes.rb @@ -4,7 +4,7 @@ module Nodes # List nodes def nodes(params = {}) - get 'nodes', {query: params} + paginate 'nodes', {query: params} end # Get a single node diff --git a/lib/voog_api/api/pages.rb b/lib/voog_api/api/pages.rb index bef3bba..45f92cf 100644 --- a/lib/voog_api/api/pages.rb +++ b/lib/voog_api/api/pages.rb @@ -4,7 +4,7 @@ module Pages # List pages def pages(params = {}) - get 'pages', {query: params} + paginate 'pages', {query: params} end # Get a single page diff --git a/lib/voog_api/api/people.rb b/lib/voog_api/api/people.rb index a27b4d0..a1c27c4 100644 --- a/lib/voog_api/api/people.rb +++ b/lib/voog_api/api/people.rb @@ -4,7 +4,7 @@ module People # List people def people(params = {}) - get 'people', {query: params} + paginate 'people', {query: params} end # Get a single person diff --git a/lib/voog_api/api/tags.rb b/lib/voog_api/api/tags.rb index d1e1219..41b1eca 100644 --- a/lib/voog_api/api/tags.rb +++ b/lib/voog_api/api/tags.rb @@ -4,7 +4,7 @@ module Tags # List tags def tags(params = {}) - get 'tags', {query: params} + paginate 'tags', {query: params} end # Get a single tag diff --git a/lib/voog_api/api/texts.rb b/lib/voog_api/api/texts.rb index 4c41eeb..8ec3c17 100644 --- a/lib/voog_api/api/texts.rb +++ b/lib/voog_api/api/texts.rb @@ -4,7 +4,7 @@ module Texts # List text contents def texts(params = {}) - get 'texts', {query: params} + paginate 'texts', {query: params} end # Get a single text content diff --git a/lib/voog_api/api/tickets.rb b/lib/voog_api/api/tickets.rb index 881c9c8..be83d88 100644 --- a/lib/voog_api/api/tickets.rb +++ b/lib/voog_api/api/tickets.rb @@ -4,7 +4,7 @@ module Tickets # List form tickets def tickets(form_id, params = {}) - get "forms/#{form_id}/tickets", {query: params} + paginate "forms/#{form_id}/tickets", {query: params} end # Get a single ticket for form diff --git a/lib/voog_api/client.rb b/lib/voog_api/client.rb index f7892bf..1c9de74 100644 --- a/lib/voog_api/client.rb +++ b/lib/voog_api/client.rb @@ -25,7 +25,9 @@ module Voog class Client - + + MAX_PER_PAGE = 250 + include Voog::API::Articles include Voog::API::Assets include Voog::API::Comments @@ -46,13 +48,15 @@ class Client include Voog::API::Texts include Voog::API::Tickets - attr_reader :api_token, :host + attr_reader :api_token, :host, :auto_paginate, :per_page # Initialize Voog API client. # # @param host [String] a Voog site host. # @param api_token [String] a Voog site API token. # @option options [String] :protocol endpoint protocol ("http" or "https"). Defaults to "http". + # @option options [String] :auto_paginate enable auto pagination for list requests. Defaults to "false". + # @option options [String] :per_page set default "per_page" value for list requests. Defaults to "nil". # @option options [Boolean] :raise_on_error interrupts program with error ("Faraday::Error") when request response code is between "400" and "600" (default is "false"). # @example Initialize client # client = Voog::Client.new('example.com', 'afcf30182aecfc8155d390d7d4552d14', protocol: :http, raise_on_error: false) @@ -61,6 +65,8 @@ def initialize(host = Voog.host, api_token = Voog.api_token, options = {}) @api_token = api_token @options = options @protocol = options[:protocol].to_s.downcase == 'https' ? 'https' : 'http' + @auto_paginate = options.fetch(:auto_paginate, Voog.auto_paginate) + @per_page = options.fetch(:per_page, Voog.per_page) @raise_on_error = options.fetch(:raise_on_error, true) end @@ -120,7 +126,32 @@ def last_response def parse_response(response) JSON.parse(response).inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo} end - + + # Fetch all elements for requested API resource when {#auto_paginate} is turned on. + def paginate(url, options = {}, &block) + opts = options.dup + if @auto_paginate || @per_page + opts[:query][:per_page] ||= @per_page || (@auto_paginate ? MAX_PER_PAGE : nil) + end + + data = request(:get, url, nil, opts) + + if @auto_paginate + i = 0 + while @last_response.rels[:next] + puts "Request: #{i += 1}" + @last_response = @last_response.rels[:next].get(headers: opts[:headers]) + if block_given? + yield(data, @last_response) + else + data.concat(@last_response.data) if @last_response.data.is_a?(Array) + end + end + end + + data + end + private def request(method, path, data, options = {})