twitter 5.0.0.rc.1 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG.md +7 -1
  3. data/CONTRIBUTING.md +13 -15
  4. data/README.md +53 -33
  5. data/Rakefile +6 -0
  6. data/lib/twitter/arguments.rb +3 -0
  7. data/lib/twitter/base.rb +88 -89
  8. data/lib/twitter/client.rb +5 -41
  9. data/lib/twitter/configuration.rb +4 -5
  10. data/lib/twitter/core_ext/kernel.rb +5 -1
  11. data/lib/twitter/creatable.rb +6 -1
  12. data/lib/twitter/cursor.rb +16 -12
  13. data/lib/twitter/entity/uri.rb +2 -1
  14. data/lib/twitter/enumerable.rb +1 -1
  15. data/lib/twitter/error.rb +42 -39
  16. data/lib/twitter/factory.rb +12 -5
  17. data/lib/twitter/geo.rb +2 -7
  18. data/lib/twitter/geo_factory.rb +11 -7
  19. data/lib/twitter/geo_results.rb +12 -8
  20. data/lib/twitter/identity.rb +4 -12
  21. data/lib/twitter/list.rb +6 -3
  22. data/lib/twitter/media/photo.rb +5 -3
  23. data/lib/twitter/media_factory.rb +11 -7
  24. data/lib/twitter/null_object.rb +4 -3
  25. data/lib/twitter/place.rb +10 -16
  26. data/lib/twitter/profile_banner.rb +4 -5
  27. data/lib/twitter/rate_limit.rb +3 -0
  28. data/lib/twitter/relationship.rb +0 -9
  29. data/lib/twitter/rest/api/direct_messages.rb +9 -6
  30. data/lib/twitter/rest/api/favorites.rb +6 -11
  31. data/lib/twitter/rest/api/friends_and_followers.rb +6 -9
  32. data/lib/twitter/rest/api/lists.rb +27 -20
  33. data/lib/twitter/rest/api/oauth.rb +17 -0
  34. data/lib/twitter/rest/api/places_and_geo.rb +0 -18
  35. data/lib/twitter/rest/api/saved_searches.rb +6 -4
  36. data/lib/twitter/rest/api/suggested_users.rb +2 -2
  37. data/lib/twitter/rest/api/tweets.rb +7 -9
  38. data/lib/twitter/rest/api/users.rb +6 -6
  39. data/lib/twitter/rest/api/utils.rb +44 -17
  40. data/lib/twitter/rest/client.rb +25 -43
  41. data/lib/twitter/rest/response/parse_error_json.rb +15 -0
  42. data/lib/twitter/rest/response/parse_json.rb +5 -1
  43. data/lib/twitter/search_results.rb +12 -8
  44. data/lib/twitter/size.rb +2 -15
  45. data/lib/twitter/streaming/client.rb +23 -11
  46. data/lib/twitter/streaming/event.rb +35 -0
  47. data/lib/twitter/streaming/friend_list.rb +13 -0
  48. data/lib/twitter/streaming/message_parser.rb +18 -0
  49. data/lib/twitter/streaming/response.rb +4 -0
  50. data/lib/twitter/suggestion.rb +5 -10
  51. data/lib/twitter/token.rb +3 -1
  52. data/lib/twitter/trend.rb +2 -7
  53. data/lib/twitter/trend_results.rb +20 -14
  54. data/lib/twitter/tweet.rb +18 -23
  55. data/lib/twitter/user.rb +34 -19
  56. data/lib/twitter/version.rb +1 -1
  57. data/spec/fixtures/request_token.txt +6 -0
  58. data/spec/fixtures/track_streaming_user.json +5 -0
  59. data/spec/twitter/base_spec.rb +0 -16
  60. data/spec/twitter/basic_user_spec.rb +3 -3
  61. data/spec/twitter/cursor_spec.rb +4 -4
  62. data/spec/twitter/direct_message_spec.rb +9 -9
  63. data/spec/twitter/entity/uri_spec.rb +12 -11
  64. data/spec/twitter/geo/point_spec.rb +5 -5
  65. data/spec/twitter/geo/polygon_spec.rb +5 -5
  66. data/spec/twitter/geo_factory_spec.rb +2 -2
  67. data/spec/twitter/geo_spec.rb +6 -6
  68. data/spec/twitter/identifiable_spec.rb +5 -5
  69. data/spec/twitter/list_spec.rb +7 -7
  70. data/spec/twitter/media/photo_spec.rb +19 -18
  71. data/spec/twitter/media_factory_spec.rb +2 -2
  72. data/spec/twitter/null_object_spec.rb +7 -6
  73. data/spec/twitter/oembed_spec.rb +6 -6
  74. data/spec/twitter/place_spec.rb +37 -37
  75. data/spec/twitter/rate_limit_spec.rb +0 -17
  76. data/spec/twitter/relationship_spec.rb +4 -12
  77. data/spec/twitter/rest/api/direct_messages_spec.rb +8 -8
  78. data/spec/twitter/rest/api/friends_and_followers_spec.rb +50 -120
  79. data/spec/twitter/rest/api/geo_spec.rb +0 -14
  80. data/spec/twitter/rest/api/lists_spec.rb +39 -39
  81. data/spec/twitter/rest/api/oauth_spec.rb +15 -4
  82. data/spec/twitter/rest/api/saved_searches_spec.rb +6 -6
  83. data/spec/twitter/rest/api/tweets_spec.rb +6 -6
  84. data/spec/twitter/rest/api/users_spec.rb +4 -4
  85. data/spec/twitter/rest/client_spec.rb +9 -9
  86. data/spec/twitter/saved_search_spec.rb +5 -5
  87. data/spec/twitter/search_results_spec.rb +3 -3
  88. data/spec/twitter/settings_spec.rb +2 -2
  89. data/spec/twitter/size_spec.rb +5 -15
  90. data/spec/twitter/source_user_spec.rb +3 -3
  91. data/spec/twitter/streaming/client_spec.rb +33 -16
  92. data/spec/twitter/streaming/event_spec.rb +45 -0
  93. data/spec/twitter/suggestion_spec.rb +5 -15
  94. data/spec/twitter/target_user_spec.rb +3 -3
  95. data/spec/twitter/token_spec.rb +2 -2
  96. data/spec/twitter/trend_results_spec.rb +6 -6
  97. data/spec/twitter/trend_spec.rb +7 -17
  98. data/spec/twitter/tweet_spec.rb +31 -25
  99. data/spec/twitter/user_spec.rb +16 -16
  100. data/twitter.gemspec +5 -2
  101. metadata +67 -15
  102. metadata.gz.sig +0 -0
data.tar.gz.sig CHANGED
Binary file
@@ -8,12 +8,15 @@
8
8
  * [Remove `Twitter#from_user`](https://github.com/sferik/twitter/commit/d2ae9f1cc1f5224bcdff06cda65fabdf9e7fbcb3)
9
9
  * [Remove `ClientError`, `ServerError`, and `ParserError`](https://github.com/sferik/twitter/commit/72843948d8a6f66345adc254fa91cf1097592b22)
10
10
  * [Remove global configuration](https://github.com/sferik/twitter/commit/239c5a8462fabb8c8ef9ec6a4cdded34561d572d)
11
+ * [Remove ability to configure client with environment variables](https://github.com/sferik/twitter/commit/17e958579f65abf8932841f20058a5989abb994f)
12
+ * [Remove Brittish English aliases](https://github.com/sferik/twitter/commit/572813b373a1c3001ff6c1bb729f092434d17bab)
11
13
  * [Replace `multi_json` with `json`](https://github.com/sferik/twitter/commit/e5fc292fee078567664acf6be4ed31a8ad077780)
12
14
  * [Rename `oauth_token` to `access_token`](https://github.com/sferik/twitter/commit/d360f8015c487c4599460abd0dd0bc7e59a522a3)
13
15
  * [Move `Twitter::Arguments` out of `REST::API` namespace](https://github.com/sferik/twitter/commit/8faa15309d906dd46fccc1b914ea4aa7a5da7c2d)
14
16
  * [Move `Twitter::Client` into `REST` namespace](https://github.com/sferik/twitter/commit/5b8c3fd243227888fc0886b0bf864ecd3a018f99)
15
17
  * [Add `Twitter::Streaming::Client`](https://github.com/sferik/twitter/commit/23afe90aa494229a4389c3e51f753102b34fc551)
16
18
  * [Add `Twitter::Error::AlreadyPosted`](https://github.com/sferik/twitter/commit/e11d2a27dd0dfbbe16c812a81b9c2ab2852a7790)
19
+ * [Add `Twitter::REST::Client#reverse_token`](https://github.com/sferik/twitter/commit/39139c4df35b54b86fae29d1ac83a08f4aa293cd)
17
20
  * [Add `#url` methods to `Twitter::List`, `Twitter::Tweet`, and `Twitter::User`](https://github.com/sferik/twitter/commit/a89ec0f4e81097cc303b6c204e0375eb57ffd614)
18
21
  * [Add `Twitter::Place#contained_within` and `#contained_within?`](https://github.com/sferik/twitter/commit/23cc247bd20001ecbafa544bfb4546bdfc630429)
19
22
  * [Add `Twitter::GeoResults`](https://github.com/sferik/twitter/commit/be1a0a1425a6700267aae0f94a8835bff24dad56)
@@ -23,9 +26,12 @@
23
26
  * [Allow `URI` as argument](https://github.com/sferik/twitter/commit/c207567e674f108e4074e12c9e7343fb74e8a97c)
24
27
  * [Allow `String` in addition to `URI` objects](https://github.com/sferik/twitter/commit/89a46fbd3560109da87d5f87262dcf6bd2a336c6)
25
28
  * [Collection caching](https://github.com/sferik/twitter/commit/d484d7d7d7a0956f9b4fa6791a911ed7c9522cba)
26
- * [Memoize result within `Twitter::Base#new_or_null_object`](https://github.com/sferik/twitter/commit/45dd18a9feadbb56a60cea76424dd466d3e80c5e)
27
29
  * [Implement `Twitter::Cursor#each` without making an extra HTTP request](https://github.com/sferik/twitter/commit/8eeff57f5c6d6ca0a6f1ff5ebc31e652a71fc150)
28
30
  * [Make `Twitter::SearchResults` enumerable](https://github.com/sferik/twitter/commit/d5ce8537164912e79dffc5a054ecd9ae6ecb8075)
31
+ * [Make `Twitter::Base` objects immutable](https://github.com/sferik/twitter/commit/69b1ef7edad32398b778c8449bc3605739a6c59a)
32
+ * [Missing key now raises `KeyError`, not `ArgumentError`](https://github.com/sferik/twitter/commit/f56698caff608527b9f3c2c3dd4c18306589cb3b)
33
+ * [Use `equalizer` instead of manually overwriting #==](https://github.com/sferik/twitter/commit/a7ddf718b119e9c5fc8b87e6784e8c3304707a72)
34
+ * [Give methods more natural names](https://github.com/sferik/twitter/commit/e593194fb7bd689fca561e6334db1e6af622590a)
29
35
  * [Fix `Twitter::SearchResults#rpp` return value](https://github.com/sferik/twitter/commit/28d73200490ac2755c3e68d8d273fbc64a8d7066)
30
36
 
31
37
  4.8.1
@@ -1,25 +1,23 @@
1
1
  ## Contributing
2
2
  In the spirit of [free software][free-sw], **everyone** is encouraged to help
3
- improve this project.
3
+ improve this project. Here are some ways *you* can contribute:
4
4
 
5
5
  [free-sw]: http://www.fsf.org/licensing/essays/free-sw.html
6
6
 
7
- Here are some ways *you* can contribute:
8
-
9
- * by using alpha, beta, and prerelease versions
10
- * by reporting bugs
11
- * by suggesting new features
12
- * by writing or editing documentation
13
- * by writing specifications
14
- * by writing code (**no patch is too small**: fix typos, add comments, clean up
15
- inconsistent whitespace)
16
- * by refactoring code
17
- * by fixing [issues][]
18
- * by reviewing patches
19
- * [financially][pledgie]
7
+ * Use alpha, beta, and pre-release versions.
8
+ * Report bugs.
9
+ * Suggest new features.
10
+ * Write or edit documentation.
11
+ * Write specifications.
12
+ * Write code (**no patch is too small**: fix typos, add comments, clean up
13
+ inconsistent whitespace).
14
+ * Refactor code.
15
+ * Fix [issues][].
16
+ * Review patches.
17
+ * Financially pledge using [Pledgie][].
20
18
 
21
19
  [issues]: https://github.com/sferik/twitter/issues
22
- [pledgie]: http://pledgie.com/campaigns/18388
20
+ [Pledgie]: http://pledgie.com/campaigns/18388
23
21
 
24
22
  ## Submitting an Issue
25
23
  We use the [GitHub issue tracker][issues] to track bugs and features. Before
data/README.md CHANGED
@@ -74,17 +74,6 @@ client = Twitter::REST::Client.new do |config|
74
74
  end
75
75
  ```
76
76
 
77
- Alternately, you can configure a `Twitter::REST::Client` piecemeal, after it
78
- has been initialized, if that better suits your application:
79
-
80
- ```ruby
81
- client = Twitter::REST::Client.new
82
- client.consumer_key = "YOUR_CONSUMER_KEY"
83
- client.consumer_secret = "YOUR_CONSUMER_SECRET"
84
- client.access_token = "YOUR_ACCESS_TOKEN"
85
- client.access_token_secret = "YOUR_ACCESS_SECRET"
86
- ```
87
-
88
77
  Note: `oauth_token` has been renamed to `access_token` and `oauth_token_secret`
89
78
  is now `access_token_secret` to conform to the terminology used in Twitter's
90
79
  developer documentation.
@@ -119,7 +108,7 @@ and [Tony Arcieri][tarcieri] for helping to develop this feature.
119
108
  **Configuration works just like `Twitter::REST::Client`**
120
109
 
121
110
  ```ruby
122
- client = Twitter::Streaming::Client.new do
111
+ client = Twitter::Streaming::Client.new do |config|
123
112
  config.consumer_key = "YOUR_CONSUMER_KEY"
124
113
  config.consumer_secret = "YOUR_CONSUMER_SECRET"
125
114
  config.access_token = "YOUR_ACCESS_TOKEN"
@@ -144,17 +133,19 @@ client.sample do |tweet|
144
133
  end
145
134
  ```
146
135
 
147
- **Stream tweets for the authenticated user**
136
+ **Stream tweets, events and direct messages for the authenticated user**
148
137
 
149
138
  ```ruby
150
- client.user do |tweet|
151
- puts tweet.text
139
+ client.user do |message|
140
+ puts message
152
141
  end
153
142
  ```
154
143
 
155
- Currently, this library will only stream tweets. The goal is to eventually
156
- handle all [streaming message types][messages]. Patches that add support for a
157
- new message type would be appreciated.
144
+ `message` can be one of
145
+ + Twitter::Tweet
146
+ + Twitter::DirectMessage
147
+ + Twitter::Streaming::Event
148
+ + Twitter::Streaming::FriendList
158
149
 
159
150
  [messages]: https://dev.twitter.com/docs/streaming-apis/messages
160
151
 
@@ -250,7 +241,7 @@ simplicity and performance.
250
241
  </tr>
251
242
  <tr>
252
243
  <td>
253
- Collect your 20 most recent friends (twice).
244
+ Collect your 20 most recent friends twice.
254
245
  </td>
255
246
  <td>
256
247
  <pre><code lang="ruby">friends = client.friends
@@ -345,7 +336,7 @@ removed:
345
336
  * `#profile_image_url`
346
337
  * `#profile_image_url_https`
347
338
 
348
- These attributes can be accessed on the `Twitter::User` object, returned
339
+ These attributes can be accessed via the `Twitter::User` object, returned
349
340
  through the `#user` method.
350
341
 
351
342
  ### Users
@@ -354,8 +345,8 @@ been removed:
354
345
 
355
346
  * `#favorite_count` (use `#favorites_count`)
356
347
  * `#favoriters_count` (use `#favorites_count`)
357
- * `#favourite_count` (use `#favourites_count`)
358
- * `#favouriters_count` (use `#favourites_count`)
348
+ * `#favourite_count` (use `#favorites_count`)
349
+ * `#favouriters_count` (use `#favorites_count`)
359
350
  * `#follower_count` (use `#followers_count`)
360
351
  * `#friend_count` (use `#friends_count`)
361
352
  * `#status_count` (use `#statuses_count`)
@@ -364,6 +355,30 @@ been removed:
364
355
  * `#updates_count` (use `#tweets_count`)
365
356
  * `#translator` (use `#translator?`)
366
357
 
358
+ ### Remove British English aliases
359
+ Earlier versions of this library aliased `favourites` to `favorites`. These
360
+ aliases have been removed. Ruby is implemented in American English. The
361
+ `initialize` method is spelled with a "z", not an "s", and Ruby provides no
362
+ alias. Likewise, this library does not provide aliases for Commonwealthers.
363
+ Merica. :us:
364
+
365
+ ### More natural method names
366
+ All create, destroy, add, and remove methods have been renamed to put the verb
367
+ at the beginning:
368
+
369
+ * `#direct_message_create` is now `#create_direct_message`
370
+ * `#direct_message_destroy` is now `#destroy_direct_message`
371
+ * `#list_create` is now `#create_list`
372
+ * `#list_destroy` is now `#destroy_list`
373
+ * `#list_remove_member` is now `#remove_list_member`
374
+ * `#list_remove_members` is now `#remove_list_members`
375
+ * `#list_add_member` is now `#add_list_member`
376
+ * `#list_add_members` is now `#add_list_members`
377
+ * `#lists_owned` is now `#owned_list`
378
+ * `#saved_search_create` is now `#create_saved_search`
379
+ * `#saved_search_destroy` is now `#destroy_saved_search`
380
+ * `#status_destroy` is now `#destroy_status`
381
+
367
382
  ### Errors
368
383
  The `Twitter::Error::ClientError` and `Twitter::Error::ServerError` class
369
384
  hierarchy has been removed. All errors now inherit directly from
@@ -432,20 +447,13 @@ You can pass configuration options as a block to `Twitter::REST::Client.new`.
432
447
 
433
448
  ```ruby
434
449
  client = Twitter::REST::Client.new do |config|
435
- config.consumer_key = YOUR_APP_CONSUMER_KEY
436
- config.consumer_secret = YOUR_APP_CONSUMER_SECRET
437
- config.access_token = A_USER_ACCESS_TOKEN
438
- config.access_token_secret = A_USER_ACCESS_SECRET
450
+ config.consumer_key = "YOUR_CONSUMER_KEY"
451
+ config.consumer_secret = "YOUR_CONSUMER_SECRET"
452
+ config.access_token = "YOUR_ACCESS_TOKEN"
453
+ config.access_token_secret = "YOUR_ACCESS_SECRET"
439
454
  end
440
455
  ```
441
456
 
442
- Alternately, you can set the following environment variables:
443
-
444
- TWITTER_CONSUMER_KEY
445
- TWITTER_CONSUMER_SECRET
446
- TWITTER_ACCESS_TOKEN
447
- TWITTER_ACCESS_TOKEN_SECRET
448
-
449
457
  After configuration, requests can be made like so:
450
458
 
451
459
  ```ruby
@@ -548,6 +556,18 @@ client.search("#ruby -rt", :lang => "ja").first.text
548
556
  ```
549
557
  For more usage examples, please see the full [documentation][].
550
558
 
559
+ ## Object Graph
560
+
561
+ ![Entity-relationship diagram][erd]
562
+
563
+ [erd]: https://github.com/sferik/twitter/raw/master/etc/erd.png "Entity-relationship diagram"
564
+
565
+ This entity-relationship diagram is generated programatically. If you add or
566
+ remove any Twitter objects, please regenerate the ERD with the following
567
+ command:
568
+
569
+ bundle exec rake erd
570
+
551
571
  ## Supported Ruby Versions
552
572
  This library aims to support and is [tested against][travis] the following Ruby
553
573
  implementations:
data/Rakefile CHANGED
@@ -7,5 +7,11 @@ RSpec::Core::RakeTask.new(:spec)
7
7
  task :test => :spec
8
8
  task :default => :spec
9
9
 
10
+ task :erd do
11
+ `bundle exec ruby ./etc/erd.rb > ./etc/erd.dot`
12
+ `dot -Tpng ./etc/erd.dot -o ./etc/erd.png`
13
+ `open ./etc/erd.png`
14
+ end
15
+
10
16
  require 'yard'
11
17
  YARD::Rake::YardocTask.new
@@ -2,6 +2,9 @@ module Twitter
2
2
  class Arguments < Array
3
3
  attr_reader :options
4
4
 
5
+ # Initializes a new Arguments object
6
+ #
7
+ # @return [Twitter::Arguments]
5
8
  def initialize(args)
6
9
  @options = args.last.is_a?(::Hash) ? args.pop : {}
7
10
  super(args)
@@ -1,106 +1,116 @@
1
1
  require 'forwardable'
2
+ require 'memoizable'
2
3
  require 'twitter/null_object'
3
4
  require 'uri'
4
5
 
5
6
  module Twitter
6
7
  class Base
7
8
  extend Forwardable
9
+ include Memoizable
8
10
  attr_reader :attrs
9
11
  alias to_h attrs
10
12
  alias to_hash attrs
11
13
  alias to_hsh attrs
12
- def_delegators :attrs, :delete, :update
13
14
 
14
- # Define methods that retrieve the value from attributes
15
- #
16
- # @param attrs [Array, Symbol]
17
- def self.attr_reader(*attrs)
18
- attrs.each do |attr|
19
- define_attribute_method(attr)
20
- define_predicate_method(attr)
15
+ class << self
16
+
17
+ # Construct an object from a response hash
18
+ #
19
+ # @param response [Hash]
20
+ # @return [Twitter::Base]
21
+ def from_response(response={})
22
+ new(response[:body])
21
23
  end
22
- end
23
24
 
24
- # Define object methods from attributes
25
- #
26
- # @param klass [Symbol]
27
- # @param key1 [Symbol]
28
- # @param key2 [Symbol]
29
- def self.object_attr_reader(klass, key1, key2=nil)
30
- define_attribute_method(key1, klass, key2)
31
- define_predicate_method(key1)
32
- end
25
+ # Define methods that retrieve the value from attributes
26
+ #
27
+ # @param attrs [Array, Symbol]
28
+ def attr_reader(*attrs)
29
+ attrs.each do |attr|
30
+ define_attribute_method(attr)
31
+ define_predicate_method(attr)
32
+ end
33
+ end
33
34
 
34
- # Define URI methods from attributes
35
- #
36
- # @param attrs [Array, Symbol]
37
- def self.uri_attr_reader(*attrs)
38
- attrs.each do |uri_key|
39
- array = uri_key.to_s.split("_")
40
- index = array.index("uri")
41
- array[index] = "url"
42
- url_key = array.join("_").to_sym
43
- define_uri_method(uri_key, url_key)
44
- define_predicate_method(uri_key, url_key)
45
- alias_method(url_key, uri_key)
46
- alias_method("#{url_key}?", "#{uri_key}?")
35
+ # Define object methods from attributes
36
+ #
37
+ # @param klass [Symbol]
38
+ # @param key1 [Symbol]
39
+ # @param key2 [Symbol]
40
+ def object_attr_reader(klass, key1, key2=nil)
41
+ define_attribute_method(key1, klass, key2)
42
+ define_predicate_method(key1)
47
43
  end
48
- end
49
44
 
50
- # Dynamically define a method for a URI
51
- #
52
- # @param key1 [Symbol]
53
- # @param key2 [Symbol]
54
- def self.define_uri_method(key1, key2)
55
- define_method(key1) do
56
- memoize(key1) do
57
- ::URI.parse(@attrs[key2]) if @attrs[key2]
45
+ # Define URI methods from attributes
46
+ #
47
+ # @param attrs [Array, Symbol]
48
+ def uri_attr_reader(*attrs)
49
+ attrs.each do |uri_key|
50
+ array = uri_key.to_s.split("_")
51
+ index = array.index("uri")
52
+ array[index] = "url"
53
+ url_key = array.join("_").to_sym
54
+ define_uri_method(uri_key, url_key)
55
+ alias_method(url_key, uri_key)
56
+ define_predicate_method(uri_key, url_key)
57
+ alias_method(:"#{url_key}?", :"#{uri_key}?")
58
58
  end
59
59
  end
60
- end
61
60
 
62
- # Dynamically define a method for an attribute
63
- #
64
- # @param key1 [Symbol]
65
- # @param klass [Symbol]
66
- # @param key2 [Symbol]
67
- def self.define_attribute_method(key1, klass=nil, key2=nil)
68
- define_method(key1) do
69
- memoize(key1) do
61
+ # Define display_uri attribute methods
62
+ def display_uri_attr_reader
63
+ define_attribute_method(:display_url)
64
+ alias_method(:display_uri, :display_url)
65
+ define_predicate_method(:display_uri, :display_url)
66
+ alias_method(:display_url?, :display_uri?)
67
+ end
68
+
69
+ private
70
+
71
+ # Dynamically define a method for a URI
72
+ #
73
+ # @param key1 [Symbol]
74
+ # @param key2 [Symbol]
75
+ def define_uri_method(key1, key2)
76
+ define_method(key1) do ||
77
+ URI.parse(@attrs[key2]) if @attrs[key2]
78
+ end
79
+ memoize(key1)
80
+ end
81
+
82
+ # Dynamically define a method for an attribute
83
+ #
84
+ # @param key1 [Symbol]
85
+ # @param klass [Symbol]
86
+ # @param key2 [Symbol]
87
+ def define_attribute_method(key1, klass=nil, key2=nil)
88
+ define_method(key1) do ||
70
89
  if klass.nil?
71
90
  @attrs[key1]
72
91
  else
73
92
  if @attrs[key1]
74
- if key2.nil?
75
- Twitter.const_get(klass).new(@attrs[key1])
76
- else
77
- attrs = @attrs.dup
78
- value = attrs.delete(key1)
79
- Twitter.const_get(klass).new(value.update(key2 => attrs))
80
- end
93
+ attrs = attrs_for_object(key1, key2)
94
+ Twitter.const_get(klass).new(attrs)
81
95
  else
82
- Twitter::NullObject.instance
96
+ NullObject.new
83
97
  end
84
98
  end
85
99
  end
100
+ memoize(key1)
86
101
  end
87
- end
88
102
 
89
- # Dynamically define a predicate method for an attribute
90
- #
91
- # @param key [Symbol]
92
- def self.define_predicate_method(key1, key2=key1)
93
- define_method(:"#{key1}?") do
94
- !!@attrs[key2]
103
+ # Dynamically define a predicate method for an attribute
104
+ #
105
+ # @param key1 [Symbol]
106
+ # @param key2 [Symbol]
107
+ def define_predicate_method(key1, key2=key1)
108
+ define_method(:"#{key1}?") do ||
109
+ !!@attrs[key2]
110
+ end
111
+ memoize(:"#{key1}?")
95
112
  end
96
- end
97
113
 
98
- # Construct an object from a response hash
99
- #
100
- # @param response [Hash]
101
- # @return [Twitter::Base]
102
- def self.from_response(response={})
103
- new(response[:body])
104
114
  end
105
115
 
106
116
  # Initializes a new object
@@ -120,26 +130,15 @@ module Twitter
120
130
  nil
121
131
  end
122
132
 
123
- def memoize(key, &block)
124
- ivar = :"@#{key}"
125
- return instance_variable_get(ivar) if instance_variable_defined?(ivar)
126
- result = block.call
127
- instance_variable_set(ivar, result)
128
- end
129
-
130
133
  private
131
134
 
132
- # @param attr [Symbol]
133
- # @param other [Twitter::Base]
134
- # @return [Boolean]
135
- def attr_equal(attr, other)
136
- self.class == other.class && !other.send(attr.to_sym).nil? && send(attr.to_sym) == other.send(attr.to_sym)
137
- end
138
-
139
- # @param other [Twitter::Base]
140
- # @return [Boolean]
141
- def attrs_equal(other)
142
- self.class == other.class && !other.attrs.empty? && attrs == other.attrs
135
+ def attrs_for_object(key1, key2=nil)
136
+ if key2.nil?
137
+ @attrs[key1]
138
+ else
139
+ attrs = @attrs.dup
140
+ attrs.delete(key1).merge(key2 => attrs)
141
+ end
143
142
  end
144
143
 
145
144
  end