Post

3 followers Follow
0
Avatar

Podio API Cache Ruby on Rails

Hi,

Curious if anyone has any really good strategies for caches requests via the Podio API to a Rails app. I've seen a few good examples for PHP, but nothing for Rails.

I'm essentially iterating through several workspaces, and looking for instances where the same item is referenced across several apps, across several workspaces so that I can render them on one single view.

For example (pseudo):

workspace_One, app_one, item1
workspace_Two, app_one, field1 references item1 in workspace_One.app_one
workspace_Three, app_one, field1 references item1 in workspace_One.app_one
workspace_Four, app_one, field1 references item1 in workspace_One.app_one
workspace_Five, app_one, field1 references item1 in workspace_One.app_one
workspace_ThirtyFive, app_one, field1 references item1 in workspace_One.app_one
etc.

  • Call workspace_One to Workspace_ThirtyFive
  • Render on Show view names of each workspace where field1 references item1 from workspace_one

I've succeeded in doing that programmatically, but it's extremely slow, and I'm fast approaching my API rate limits because users are refreshing the page, making the call several times, etc.

I appreciate any help I can get.

-Rolando Brown
rolando.brown@gmail.com

Rolando Brown

Official comment

Avatar

Hi Rolando,

We use this helper mixin internally, it might help you. It requires Rails caching to be set up, and this specific implementation assumes use of app authentication and some specific settings available:

module ApiRequestHelper

  protected

  # login as an app, but change back to the default Podio client
  def login_as_app(app_config)
    Podio.with_client do
      begin
        token_key = "app_token_#{app_config[:id]}"
        token = Rails.cache.read(token_key)

        if token
          # setup client with existing token
          Podio.client = Podio::Client.new(PODIO_READ_ONLY_CLIENT_OPTIONS.merge(:oauth_token => token))
        else
          # get a new token and save it in the cache
          Podio.client = Podio::Client.new(PODIO_READ_ONLY_CLIENT_OPTIONS)
          Podio.client.authenticate_with_app(app_config[:id], app_config[:token])
          Rails.cache.write(token_key, Podio.client.oauth_token)
        end

        yield

        # in case we refreshed the token, store the updated token in the cache
        if Podio.client.oauth_token.refreshed
          Rails.cache.write(token_key, Podio.client.oauth_token)
        end
      rescue Podio::InvalidGrantError
        Rails.cache.delete(token_key)
      end
    end
  end

  def cached_api_request(cache_key, app_id)
    full_cache_key = "docs-#{cache_key}"

    result = begin
      Rails.cache.read(full_cache_key) if Rails.cache.exist?(full_cache_key)
    rescue
      nil
    end

    unless result
      login_as_app app_id do
        result = yield
      end
      Rails.cache.write(full_cache_key, result, :expires_in => 5.minutes)
    end

    result
  end

end

Here's an example of how we call it to get a number of items back, either from cache or API:

    cached_api_request("products", DynamicPages::Jobs::PRODUCTS_APP) do
      products = Podio::Item.find_all(DynamicPages::Jobs::PRODUCTS_APP[:id])
      products.all.collect { |item| item_to_product(item) }
    end

Hope this helps.

Casper Fabricius

Please sign in to leave a comment.

2 comments

0
Avatar

Hi Rolando,

It's not entirely clear to me what you're trying to achieve, but you may find Podio::Item.find_references(item_id) helpful to find references to an item.

About caching, the simplest approach would be to simply use time-based expiry if you can live with results being slightly out of date.

Best,
Andreas

Andreas Garnæs 0 votes