Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Caching Twitter API Calls in Rails

My project implements the 'Sign in with Twitter' OAuth dance, and renders a page showing all the users followed by the current user.

# /views/user/show.html.erb

<h1>Users You Follow</h1>

<%= render :partial => 'followed_user', :collection => @current_user.following %>

following is a virtual attribute of the Users model.

# /users/models/user.rb

def following
  result = twitter_request_authenticated('get_following')
  parse_body(result)
end

First off, because I'm new to Rails (and to MVC) I have to ask: is this a suitable abstraction? Should these 'followed users' themselves be modelled?

And now the real question:

Hitting Twitter for this information on every page load seems unnecessary. If we wanted to cache the result of such an API call for a given period of time (and make a method available to conveniently flush that cache), how might we go about that? Is it just a question of storing the return value of the API call in a database column, along with an 'expiry' column, and only calling the API when that column value is empty or cache_expires < now? If so, that sounds like it might be better situated in its own model. Thoughts?

like image 693
cantlin Avatar asked Mar 28 '11 14:03

cantlin


1 Answers

If you want the cache to expire after a certain amount of time you'll probably want to use Memcached. Memcached allows you to specify an expiration time for your cache. Once you have Rails configured to use Memcached as the default cache solution, you could do the following:

def following
  Rails.cache.fetch("following/#{id}", :expires_in => 1.hour) do
    result = twitter_request_authenticated('get_following')
    parse_body(result)
  end
end

Which would cache the following list, in memory, for 1 hour, and the cache would be unique to each user. You could then manually expire this cache at any point using this command:

Rails.cache.delete("following/#{id}") # where id is the user's id

To get started with Ruby on Rails caching check out this guide.

P.S: I think your approach of not modeling each user that the current_user is following is perfectly fine. If you want to perform a full set of actions on these users then it might be worth creating a separate model for a TwitterUser, but I would not merge User and TwitterUser because they are probably quite different. For example, a random TwitterUser might not have authorization in your system and probably won't be able to login just because a User of your system is following them.

like image 195
Pan Thomakos Avatar answered Sep 30 '22 20:09

Pan Thomakos