Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Implement Twitter::Cursor#each without making an extra HTTP request

  • Loading branch information...
commit 8eeff57f5c6d6ca0a6f1ff5ebc31e652a71fc150 1 parent 6042913
@sferik authored
View
12 lib/twitter/api/friends_and_followers.rb
@@ -32,7 +32,7 @@ module FriendsAndFollowers
# Twitter.friend_ids('sferik')
# Twitter.friend_ids(7505382) # Same as above
def friend_ids(*args)
- cursor_from_response_with_user(:ids, nil, :get, "/1.1/friends/ids.json", args, :friend_ids)
+ cursor_from_response_with_user(:ids, nil, :get, "/1.1/friends/ids.json", args)
end
# @see https://dev.twitter.com/docs/api/1.1/get/followers/ids
@@ -57,7 +57,7 @@ def friend_ids(*args)
# Twitter.follower_ids('sferik')
# Twitter.follower_ids(7505382) # Same as above
def follower_ids(*args)
- cursor_from_response_with_user(:ids, nil, :get, "/1.1/followers/ids.json", args, :follower_ids)
+ cursor_from_response_with_user(:ids, nil, :get, "/1.1/followers/ids.json", args)
end
# Returns the relationship of the authenticating user to the comma separated list of up to 100 screen_names or user_ids provided. Values for connections can be: following, following_requested, followed_by, none.
@@ -94,7 +94,7 @@ def friendships(*args)
# @example Return an array of numeric IDs for every user who has a pending request to follow the authenticating user
# Twitter.friendships_incoming
def friendships_incoming(options={})
- cursor_from_response(:ids, nil, :get, "/1.1/friendships/incoming.json", options, :friendships_incoming)
+ cursor_from_response(:ids, nil, :get, "/1.1/friendships/incoming.json", options)
end
# Returns an array of numeric IDs for every protected user for whom the authenticating user has a pending follow request
@@ -109,7 +109,7 @@ def friendships_incoming(options={})
# @example Return an array of numeric IDs for every protected user for whom the authenticating user has a pending follow request
# Twitter.friendships_outgoing
def friendships_outgoing(options={})
- cursor_from_response(:ids, nil, :get, "/1.1/friendships/outgoing.json", options, :friendships_outgoing)
+ cursor_from_response(:ids, nil, :get, "/1.1/friendships/outgoing.json", options)
end
# Allows the authenticating user to follow the specified users, unless they are already followed
@@ -280,7 +280,7 @@ def friendship?(source, target, options={})
# Twitter.followers('sferik')
# Twitter.followers(7505382) # Same as above
def followers(*args)
- cursor_from_response_with_user(:users, Twitter::User, :get, "/1.1/followers/list.json", args, :followers)
+ cursor_from_response_with_user(:users, Twitter::User, :get, "/1.1/followers/list.json", args)
end
# Returns a cursored collection of user objects for every user the specified user is following (otherwise known as their "friends").
@@ -311,7 +311,7 @@ def followers(*args)
# Twitter.friends('sferik')
# Twitter.friends(7505382) # Same as above
def friends(*args)
- cursor_from_response_with_user(:users, Twitter::User, :get, "/1.1/friends/list.json", args, :friends)
+ cursor_from_response_with_user(:users, Twitter::User, :get, "/1.1/friends/list.json", args)
end
alias following friends
View
14 lib/twitter/api/lists.rb
@@ -125,7 +125,7 @@ def list_remove_member(*args)
# Twitter.memberships('sferik')
# Twitter.memberships(7505382)
def memberships(*args)
- cursor_from_response_with_user(:lists, Twitter::List, :get, "/1.1/lists/memberships.json", args, :memberships)
+ cursor_from_response_with_user(:lists, Twitter::List, :get, "/1.1/lists/memberships.json", args)
end
# Returns the subscribers of the specified list
@@ -152,7 +152,7 @@ def memberships(*args)
# Twitter.list_subscribers('sferik', 8863586)
# Twitter.list_subscribers(7505382, 'presidents')
def list_subscribers(*args)
- cursor_from_response_with_list(:get, "/1.1/lists/subscribers.json", args, :list_subscribers)
+ cursor_from_response_with_list(:get, "/1.1/lists/subscribers.json", args)
end
# Make the authenticated user follow the specified list
@@ -320,7 +320,7 @@ def list_member?(*args)
# Twitter.list_members(7505382, 'presidents')
# Twitter.list_members(7505382, 8863586)
def list_members(*args)
- cursor_from_response_with_list(:get, "/1.1/lists/members.json", args, :list_members)
+ cursor_from_response_with_list(:get, "/1.1/lists/members.json", args)
end
# Add a member to a list
@@ -474,7 +474,7 @@ def list(*args)
# Twitter.subscriptions('sferik')
# Twitter.subscriptions(7505382)
def subscriptions(*args)
- cursor_from_response_with_user(:lists, Twitter::List, :get, "/1.1/lists/subscriptions.json", args, :subscriptions)
+ cursor_from_response_with_user(:lists, Twitter::List, :get, "/1.1/lists/subscriptions.json", args)
end
# Removes specified members from the list
@@ -529,7 +529,7 @@ def list_remove_members(*args)
# Twitter.lists_owned('sferik')
# Twitter.lists_owned(7505382)
def lists_owned(*args)
- cursor_from_response_with_user(:lists, Twitter::List, :get, "/1.1/lists/ownerships.json", args, :lists_owned)
+ cursor_from_response_with_user(:lists, Twitter::List, :get, "/1.1/lists/ownerships.json", args)
end
alias lists_ownerships lists_owned
@@ -546,11 +546,11 @@ def list_from_response(request_method, path, args)
object_from_response(Twitter::List, request_method, path, arguments.options)
end
- def cursor_from_response_with_list(request_method, path, args, calling_method)
+ def cursor_from_response_with_list(request_method, path, args)
arguments = Twitter::API::Arguments.new(args)
merge_list!(arguments.options, arguments.pop)
merge_owner!(arguments.options, arguments.pop)
- cursor_from_response(:users, Twitter::User, request_method, path, arguments.options, calling_method)
+ cursor_from_response(:users, Twitter::User, request_method, path, arguments.options)
end
def list_user?(request_method, path, args)
View
2  lib/twitter/api/tweets.rb
@@ -281,7 +281,7 @@ def oembeds(*args)
def retweeters_ids(*args)
arguments = Twitter::API::Arguments.new(args)
arguments.options[:id] ||= extract_id(arguments.first)
- cursor_from_response(:ids, nil, :get, "/1.1/statuses/retweeters/ids.json", arguments.options, :retweeters_ids)
+ cursor_from_response(:ids, nil, :get, "/1.1/statuses/retweeters/ids.json", arguments.options)
end
private
View
2  lib/twitter/api/undocumented.rb
@@ -35,7 +35,7 @@ module Undocumented
# Twitter.following_followers_of('sferik')
# Twitter.following_followers_of(7505382) # Same as above
def following_followers_of(*args)
- cursor_from_response_with_user(:users, Twitter::User, :get, "/users/following_followers_of.json", args, :following_followers_of)
+ cursor_from_response_with_user(:users, Twitter::User, :get, "/users/following_followers_of.json", args)
end
# Returns Tweets count for a URL
View
4 lib/twitter/api/users.rb
@@ -153,7 +153,7 @@ def update_profile_image(image, options={})
# @example Return an array of user objects that the authenticating user is blocking
# Twitter.blocking
def blocking(options={})
- cursor_from_response(:users, Twitter::User, :get, "/1.1/blocks/list.json", options, :blocking)
+ cursor_from_response(:users, Twitter::User, :get, "/1.1/blocks/list.json", options)
end
# Returns an array of numeric user ids the authenticating user is blocking
@@ -170,7 +170,7 @@ def blocking(options={})
def blocked_ids(*args)
arguments = Twitter::API::Arguments.new(args)
merge_user!(arguments.options, arguments.pop)
- cursor_from_response(:ids, nil, :get, "/1.1/blocks/ids.json", arguments.options, :blocked_ids)
+ cursor_from_response(:ids, nil, :get, "/1.1/blocks/ids.json", arguments.options)
end
# Returns true if the authenticating user is blocking a target user
View
10 lib/twitter/api/utils.rb
@@ -108,12 +108,11 @@ def object_from_response(klass, request_method, path, options={})
# @param request_method [Symbol]
# @param path [String]
# @param args [Array]
- # @param method_name [Symbol]
# @return [Twitter::Cursor]
- def cursor_from_response_with_user(collection_name, klass, request_method, path, args, method_name)
+ def cursor_from_response_with_user(collection_name, klass, request_method, path, args)
arguments = Twitter::API::Arguments.new(args)
merge_user!(arguments.options, arguments.pop || screen_name) unless arguments.options[:user_id] || arguments.options[:screen_name]
- cursor_from_response(collection_name, klass, request_method, path, arguments.options, method_name)
+ cursor_from_response(collection_name, klass, request_method, path, arguments.options)
end
# @param collection_name [Symbol]
@@ -121,12 +120,11 @@ def cursor_from_response_with_user(collection_name, klass, request_method, path,
# @param request_method [Symbol]
# @param path [String]
# @param options [Hash]
- # @param method_name [Symbol]
# @return [Twitter::Cursor]
- def cursor_from_response(collection_name, klass, request_method, path, options, method_name)
+ def cursor_from_response(collection_name, klass, request_method, path, options)
merge_default_cursor!(options)
response = send(request_method.to_sym, path, options)
- Twitter::Cursor.from_response(response, collection_name.to_sym, klass, self, method_name, options)
+ Twitter::Cursor.from_response(response, collection_name.to_sym, klass, self, request_method, path, options)
end
def handle_forbidden_error(klass, error)
View
69 lib/twitter/cursor.rb
@@ -12,11 +12,12 @@ class Cursor
# @param collection_name [String, Symbol] The name of the method to return the collection
# @param klass [Class] The class to instantiate object in the collection
# @param client [Twitter::Client]
- # @param method_name [String, Symbol]
- # @param method_options [Hash]
+ # @param request_method [String, Symbol]
+ # @param path [String]
+ # @param options [Hash]
# @return [Twitter::Cursor]
- def self.from_response(response, collection_name, klass, client, method_name, method_options)
- new(response[:body], collection_name, klass, client, method_name, method_options)
+ def self.from_response(response, collection_name, klass, client, request_method, path, options)
+ new(response[:body], collection_name, klass, client, request_method, path, options)
end
# Initializes a new Cursor
@@ -25,40 +26,38 @@ def self.from_response(response, collection_name, klass, client, method_name, me
# @param collection_name [String, Symbol] The name of the method to return the collection
# @param klass [Class] The class to instantiate object in the collection
# @param client [Twitter::Client]
- # @param method_name [String, Symbol]
- # @param method_options [Hash]
+ # @param request_method [String, Symbol]
+ # @param path [String]
+ # @param options [Hash]
# @return [Twitter::Cursor]
- def initialize(attrs, collection_name, klass, client, method_name, method_options)
- @attrs = attrs
+ def initialize(attrs, collection_name, klass, client, request_method, path, options)
+ @collection_name = collection_name.to_sym
+ @klass = klass
@client = client
- @method_name = method_name
- @method_options = method_options
- @collection = Array(attrs[collection_name.to_sym]).map do |item|
- if klass
- klass.new(item)
- else
- item
- end
- end
+ @request_method = request_method.to_sym
+ @path = path
+ @options = options
+ set_attrs(attrs)
singleton_class.class_eval do
alias_method(collection_name.to_sym, :collection)
end
end
- # @param collection [Array]
- # @param cursor [Integer]
- # @return [Array]
- def all(collection=collection, cursor=next_cursor)
- cursor = @client.send(@method_name.to_sym, @method_options.merge(:cursor => cursor))
- collection += cursor.collection
- cursor.last? ? collection.flatten : all(collection, cursor.next_cursor)
+ def all
+ map{|element| element}
end
- # @return [Enumerable]
- def each
- all(collection, next_cursor).each do |element|
+ # @return [Enumerator]
+ def each(&block)
+ return to_enum(:each) unless block_given?
+ @collection.each do |element|
yield element
end
+ unless last?
+ fetch_next
+ each(&block)
+ end
+ self
end
def next_cursor
@@ -75,13 +74,25 @@ def previous_cursor
def first?
previous_cursor.zero?
end
- alias first first?
# @return [Boolean]
def last?
next_cursor.zero?
end
- alias last last?
+
+ private
+
+ def fetch_next
+ response = @client.send(@request_method, @path, @options.merge(:cursor => next_cursor))
+ set_attrs(response[:body])
+ end
+
+ def set_attrs(attrs)
+ @attrs = attrs
+ @collection = Array(attrs[@collection_name]).map do |element|
+ @klass ? @klass.new(element) : element
+ end
+ end
end
end
View
10 spec/twitter/cursor_spec.rb
@@ -4,7 +4,7 @@
describe "#collection" do
it "returns a collection" do
- collection = Twitter::Cursor.new({:ids => [1, 2, 3, 4, 5]}, :ids, nil, Twitter::Client.new, :follower_ids, {}).collection
+ collection = Twitter::Cursor.new({:ids => [1, 2, 3, 4, 5]}, :ids, nil, Twitter::Client.new, :get, "/1.1/followers/ids.json", {}).collection
expect(collection).to be_an Array
expect(collection.first).to be_a Fixnum
end
@@ -48,7 +48,7 @@
describe "#first?" do
context "when previous cursor equals zero" do
before do
- @cursor = Twitter::Cursor.new({:previous_cursor => 0}, :ids, nil, Twitter::Client.new, :follower_ids, {})
+ @cursor = Twitter::Cursor.new({:previous_cursor => 0}, :ids, nil, Twitter::Client.new, :get, "/1.1/followers/ids.json", {})
end
it "returns true" do
expect(@cursor.first?).to be_true
@@ -56,7 +56,7 @@
end
context "when previous cursor does not equal zero" do
before do
- @cursor = Twitter::Cursor.new({:previous_cursor => 1}, :ids, nil, Twitter::Client.new, :follower_ids, {})
+ @cursor = Twitter::Cursor.new({:previous_cursor => 1}, :ids, nil, Twitter::Client.new, :get, "/1.1/followers/ids.json", {})
end
it "returns true" do
expect(@cursor.first?).to be_false
@@ -67,7 +67,7 @@
describe "#last?" do
context "when next cursor equals zero" do
before do
- @cursor = Twitter::Cursor.new({:next_cursor => 0}, :ids, nil, Twitter::Client.new, :follower_ids, {})
+ @cursor = Twitter::Cursor.new({:next_cursor => 0}, :ids, nil, Twitter::Client.new, :get, "/1.1/followers/ids.json", {})
end
it "returns true" do
expect(@cursor.last?).to be_true
@@ -75,7 +75,7 @@
end
context "when next cursor does not equal zero" do
before do
- @cursor = Twitter::Cursor.new({:next_cursor => 1}, :ids, nil, Twitter::Client.new, :follower_ids, {})
+ @cursor = Twitter::Cursor.new({:next_cursor => 1}, :ids, nil, Twitter::Client.new, :get, "/1.1/followers/ids.json", {})
end
it "returns false" do
expect(@cursor.last?).to be_false
Please sign in to comment.
Something went wrong with that request. Please try again.