Permalink
Browse files

Always return URIs instead of strings

Standardize on URI over URL.
  • Loading branch information...
1 parent f6deb7d commit 341f68d1a46667a820754d30ffa6ec2f50034afc @sferik committed Jul 28, 2013
View
@@ -200,23 +200,23 @@ end</code></pre>
</tbody>
</table>
-In the examples above, *n* is dependent on the number of people the
-authenticated user follows on Twitter (divided by 20, the number of friends you
-can fetch per request). So, if the user followers 85 people, calling
-`Twitter.friends.take(20)` would make 6 HTTP requests in version 4. In version
+In the examples above, *n* varies with the number of people the authenticated
+user follows on Twitter. This resource returns up to 20 friends per HTTP GET,
+so if the authenticated user follows 200 people, calling
+`Twitter.friends.take(20)` would make 11 HTTP requests in version 4. In version
5, it makes just 1 HTTP request. Keep in mind, eliminating a single HTTP
request to the Twitter API will reduce the latency of your application by
[about 500 ms][status].
[status]: https://dev.twitter.com/status
-The last example might seem contrived ("Why would I need to call
+The last example might seem contrived ("Why would I call
`Twitter.friends.take(20)` twice?") but it applies to any
[`Enumerable`][enumerable] method you might call on a cursor, including:
`#all?`, `#collect`, `#count`, `#each`, `#inject`, `#max`, `#min`, `#reject`,
`#reverse_each`, `#select`, `#sort`, `#sort_by`, and `#to_a`. In version 4,
each time you called one of those methods, it would perform *n+1* HTTP
-requests. In version 5, it will only perform those HTTP requests the first time
+requests. In version 5, it only performs those HTTP requests the first time any
one of those methods is called. Each subsequent call fetches data from a
[cache][].
@@ -232,34 +232,35 @@ before yielding any data.
Here is a list of the interface changes to `Twitter::Cursor`:
+* `#all` has been replaced by `#to_a`.
+* `#last` has been replaced by `#last?`.
* `#first` has been replaced by `#first?`.
* `#first` now returns the first element in the collection, as prescribed by `Enumerable`.
-* `#last` has been replaced by `#last?`.
-* `#all` has been replaced by `#to_a`.
* `#collection` and its aliases have been removed.
### Search Results
The `Twitter::SearchResults` class has also been redesigned to have an
[`Enumerable`][enumerable] interface. The `#statuses` method and its aliases
(`#collection` and `#results`) have been replaced by `#to_a`. Additionally,
this class no longer inherits from `Twitter::Base`. As a result, the `#[]`
-method has been removed without replacement.
+method has been removed.
### Trend Results
The `Twitter.trends` method now returns an [`Enumerable`][enumerable]
-`Twitter::TrendResults` object instead of an array. This object exposes the
-recency of the trend (via `#as_of`), when the trend started (via
-`#created_at`), and the location of the trend (via `#location`). This
-information was previously unavailable.
+`Twitter::TrendResults` object instead of an array. This object provides
+methods to determinte the recency of the trend (`#as_of`), when the trend
+started (`#created_at`), and the location of the trend (`#location`). This data
+was previously unavailable.
### Geo Results
-The `Twitter.reverse_geocode`, `Twitter.geo_search`, and
+Similarly, the `Twitter.reverse_geocode`, `Twitter.geo_search`, and
`Twitter.similar_places` methods now return an [`Enumerable`][enumerable]
-`Twitter::GeoResults` object instead of an array. This object exposes the token
-to create a new place (via `#token`), which was previously unavailable.
+`Twitter::GeoResults` object instead of an array. This object provides access
+to the token to create a new place (`#token`), which was previously
+unavailable.
-### Users
-The `Twitter::User` object has been cleaned up. The following methods have been
+### Tweets
+The `Twitter::Tweet` object has been cleaned up. The following methods have been
removed:
* `#from_user`
@@ -271,17 +272,14 @@ removed:
* `#profile_image_url`
* `#profile_image_url_https`
-These attributes can be accessed through the `#user` method.
+These attributes can be accessed on the `Twitter::User` object, returned
+through the `#user` method.
### Null Objects
In version 4, methods you would expect to return a `Twitter` object would
-return `nil` if that object was missing. This may have resulted in errors like
-this:
-
- NoMethodError: undefined method for nil:NilClass
-
-To prevent such errors, you may have introduced checks for the truthiness of
-the response, for example:
+return `nil` if that object was missing. This may have resulted in a
+`NoMethodError`. To prevent such errors, you may have introduced checks for the
+truthiness of the response, for example:
```ruby
status = Twitter.status(55709764298092545)
@@ -306,23 +304,18 @@ elsif status.geo?
end
```
-### URL Methods
-`Twitter::List`, `Twitter::Tweet`, and `Twitter::User` objects all have `#url`
-methods, which generate an HTTPS URL to twitter.com. You may specify a
-different protocol by passing it to the `#url` method. For example:
-
-```ruby
-status = Twitter.status(55709764298092545)
-status.url #=> https://twitter.com/sferik/status/55709764298092545
-status.url("http") #=> http://twitter.com/sferik/status/55709764298092545
-```
+### URI Methods
+The `Twitter::List`, `Twitter::Tweet`, and `Twitter::User` objects all have a
+`#uri` method, which returnis an HTTPS URI to twitter.com. This clobbers the
+`Twitter::List#uri` method, which previously returned the list URI's path (not
+a URI).
-`Twitter::User` previously had a method called `#url`, which returned the URL
-to the user's website. This URL is now accessible via the `#website` method.
+These methods are aliased to `#url` for users who prefer that nomenclature.
+`Twitter::User` previously had a `#url` method, which returned the user's
+website. This URI is now available via the `#website` method.
-These methods are aliased to `#uri`, for users who prefer that nomenclature.
-This clobbers the `Twitter::List#uri` method, which previously returned the
-list's path (not a full URI).
+All `#uri` methods now return `URI` objects instead of strings. To convert a
+`URI` object to a string, call `#to_s` on it.
## Configuration
Twitter API v1.1 requires you to authenticate via OAuth, so you'll need to
@@ -525,9 +518,9 @@ recommend [Oj][].
## Statistics
Here are some fun facts about this library:
-* It is implemented in just 2,000 lines of Ruby code
-* With over 5,000 lines of specs, the spec-to-code ratio is about 2.5:1
-* The spec suite contains over 800 examples and runs in about 5 seconds
+* It is implemented in just 2,500 lines of Ruby code
+* With over 6,250 lines of specs, the spec-to-code ratio is about 2.5:1
+* The spec suite contains over 900 examples and runs in about 5 seconds
* It has 100% C0 code coverage (the tests execute every line of
source code at least once)
* It is comprehensive: you can request all documented Twitter REST API
View
@@ -8,7 +8,7 @@
require 'twitter/entity'
require 'twitter/entity/hashtag'
require 'twitter/entity/symbol'
-require 'twitter/entity/url'
+require 'twitter/entity/uri'
require 'twitter/entity/user_mention'
require 'twitter/geo_factory'
require 'twitter/language'
@@ -30,6 +30,7 @@
require 'twitter/trend'
require 'twitter/tweet'
require 'twitter/user'
+require 'uri'
module Twitter
class << self
@@ -38,19 +38,19 @@ def following_followers_of(*args)
cursor_from_response_with_user(:users, Twitter::User, :get, "/users/following_followers_of.json", args)
end
- # Returns Tweets count for a URL
+ # Returns Tweets count for a URI
#
# @note Undocumented
# @rate_limited No
# @authentication Not required
# @return [Integer]
- # @param url [Integer] A URL.
+ # @param uri [String, URI] A URI.
# @param options [Hash] A customizable set of options.
# @example Return Tweet count for http://twitter.com
# Twitter.tweet_count("http://twitter.com/")
- def tweet_count(url, options={})
+ def tweet_count(uri, options={})
connection = Faraday.new("https://cdn.api.twitter.com", @connection_options.merge(:builder => @middleware))
- connection.get("/1/urls/count.json", options.merge(:url => url)).body[:count]
+ connection.get("/1/urls/count.json", options.merge(:url => uri.to_s)).body[:count]
end
end
View
@@ -18,11 +18,11 @@ module Utils
# @return [Integer]
def extract_id(object)
case object
- when Integer
+ when ::Integer
object
- when String
+ when ::String
object.split("/").last.to_i
- when URI
+ when ::URI
object.path.split("/").last.to_i
when Twitter::Identity
object.id
@@ -167,7 +167,7 @@ def merge_user!(hash, user, prefix=nil)
else
hash[[prefix, "screen_name"].compact.join("_").to_sym] = user
end
- when URI
+ when ::URI
hash[[prefix, "screen_name"].compact.join("_").to_sym] = user.path.split("/").last
when Twitter::User
hash[[prefix, "user_id"].compact.join("_").to_sym] = user.id
@@ -201,7 +201,7 @@ def merge_users!(hash, users)
else
screen_names << user
end
- when URI
+ when ::URI
screen_names << user.path.split("/").last
when Twitter::User
user_ids << user.id
View
@@ -137,7 +137,7 @@ def bearer_auth_header
end
def oauth_auth_header(method, path, params={})
- uri = URI(@endpoint + path)
+ uri = ::URI.parse(@endpoint + path)
SimpleOAuth::Header.new(method, uri, params, credentials)
end
end
@@ -4,6 +4,8 @@ module Twitter
class Configuration < Twitter::Base
attr_reader :characters_reserved_per_media, :max_media_per_upload,
:non_username_paths, :photo_size_limit, :short_url_length, :short_url_length_https
+ alias short_uri_length short_url_length
+ alias short_uri_length_https short_url_length_https
# Returns an array of photo sizes
#
View
@@ -0,0 +1,49 @@
+require 'twitter/entity'
+
+module Twitter
+ class Entity
+ class URI < Twitter::Entity
+
+ # @return [URI]
+ def display_uri
+ @display_uri ||= ::URI.parse(@attrs[:display_url]) if display_uri?
+ end
+ alias display_url display_uri
+
+ # @return [Boolean]
+ def display_uri?
+ !!@attrs[:display_url]
+ end
+ alias display_url? display_uri?
+
+ # @return [URI]
+ def expanded_uri
+ @expanded_uri ||= ::URI.parse(@attrs[:expanded_url]) if expanded_uri?
+ end
+ alias expanded_url expanded_uri
+
+ # @return [Boolean]
+ def expanded_uri?
+ !!@attrs[:expanded_url]
+ end
+ alias expanded_url? expanded_uri?
+
+ # @return [URI]
+ def uri
+ @uri ||= ::URI.parse(@attrs[:url]) if uri?
+ end
+ alias url uri
+
+ # @return [Boolean]
+ def uri?
+ !!@attrs[:url]
+ end
+ alias url? uri?
+
+ end
+
+ Uri = URI
+ URL = URI
+ Url = URI
+ end
+end
@@ -1,9 +0,0 @@
-require 'twitter/entity'
-
-module Twitter
- class Entity
- class Url < Twitter::Entity
- attr_reader :display_url, :expanded_url, :url
- end
- end
-end
View
@@ -8,23 +8,23 @@ class List < Twitter::Identity
:mode, :name, :slug, :subscriber_count
object_attr_reader :User, :user
- # @return [String] The URL to the list members.
- def members_url(protocol="https")
- "#{protocol}://twitter.com/#{user.screen_name}/#{slug}/members"
+ # @return [URI] The URI to the list members.
+ def members_uri
+ @members_uri ||= ::URI.parse("https://twitter.com/#{user.screen_name}/#{slug}/members")
end
- alias members_uri members_url
+ alias members_url members_uri
- # @return [String] The URL to the list subscribers.
- def subscribers_url(protocol="https")
- "#{protocol}://twitter.com/#{user.screen_name}/#{slug}/subscribers"
+ # @return [URI] The URI to the list subscribers.
+ def subscribers_uri
+ @subscribers_uri ||= ::URI.parse("https://twitter.com/#{user.screen_name}/#{slug}/subscribers")
end
- alias subscribers_uri subscribers_url
+ alias subscribers_url subscribers_uri
- # @return [String] The URL to the list.
- def url(protocol="https")
- "#{protocol}://twitter.com/#{user.screen_name}/#{slug}"
+ # @return [URI] The URI to the list.
+ def uri
+ @uri ||= ::URI.parse("https://twitter.com/#{user.screen_name}/#{slug}")
end
- alias uri url
+ alias url uri
end
end
Oops, something went wrong.

0 comments on commit 341f68d

Please sign in to comment.