From 13e23b8f22dcd5adbd66b2905ab8d5946f23e2e7 Mon Sep 17 00:00:00 2001 From: Sergey Kukunin Date: Wed, 13 Mar 2013 23:15:44 +0200 Subject: [PATCH 1/2] Add paginate method for pagination --- lib/fql.rb | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/lib/fql.rb b/lib/fql.rb index ea6cdc5..3c20d99 100644 --- a/lib/fql.rb +++ b/lib/fql.rb @@ -29,6 +29,72 @@ def execute(query, options = {}) self.decode_response response end + + # The wrapper of execute method, to get all records using pagination + # Pagination uses timestamp columns (relies on ORDER BY time DESC) + # and set WHERE clause to get next portion of data + # + # Works only with descendence ordering + # + # Supports both of single and multiple queries + # + # Query should contain two placeholders: where and limit. + # Paginate method will use them to modificate FQL query + # + # Accepted options the same, as .execute method plus: + # time_column: The name of column with timestamp. Default is 'time' + # primary_key: The name of primary key (ID) column. Default is 'id' + # rpp: Results per page. Default is 50. Should be lesser than Facebook limitations (different for each table). Defauls is 50 + # until: You can set the start time for pagination. All older records will be retrived + # + # Example: + # + # Fql.paginate('SELECT post_id, message FROM stream WHERE source_id = 1234567 %{where} ORDER BY updated_time DESC LIMIT %{limit}', { + # time_column: 'updated_time', + # primary_key: 'post_id', + # rpp: 30 + # }) do |result| + # #process the result here + # end + # + def paginate(query, options = {}) + query = { q: query } if query.is_a? String + + time_column = options[:time_column] || 'time' + primary_key = options[:primary_key] || 'id' + limit = options[:rpp] || 50 # Make limit chunk + + begin + #Make where chunk + where = '' + where << " and #{time_column} <= #{options[:until].to_i}" unless options[:until].blank? + (options[:last_ids] || []).each do |v| + where << " and #{primary_key} != '#{v}'" + end + + #Set where and limit chunks into query + pquery = {} + query.each { |k,v| pquery[k] = v % {where: where, limit: limit} } + + #Make query + results = self.execute(pquery, options) + + #Usually you need to paginate first query + set = query.size > 1 ? results.first['fql_result_set'] : results + + unless set.blank? + last_timestamp = set.last[time_column] + options[:until] = last_timestamp + #Exclude all IDs with the same timestamp from next portion of data + ids = set.select { |v| v[time_column] == last_timestamp }.map{ |v| v[primary_key] } + + options[:last_ids] = ids + + yield results + end + end until set.blank? + end + # Constructs the Facebook url which will return the results from the FQL # query. The FQL query and optional access_token are passed as GET # parameters. From 034436b9d3d7aa9f94acd14ad162413dc7caedb2 Mon Sep 17 00:00:00 2001 From: Sergey Kukunin Date: Thu, 14 Mar 2013 02:19:42 +0200 Subject: [PATCH 2/2] use double quotes instead single --- lib/fql/query.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/fql/query.rb b/lib/fql/query.rb index 4c98ab2..e1f13f5 100644 --- a/lib/fql/query.rb +++ b/lib/fql/query.rb @@ -30,7 +30,7 @@ def escape_query(query) def compose_multi_query q = '' @queries.each do |key, query| - q += "'#{key}':'#{escape_query query}'," + q += "\"#{key}\":\"#{escape_query query}\"," end # Remove last ',' and add enclosing braces '{' + q[0...-1] + '}'