Created
November 22, 2012 13:51
-
-
Save samleb/4131271 to your computer and use it in GitHub Desktop.
Ruby snippet to get Facebook Like in batches
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class Film < ActiveRecord::Base | |
| class << self | |
| def compute_facebook_likes | |
| fb = FacebookLike.new(AppConfig.facebook.access_token) | |
| find_in_batches(:select => 'id, permalink', :batch_size => fb.batch_size) do |group| | |
| urls = group.map { |f| film_url(f) } | |
| likes = fb.request_likes_for_urls(urls) | |
| update_facebook_likes(group, likes) | |
| sleep 0.2 | |
| end | |
| end | |
| end | |
| # … | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require 'uri' | |
| class FacebookLike | |
| autoload :Net, 'net/https' | |
| autoload :CGI, 'cgi' | |
| GRAPH_URL = URI.parse("https://graph.facebook.com/").freeze | |
| FQL_QUERY_URL = "method/fql.query?query=".freeze | |
| FQL_QUERY_FORMAT = %{SELECT total_count FROM link_stat WHERE url="%s"}.freeze | |
| BATCH_SIZE = 50 | |
| class GraphException < RuntimeError; end | |
| def self.request_likes_for_urls(access_token, urls) | |
| new(access_token).request_likes_for_urls(urls) | |
| end | |
| def initialize(access_token) | |
| @token = access_token | |
| @http = create_http | |
| end | |
| def batch_size | |
| BATCH_SIZE | |
| end | |
| def request_likes_for_urls(urls) | |
| urls = Array(urls) | |
| check_batch_size!(urls.size) | |
| urls.map! { |url| fql_query_url(url) } | |
| response = @http.request(create_request(urls)) | |
| response = parse_json(response.body) | |
| check_batch_response!(response) | |
| parse_batch_response(response) | |
| end | |
| protected | |
| def create_http | |
| http = Net::HTTP.new(GRAPH_URL.host, GRAPH_URL.port) | |
| http.use_ssl = true | |
| # FIXME: try removing this as we _should_ be verifying TLS certificate | |
| # and the default behavior is not VERIFY_NONE anymore since 1.9 | |
| http.verify_mode = OpenSSL::SSL::VERIFY_NONE | |
| http | |
| end | |
| def create_request(urls) | |
| request = Net::HTTP::Post.new(GRAPH_URL.request_uri) | |
| request.form_data = { | |
| :access_token => @token, | |
| :batch => json_batch(urls) | |
| } | |
| request | |
| end | |
| def fql_query_url(url) | |
| fql_query = FQL_QUERY_FORMAT % url | |
| FQL_QUERY_URL + CGI.escape(fql_query) | |
| end | |
| def json_batch(urls) | |
| urls.map do |url| | |
| {"method" => "GET", "relative_url" => url} | |
| end.to_json | |
| end | |
| def check_batch_size!(size) | |
| if size > batch_size | |
| raise ArgumentError, "Too many URLs for batch request: #{size} (limit #{batch_size})" | |
| end | |
| end | |
| def check_batch_response!(response) | |
| unless Array === response | |
| error = response["error"] | |
| raise GraphException, "#{error["message"]} (#{error["type"]})" | |
| end | |
| end | |
| def parse_batch_response(batch) | |
| batch.map do |response| | |
| next unless response["code"] == 200 | |
| body = parse_json(response["body"]) | |
| next unless Array === body # body := {"error_msg": "Service temporarly unavailable"} | |
| body[0]["total_count"] # body := [{"total_count": 1234}] | |
| end | |
| end | |
| def parse_json(string) | |
| ActiveSupport::JSON.decode(string) | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment