worth_watching 0.0.4 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e35fd2e5e42565ad5098cfba862e9416a45201d1
4
- data.tar.gz: d6bb20f5f5d8ce4b1a2282057c1e937df33930cc
3
+ metadata.gz: 048abc5a75b5f585a50481cab76c699ec622a4a6
4
+ data.tar.gz: 7ed6a1134722d026b11ee25d54db2338a7c19e1a
5
5
  SHA512:
6
- metadata.gz: 67b77513e14d79377de17e6538500ca0f9d8061afdc975f4912f6f5474f185aa448ff5b803c9870b7b73f0a91529f59c7466cbed15a8abf965d52a178a1c83f9
7
- data.tar.gz: 185fd25dbff8bc88d45a93aa8b082c53d299daf9d564d2a0ddcbfc2ef0839562e922d9765aeec8d0e373ab3063eaccb0cf2a7b0b2359ebdd451ddcef62a71393
6
+ metadata.gz: 5903062650b35280dd7373b4ea9c8079936809ca8f554f92282599eac15dd8db00d20108021123c634fd8f14cd0b99432de91e42d0455b9f364fb7ffcba8ef09
7
+ data.tar.gz: 983f743ff6b0dd3e0ad3b640ea09c7874fca898305d3356b18249419e06f6d9eb2509566a4db123239e28725300d3fa9a5560ecdb95c4cdf4784100c6c73e679
data/.gitignore CHANGED
@@ -16,4 +16,6 @@ test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
18
  config/config.yml
19
- spec/vcr_cassettes/
19
+ spec/vcr_cassettes/
20
+ todo.txt
21
+ config.yaml
data/README.md CHANGED
@@ -1,9 +1,43 @@
1
- # WorthWatching
1
+ ## WorthWatching
2
2
 
3
- WorthWatching is a gem that allows you to aggregate movie review data from a
3
+ WorthWatching is a gem that aggregates movie review data from a
4
4
  number of different sources.
5
5
 
6
- Current supported sources are Rotten Tomatoes, IMDb and Metacritic.
6
+ Currently, the supported info sources are [Rotten Tomatoes](http://rottentomatoes.com), [IMDb](http://imdb.com) and [Metacritic](http://metacritic.com).
7
+
8
+ ### What info does WorthWatching aggregate?
9
+
10
+ The gem was designed to retrieve the overall rating form each source. But it also
11
+ retrieves extra info that may be useful.
12
+
13
+ The full list of info retrieved for each movie:
14
+
15
+ - title
16
+ - plot (no spoilers, just the general description)
17
+ - director
18
+ - cast
19
+ - genre
20
+ - release date
21
+ - **Rotten Tomatoes rating (n out of 100)**
22
+ - **IMDb rating (n out of 10)**
23
+ - **Metacritic rating (n out of 100)**
24
+ - Rotten Tomatoes movie URL
25
+ - IMDb movie URL
26
+ - Metacritic movie URL
27
+ - Rotten Tomaotes movie ID
28
+ - IMDb movie ID
29
+ - poster image URL
30
+ - reviews
31
+
32
+ Note that the success of the aggregation process is entirely dependent on knowing
33
+ the Rotten Tomatoes ID *first*.
34
+
35
+ However, you can use the `search_by_title` method to first search for a movie.
36
+ The search results include the Rotten Tomatoes ID, which you can then use aggregate movie info as
37
+ usual with the `aggregate_movie` method.
38
+
39
+ If you would like to know why this is the case, or are just interested in how aggregation happens,
40
+ [read here]() for some extra information.
7
41
 
8
42
  ## Installation
9
43
 
@@ -21,52 +55,223 @@ Or install it yourself as:
21
55
 
22
56
  ## Setup
23
57
 
24
- * Apply for the required API keys. You will need a [Rotten Tomatoes API Key](http://developer.rottentomatoes.com/) and a [TMDB API key](http://docs.themoviedb.apiary.io/).
58
+ - Apply for the required API keys. You will need a [Rotten Tomatoes API Key](http://developer.rottentomatoes.com/) and a [TMDB API key](http://docs.themoviedb.apiary.io/).
25
59
 
26
- * Fill in the details of your API keys in config/config.yml
27
60
 
28
61
  ## Usage
29
62
 
63
+ ### Getting started
64
+ ```ruby
65
+ # Create a new aggregator, passing in your API keys
66
+ movie_aggregator = WorthWatching::Aggregator.new("rotten_tomato_api_key", "tmdb_api_key")
67
+ ```
68
+
69
+ ### Searching for a movie by title
70
+
71
+ Pass the title of the movie, and the maximum number of results to return
72
+
73
+ ```ruby
74
+ # Search for movies by title. Returns an array of hashes, each hash representing
75
+ # a movie in the search result
76
+ # Note that it returns the Rotten Tomatoes ID for each movie, which is vital to aggregation
77
+ movie_aggregator.search_by_title("the godfather", 4)
78
+ => [{:title=>"The Godfather", :rt_id=>"12911", :year=>"1972"},
79
+ {:title=>"The Godfather, Part II", :rt_id=>"12926", :year=>"1974"},
80
+ {:title=>"The Godfather, Part III", :rt_id=>"13476", :year=>"1990"},
81
+ {:title=>"The Godfather of Green Bay", :rt_id=>"341816359", :year=>"2005"}]
82
+ ```
83
+
84
+ ### Retrieving info for a single movie
30
85
  ```ruby
31
- # Create a new aggregator
32
- movie_aggregator = WorthWatching::Aggregator.new("rotten_tomatoes_api_key", "tmdb_api_key")
33
86
 
34
- # Search for movie by Rotten Tomatoes ID
35
- toy_story_3 = movie_aggregator.movie_info('770672122')
87
+ # Pass the movie's Rotten Tomatoes ID
88
+ toy_story_3 = movie_aggregator.aggregate_movie("770672122")
36
89
 
37
- # We now have a Movie object and can access many attributes, including rating information
38
- toy_story_3.title
90
+ # We now have a Movie object and can access many attributes...
91
+ toy_story_3.title
39
92
  => "Toy Story 3"
93
+ ```
40
94
 
95
+ ### Rating Info
96
+ ```ruby
97
+ # Access ratings individually
41
98
  toy_story_3.rt_rating
42
99
  => 99
43
100
 
44
101
  toy_story_3.imdb_rating
45
- => 85
102
+ => 8.5
46
103
 
47
104
  toy_story_3.metacritic_rating
48
105
  => 92
49
106
 
107
+ # Get the rating summary as a string
108
+ puts toy_story_3.rating_summary
109
+ => "Rotten Tomatoes rating: 99
110
+ IMDB rating: 8.5
111
+ Metacritic rating: 92"
112
+ ```
113
+ ### General movie info
114
+ ```ruby
115
+ toy_story_3.plot
116
+ => "Pixar returns to their first success with Toy Story 3. The movie begins with
117
+ Andy leaving for college and donating his beloved toys -- including Woody
118
+ (Tom Hanks) and Buzz (Tim Allen) -- to a daycare. While the crew meets new friends,
119
+ including Ken (Michael Keaton), they soon grow to hate their new surroundings and
120
+ plan an escape. The film was directed by Lee Unkrich from a script co-authored by
121
+ Little Miss Sunshine scribe Michael Arndt. ~ Perry Seibert, Rovi"
122
+
123
+ toy_story_3.director
124
+ => "Lee Unkrich"
125
+
126
+ toy_story_3.cast
127
+ => "Tom Hanks, Tim Allen, Joan Cusack, Ned Beatty"
128
+
129
+ toy_story_3.genre
130
+ => "Animation"
131
+
132
+ toy_story_3.release_date
133
+ => #<Date: 2010-06-18 ((2455366j,0s,0n),+0s,2299161j)>
134
+
135
+ # Rotten Tomatoes URL
136
+ toy_story_3.rt_url
137
+ => "http://www.rottentomatoes.com/m/toy_story_3/"
138
+
139
+ toy_story_3.imdb_url
140
+ => "http://www.imdb.com/title/tt0435761/"
141
+
142
+ toy_story_3.metacritic_url
143
+ => "http://www.metacritic.com/movie/toy-story-3"
144
+
145
+ # Rotten Tomatoes ID
146
+ toy_story_3.rt_id
147
+ => "770672122"
148
+
149
+ toy_story_3.imdb_id
150
+ => "0435761"
151
+
152
+ toy_story_3.poster
153
+ => "http://cf2.imgobject.com/t/p/original/tOwAAVeL1p3ls9dhOBo45ElodU3.jpg"
50
154
 
51
- # Get a short 5-film list of movies currently on release
52
- recent_movies = movie_aggregator.in_cinemas(5)
155
+ # Get a general summary
156
+ puts toy_story_3.summary
157
+ => "Toy Story 3
158
+ ------------------------------------------------------------
159
+ Released: 18 Jun 2010
160
+ ------------------------------------------------------------
161
+ Pixar returns to their first success with Toy Story 3. The movie begins with Andy
162
+ leaving for college and donating his beloved toys -- including Woody (Tom Hanks)
163
+ and Buzz (Tim Allen) -- to a daycare. While the crew meets new friends,
164
+ including Ken (Michael Keaton), they soon grow to hate their new surroundings
165
+ and plan an escape. The film was directed by Lee Unkrich from a script
166
+ co-authored by Little Miss Sunshine scribe Michael Arndt. ~ Perry Seibert, Rovi
167
+ ------------------------------------------------------------
168
+ Cast: Tom Hanks, Tim Allen, Joan Cusack, Ned Beatty
169
+ ------------------------------------------------------------
170
+ Rotten Tomatoes rating: 99
171
+ IMDB rating: 8.5
172
+ Metacritic rating: 92"
173
+ ```
174
+
175
+ ### Movie reviews
176
+ Sourced from Rotten Tomatoes. ``Movie`` object has an instance variable ``reviews``,
177
+ which is an array of ``WrittenReview`` objects.
178
+
179
+ ```ruby
180
+ # Get the first review
181
+ a_review = toy_story_3.reviews.last
182
+ a_review.author
183
+ => "Ailsa Caine"
184
+
185
+ a_review.date
186
+ => #<Date: 2010-07-22 ((2455400j,0s,0n),+0s,2299161j)>
187
+
188
+ a_review.quote
189
+ => "By [Pixar's] high standards this isn't the best, but by anyone else's, it's close to perfection."
190
+
191
+ # Reviews are those collated by Rotten Tomatoes, where the review scale is binary ("fresh" or "rotten")
192
+ a_review.rating
193
+ => "fresh"
194
+
195
+ # The review's original score (not always available)
196
+ a_review.original_score
197
+ => "4/5"
53
198
 
54
- iron_man = recent_movies.first
199
+ a_review.source
200
+ => "Little White Lies"
55
201
 
56
- iron_man.title
57
- => "Iron Man 3"
202
+ a_review.link
203
+ => "http://www.littlewhitelies.co.uk/theatrical-reviews/toy-story-3/"
58
204
 
59
- critic_review = iron_man.reviews.first
60
- critic_review.quote
61
- => "The trouble is that, as the plot quickens, any cleverness withdraws, to make
62
- way for the firecrackers of the climax. That is not Black's forte, and his
63
- movie duly slumps into a mess."
205
+ # Convenience method to summarise the review as a string
206
+ a_review.to_s
207
+ => "Ailsa Caine wrote on 2010-07-22 : By [Pixar's] high standards this isn't the best, but by anyone else's, it's close to perfection.
208
+ Rating: 4/5"
64
209
  ```
65
210
 
66
- ## Contributing
211
+ ### Aggregating a list of movies
212
+ The Rotten Tomatoes API supports a number of pre-defined lists for both cinema/theater
213
+ releases and DVD releases. For example, if you want to aggregate info for each movie
214
+ on the Box Office list (best performing cinema releases), WorthWatching supports this.
215
+
216
+ Pass the name of the list you would like to process (as a Symbol), the country code
217
+ (ISO 3166-1 alpha-2) of the country you would like info to be localised to (as a Symbol),
218
+ and finally, the maximum number of movies on the list you are interested in.
219
+
220
+ The available lists mirror those available through the Rotten Tomatoes API.
221
+
222
+ They are:
223
+
224
+ - ``:box_office`` - top box office earning movies, sorted by most recent weekend gross
225
+ ticket sales
226
+ - ``:in_theaters`` - movies currently in theaters/cinemas
227
+ - ``:opening`` - current opening movies in the theaters/cinema
228
+ - ``:upcoming`` - upcoming movies in theaters/cinema
229
+ - ``:top_rentals`` - top DVD rentals
230
+ - ``:current_releases`` - current DVD releases
231
+ - ``:new_releases`` - new DVD releases
232
+ - ``:upcoming_dvd`` - upcoming DVD releases
233
+
234
+ **Be careful using this feature! Since WorthWatching will aggregate info for each movie on the list,
235
+ there is the potential to make a significant number of API calls through repeated use.**
236
+
237
+ **The Rotten Tomatoes API
238
+ does have rate limits (as of March 2014: 5 calls a second, 10,000 calls a day)**
239
+
240
+
241
+ ```ruby
242
+
243
+ # Aggregate the top 4 box office movies in the UK
244
+ top_movies = movie_aggregator.aggregate_list(:box_office, :uk, 4)
245
+
246
+ # Or the top 6 releases on DVD in the US
247
+ top_dvds = movie_aggregator.aggregate_list(:top_rentals, :us, 6)
248
+
249
+ # The above list-based methods return an array of Movie objects
250
+ number_1_movie = top_movies.first
251
+
252
+ number_1_movie.title
253
+ => "Captain America: The Winter Soldier"
254
+
255
+ number_1_movie.metacritic_rating
256
+ => 71
257
+ ```
258
+
259
+ ### Why is the returned list empty?
260
+
261
+ This may be because some movies do not have the minimum amount of data available
262
+ in order to aggregate their rating info, and are therefore 'discarded' during the aggregation
263
+ process.
264
+
265
+ If a movie's IMDb ID is not available through the Rotten Tomatoes API, rating info
266
+ cannot be retrieved.
267
+
268
+ During testing I also noticed that movies with no available release date were likely
269
+ to be very obscure and not have any rating info associated with them either. This is
270
+ the other criteria for a movie being discarded.
271
+
272
+ This only tends to happen with very small release independent films, particularly foreign ones.
273
+
274
+ The lists where the above is most likely are ``:upcoming`` and ``:upcoming_dvd``, since they
275
+ contain movies that probably don't have any rating info yet, as they haven't been released.
67
276
 
68
- 1. Fork it
69
- 2. Create your feature branch (`git checkout -b my-new-feature`)
70
- 3. Commit your changes (`git commit -am 'Add some feature'`)
71
- 4. Push to the branch (`git push origin my-new-feature`)
72
- 5. Create new Pull Request
277
+ The opposite is true for lists like ``:box_office`` and ``top_rentals``.
@@ -1,11 +1,13 @@
1
- require 'httparty'
2
1
  require 'nokogiri'
3
2
  require 'open-uri'
3
+ require 'typhoeus'
4
+ require 'json'
4
5
 
5
6
  module WorthWatching
6
7
  class Aggregator
7
8
 
8
9
  attr_accessor :rt_api_key, :tmdb_api_key
10
+ attr_reader :movie
9
11
 
10
12
  RT_API_BASE_URL = 'http://api.rottentomatoes.com/api/public/v1.0'
11
13
  TMDB_API_BASE_URL = 'http://api.themoviedb.org/3'
@@ -17,152 +19,129 @@ module WorthWatching
17
19
  end
18
20
 
19
21
  # Retrieve the details of a specific movie using its IMDB ID
22
+ #
20
23
  # @param rt_id [String] the Rotten Tomatoes ID of the movie
21
24
  # @return [Movie] a Movie object representing the movie
22
- def movie_info(rt_id)
23
- uri = "#{RT_API_BASE_URL}/movies/#{rt_id}.json?apikey=#{rt_api_key}"
24
- movie_hash = HTTParty.get(uri)
25
+ def aggregate_movie(rt_id)
26
+ uri = "#{RT_API_BASE_URL}/movies/#{rt_id}.json?apikey=#{@rt_api_key}"
27
+ movie_hash = JSON.parse(Typhoeus.get(uri).body)
25
28
 
26
- aggregate(Movie.new(movie_hash))
29
+ @movie = Movie.new(movie_hash)
30
+ aggregate
27
31
  end
28
32
 
29
- # Retrieve a list of movies that are currently in cinemas
30
- # @param result_limit [Integer] the maximum number of results to return
31
- # @return [Array] an Array of Movie objects
32
- def in_cinemas(result_limit, type)
33
-
34
- case type
35
- when :cinema
36
- uri = "#{RT_API_BASE_URL}/lists/movies/in_theaters.json?page_limit=#{result_limit}"\
37
- "&page=1&country=uk&apikey=#{rt_api_key}"
38
- when :dvd
39
- uri = "#{RT_API_BASE_URL}/lists/dvds/top_rentals.json?page_limit=#{result_limit}"\
40
- "&page=1&country=uk&apikey=#{rt_api_key}"
33
+ # Retrieve a list of movies, then aggregate info for each one
34
+ #
35
+ # @param list_name[Symbol] the name of the Rotten Tomato list. Possible values: :box_office,
36
+ # :in_theaters, :opening, :upcoming, :top_rentals, :current_releases, :new_releases, :upcoming_dvd
37
+ # @param country [Symbol] Localised data for the selected country (ISO 3166-1 alpha-2)
38
+ # @param result_limit [Integer] the max number of movies to return in the list
39
+ # @return [Array] an array of Movie objects
40
+ def aggregate_list(list_name, country, result_limit)
41
+ case list_name
42
+
43
+ # Build the appropriate URI based on the list name.
44
+ # Some enpoints use 'limit' to specify max results to return, some use 'page_limit'.
45
+ # Pass both to make the code simpler
46
+ when :box_office, :in_theaters, :opening, :upcoming
47
+ uri = "#{RT_API_BASE_URL}/lists/movies/#{list_name.to_s}.json?limit=#{result_limit}"\
48
+ "&page_limit=#{result_limit}&page=1&country=#{country.to_s}&apikey=#{@rt_api_key}"
49
+ when :top_rentals, :current_releases, :new_releases, :upcoming_dvd
50
+
51
+ # The API endpoint uses 'upcoming' for both DVD and cinema releases
52
+ # Need to avoid this clash by using ':upcoming_dvd' as possible method param,
53
+ # but change back when building the URI
54
+ list_name = :upcoming if list_name == :upcoming_dvd
55
+ uri = "#{RT_API_BASE_URL}/lists/dvds/#{list_name.to_s}.json?limit=#{result_limit}"\
56
+ "&page_limit=#{result_limit}&page=1&country=#{country.to_s}&apikey=#{@rt_api_key}"
41
57
  end
42
58
 
43
- movie_list = HTTParty.get(uri)
44
- movie_list = movie_list["movies"]
45
- in_theaters = []
46
-
47
- movie_list.each do |movie|
48
- if enough_info?(movie)
49
- movie = movie_info(movie['id'])
50
- in_theaters << movie
51
- end
52
- end
53
- Aggregator.clean_up(in_theaters)
54
- return in_theaters
59
+ get_movie_list(uri)
55
60
  end
56
61
 
57
- # Aggregates exta information about a movie that cannot be derived directly from the
58
- # Rotten Tomatoes API e.g IMDb/Metacritic rating, HQ posters
59
- # @param movie [Movie] the movie to aggregate information for
60
- # @return [Movie] the movie passed in with aggregated info completed
61
- def aggregate(movie)
62
- extra_info = get_extra_info_via_omdb(movie.imdb_id)
62
+ # Search for movies using a query string. Returns a max of 4 results
63
+ #
64
+ # @param movie_title [String] the title of the movie to search for
65
+ # @param result_limit [Integer] the max number of results to return
66
+ # @return [Array, false] an array containing hashes represting each movie in the search results, or
67
+ # false if no results are found.
68
+ def search_by_title(movie_title, result_limit)
69
+ uri = "http://api.rottentomatoes.com/api/public/v1.0/movies.json?apikey=#{@rt_api_key}&q=#{CGI.escape(movie_title)}&page_limit=#{result_limit}"
63
70
 
64
- movie.imdb_rating = extra_info[:imdb_rating]
65
- movie.metacritic_rating = extra_info[:metacritic_rating]
66
- movie.metacritic_url = extra_info[:metacritic_url]
71
+ response = JSON.parse(Typhoeus.get(uri).body)
67
72
 
68
- movie.poster = get_poster(movie.imdb_id)
69
- movie.reviews = get_reviews(movie.rt_id)
70
-
71
- return movie
73
+ if response["total"] == 0
74
+ return false
75
+ else
76
+ # Build the array of movie serach results. Have to use a regexp to extract the Rotten Tomatoes
77
+ # ID from the movie link since the API does not return it directly.
78
+ return response["movies"].inject([]) do |movie_list, movie|
79
+ movie_list << { :title => movie["title"], :rt_id => movie["links"]["self"].match(/\/[0-9]+\./).to_s.gsub(/[\/\.]/, ""), :year => movie["year"].to_s }
80
+ movie_list
81
+ end
82
+ end
72
83
  end
73
84
 
74
85
  private
75
86
 
76
- # Retrieves extra info about a particular movie that cannot be found using
77
- # the Rotten Tomatoes API. All facilitated by its IMDb ID.
78
- # @params imdb_id [String] the IMDb ID of the required movie (without 'tt' prefixed)
79
- # @return [Hash] a hash containing IMDb rating, Metacritic rating and movie URL
80
- def get_extra_info(imdb_id)
81
- imdb_url = "http://m.imdb.com/title/tt#{imdb_id}"
82
-
83
- imdb_page = Nokogiri::HTML(open(imdb_url))
84
- extra_info = {}
85
-
86
- # Extract IMDB rating
87
- extra_info[:imdb_rating] = imdb_page.css('.votes strong').text
88
-
89
- # Extract Metacritic rating (IMDB has a page listing MC reviews)
90
- imdb_mc_page = Nokogiri::HTML(open("http://www.imdb.com/title/tt#{imdb_id}/criticreviews"))
91
-
92
- mc_rating = imdb_mc_page.css(".metascore > span").text
93
-
94
- if mc_rating != ""
95
- extra_info[:metacritic_rating] = mc_rating
96
- extra_info[:metacritic_url] = imdb_mc_page.css(".see-more .offsite-link")[0]["href"]
97
- else
98
- extra_info[:metacritic_rating] = "No Rating"
99
- extra_info[:metacritic_url] = "No URL"
100
- end
101
-
102
- return extra_info
87
+ # Aggregates extra info about @movie that cannot be derived directly from the
88
+ # Rotten Tomatoes API e.g IMDb/Metacritic rating, HQ posters
89
+ #
90
+ # @return [Movie] the movie with aggregated info completed
91
+ def aggregate
92
+ retrieve_imdb_info
93
+ retrieve_metacritic_info
94
+ get_poster
95
+ get_reviews
96
+ return @movie
103
97
  end
104
98
 
105
- def get_extra_info_via_omdb(imdb_id)
106
- extra_info = {}
107
- omdb_response = HTTParty.get("http://www.omdbapi.com/?i=tt#{imdb_id}")
99
+ # Retrieves and updates the current movie's IMDb rating
100
+ def retrieve_imdb_info
101
+ omdb_response = JSON.parse(Typhoeus.get("http://www.omdbapi.com/?i=tt#{@movie.imdb_id}").body)
108
102
 
109
103
  if omdb_response["Response"] == "True"
110
- imdb_rating = omdb_response["imdbRating"]
111
- movie_title = omdb_response["Title"]
112
-
113
- mc_info = scrape_metacritic_info(movie_title)
114
-
115
- mc_rating = mc_info[:mc_rating]
116
- mc_link = mc_info[:mc_url]
117
- else
118
- imdb_rating = "Unavailable"
119
- end
120
-
121
- # Extract IMDB rating
122
- extra_info[:imdb_rating] = imdb_rating
123
-
124
- if mc_rating != ""
125
- extra_info[:metacritic_rating] = mc_rating
126
- extra_info[:metacritic_url] = mc_link
104
+ @movie.imdb_rating = omdb_response["imdbRating"]
127
105
  else
128
- extra_info[:metacritic_rating] = "Unavailable"
129
- extra_info[:metacritic_url] = "No URL"
106
+ @movie.imdb_rating = "Unavailable"
130
107
  end
131
-
132
- return extra_info
133
108
  end
134
109
 
135
- # Scrapes the metacritic rating and URL, returning a hash containing the info
136
- def scrape_metacritic_info(movie_title)
137
- mc_info = {}
110
+ # Retrieves and updates the current movie's Metacritic rating and URL
111
+ def retrieve_metacritic_info
112
+ metacritic_page = Nokogiri::HTML(open("http://www.metacritic.com/search/"\
113
+ "movie/#{CGI.escape(@movie.title)}/results"))
138
114
 
139
- # Extract Metacritic rating (IMDB has a page listing MC reviews)
140
- metacritic_page = Nokogiri::HTML(open("http://www.metacritic.com/search/"\
141
- "movie/#{CGI.escape(movie_title)}/results"))
142
- mc_info[:mc_rating] = metacritic_page.css('.first_result .metascore_w').text
143
- mc_info[:mc_url] = "http://www.metacritic.com#{metacritic_page.at_css('.first_result a').attr(:href)}"
115
+ scraped_rating = metacritic_page.css('.first_result .metascore_w').text
116
+ metacritic_url = "http://www.metacritic.com#{metacritic_page.at_css('.first_result a').attr(:href)}"
144
117
 
145
- return mc_info
118
+ # If attempt to scrape results in empty string, info must not be available
119
+ if scraped_rating == ""
120
+ scraped_rating = "No Rating"
121
+ metacritic_url = "No URL"
122
+ end
123
+
124
+ @movie.metacritic_rating = scraped_rating
125
+ @movie.metacritic_url = metacritic_url
146
126
  end
147
127
 
148
- # Retrieves the URL of a high resolution poster of a movie
149
- # @params imdb_id [String] the IMDb ID of the required movie (without 'tt' prefixed)
150
- # @return [String] the URL of the poster as a string
151
- def get_poster(imdb_id)
152
- uri = "#{TMDB_API_BASE_URL}/movie/tt#{imdb_id}?api_key=#{tmdb_api_key}"
153
- movie_info = HTTParty.get(uri, :headers => { 'Accept' => 'application/json'})
128
+ # Updates the current movie's high resolution poster URL
129
+ def get_poster
130
+ uri = "#{TMDB_API_BASE_URL}/movie/tt#{@movie.imdb_id}?api_key=#{tmdb_api_key}"
131
+ movie_info = JSON.parse(Typhoeus.get(uri).body)
154
132
 
155
133
  if movie_info.has_key?("poster_path")
156
- "http://cf2.imgobject.com/t/p/original" + movie_info["poster_path"]
134
+ @movie.poster = "http://cf2.imgobject.com/t/p/original" + movie_info["poster_path"]
157
135
  else
158
- "No poster available"
136
+ @movie.poster = "No poster available"
159
137
  end
160
138
  end
161
139
 
162
- def get_reviews(rt_id)
163
- uri = "#{RT_API_BASE_URL}/movies/#{rt_id}/reviews.json?review_type=top_critic"\
164
- "&page_limit=5&page=1&country=uk&apikey=#{rt_api_key}"
165
- review_hash = HTTParty.get(uri)
140
+ # Retrieves and updates the current movie's reviews
141
+ def get_reviews
142
+ uri = "#{RT_API_BASE_URL}/movies/#{@movie.rt_id}/reviews.json?review_type=top_critic"\
143
+ "&page_limit=5&page=1&country=uk&apikey=#{@rt_api_key}"
144
+ review_hash = JSON.parse(Typhoeus.get(uri).body)
166
145
 
167
146
  review_list = []
168
147
 
@@ -170,11 +149,12 @@ module WorthWatching
170
149
  review_list << WrittenReview.new(review)
171
150
  end
172
151
 
173
- return review_list
152
+ @movie.reviews = review_list
174
153
  end
175
154
 
176
155
  # Checks that a given movie has enough information available via API to aggregate
177
156
  # data. It MUST have an IMDb id and a release date.
157
+ #
178
158
  # @param [Hash] the hash representation of the movie to check
179
159
  # @return [Boolean] whether the movie has a theater release date and IMDb ID
180
160
  def enough_info?(movie)
@@ -197,13 +177,21 @@ module WorthWatching
197
177
  return has_release_date && has_imdb_id
198
178
  end
199
179
 
200
- # Removes movies from an array that do no have the required rating information
201
- # @param movie_list [Array] the list to clean up
202
- # @return [Array] the pruned list of movies
203
- def self.clean_up(movie_list)
204
- movie_list.delete_if do |movie|
205
- movie.metacritic_rating == "No Rating"
206
- end
180
+ # Retrieves a list of movies from the Rotten Tomatoes API, then aggregates
181
+ # info for each one
182
+ #
183
+ # @param uri [String] the Rotten Tomatoes API endpoint for the list
184
+ # @return [Array] an array of Movie objects
185
+ def get_movie_list(uri)
186
+ response = JSON.parse(Typhoeus.get(uri).body)
187
+ movie_list_response = response["movies"]
188
+
189
+ movie_list = movie_list_response.inject([]) do |list, movie|
190
+ list << aggregate_movie(movie['id']) if enough_info?(movie)
191
+ list
192
+ end
193
+
194
+ return movie_list
207
195
  end
208
196
  end
209
197
  end