From 83a95622035004b14c63c4a64229014b05cfeae0 Mon Sep 17 00:00:00 2001 From: jason perez Date: Sat, 1 Feb 2014 10:57:48 -0800 Subject: [PATCH 1/6] fix search results to not throw an error if movie not found --- lib/api.rb | 19 +++++++++++++------ spec/api_spec.rb | 41 ++++++++++++++++++++++++++--------------- 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/lib/api.rb b/lib/api.rb index a8d499c..1a37130 100644 --- a/lib/api.rb +++ b/lib/api.rb @@ -9,14 +9,21 @@ class Api def self.search_by_title(title) url = "http://api.rottentomatoes.com/api/public/v1.0/movies.json?apikey=#{APIKEY}&q=#{URI.encode(title)}&page_limit=1" struct = OpenStruct.new(get_url_as_json(url).fetch("movies").first) - Movie.new(id: struct.id.to_i, - title: struct.title, - year: struct.year, - score: struct.ratings["critics_score"] - ) + if struct.respond_to?(:title) + Movie.new(id: struct.id.to_i, + title: struct.title, + year: struct.year, + score: struct.ratings["critics_score"] + ) + else + Movie.new(id: 0, + title: "no results", + year: "", + score: "N/A" + ) + end end - def self.get_url_as_json(url) JSON.parse(open(url).read) end diff --git a/spec/api_spec.rb b/spec/api_spec.rb index 9014106..a15f7d9 100644 --- a/spec/api_spec.rb +++ b/spec/api_spec.rb @@ -2,26 +2,37 @@ require "ostruct" describe Api do + describe ".search_by_title" do + context "when title found" do + let(:movie) { Api.search_by_title("Forrest Gump") } - let(:movie) { Api.search_by_title("Forrest Gump") } + before do + Api.stub(:get_url_as_json) { JSON.parse(File.read("spec/fixtures/forrest.json")) } + end - before do - Api.stub(:get_url_as_json) { JSON.parse(File.read("spec/fixtures/forrest.json")) } - end + it "should search for movies" do + movie.title.should eq("Forrest Gump") + end - it "should search for movies" do - movie.title.should eq("Forrest Gump") - end + it "should return the score" do + movie.score.should eq(71) + end - it "should return the score" do - movie.score.should eq(71) - end + it "should return the id" do + movie.id.should eq(10036) + end - it "should return the id" do - movie.id.should eq(10036) - end + it "should return the year" do + movie.year.should eq(1994) + end + end + + context "when title not found" do + let(:movie) { Api.search_by_title("asdfasdfasdf") } - it "should return the year" do - movie.year.should eq(1994) + it "should not raise an error" do + movie.title.should_not raise_error + end + end end end From 6243578ae9c3e3c8a32e83d93b6bf5abc272adc8 Mon Sep 17 00:00:00 2001 From: jason perez Date: Tue, 4 Feb 2014 00:13:53 -0800 Subject: [PATCH 2/6] update no results method to return a NotFoundMovie object --- lib/api.rb | 14 +++++++------- lib/movie.rb | 9 +++++++++ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/lib/api.rb b/lib/api.rb index 1a37130..1307eb8 100644 --- a/lib/api.rb +++ b/lib/api.rb @@ -8,19 +8,19 @@ class Api def self.search_by_title(title) url = "http://api.rottentomatoes.com/api/public/v1.0/movies.json?apikey=#{APIKEY}&q=#{URI.encode(title)}&page_limit=1" - struct = OpenStruct.new(get_url_as_json(url).fetch("movies").first) - if struct.respond_to?(:title) + build_movie(get_url_as_json(url).fetch("movies").first) + end + + def self.build_movie(json) + struct = OpenStruct.new(json) + if struct.ratings Movie.new(id: struct.id.to_i, title: struct.title, year: struct.year, score: struct.ratings["critics_score"] ) else - Movie.new(id: 0, - title: "no results", - year: "", - score: "N/A" - ) + NotFoundMovie.new end end diff --git a/lib/movie.rb b/lib/movie.rb index 167a23e..7e0b99d 100644 --- a/lib/movie.rb +++ b/lib/movie.rb @@ -8,3 +8,12 @@ def initialize(hash={}) @score = hash.fetch(:score) end end + +class NotFoundMovie + attr_reader :title, :score + + def initialize + @title = "no results" + @score = "N/A" + end +end From 125667bccbfe9acb49223a8f4aef5ab36ed88a4b Mon Sep 17 00:00:00 2001 From: jason perez Date: Tue, 4 Feb 2014 13:20:08 -0800 Subject: [PATCH 3/6] update title not found spec with mock api --- spec/api_spec.rb | 10 ++++++++-- spec/fixtures/no_result.json | 8 ++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 spec/fixtures/no_result.json diff --git a/spec/api_spec.rb b/spec/api_spec.rb index a15f7d9..4af62b6 100644 --- a/spec/api_spec.rb +++ b/spec/api_spec.rb @@ -25,13 +25,19 @@ it "should return the year" do movie.year.should eq(1994) end + + it "should add the search result to movie_list" end context "when title not found" do let(:movie) { Api.search_by_title("asdfasdfasdf") } - it "should not raise an error" do - movie.title.should_not raise_error + before do + Api.stub(:get_url_as_json) { JSON.parse(File.read("spec/fixtures/no_result.json")) } + end + + it "should return a not found title" do + movie.title.should eq("no results") end end end diff --git a/spec/fixtures/no_result.json b/spec/fixtures/no_result.json new file mode 100644 index 0000000..cc3e7bb --- /dev/null +++ b/spec/fixtures/no_result.json @@ -0,0 +1,8 @@ +{ + "total": 0, + "movies": [], + "links": { + "self": "http://api.rottentomatoes.com/api/public/v1.0/movies.json?q=asfasffsafsafa&page_limit=1&page=1" + }, + "link_template": "http://api.rottentomatoes.com/api/public/v1.0/movies.json?q={search-term}&page_limit={results-per-page}&page={page-number}" +} \ No newline at end of file From 0f4b3543409f42d0bdf8f555853aca1e6f8b3283 Mon Sep 17 00:00:00 2001 From: jason perez Date: Tue, 4 Feb 2014 21:24:09 -0800 Subject: [PATCH 4/6] add the average rating score for a group of movies --- lib/movie_clerk.rb | 32 ++++++++++++++++++++++++++++++++ movie_json.rb | 21 +++++++-------------- spec/api_spec.rb | 2 -- spec/movie_clerk_spec.rb | 17 +++++++++++++++++ 4 files changed, 56 insertions(+), 16 deletions(-) create mode 100644 lib/movie_clerk.rb create mode 100644 spec/movie_clerk_spec.rb diff --git a/lib/movie_clerk.rb b/lib/movie_clerk.rb new file mode 100644 index 0000000..020b262 --- /dev/null +++ b/lib/movie_clerk.rb @@ -0,0 +1,32 @@ +require_relative "api" + +class MovieClerk + def initialize + @movies = [] + @scores = [] + puts "Welcome to The Movie Clerk!" + end + + def find_movie + puts "Add a movie you like:" + movie_title = gets + search_by_title(movie_title) + send_movie_details(@movies.last) + end + + def search_by_title(movie_title) + @movies << Api.search_by_title(movie_title) + end + + def send_movie_details(movie) + puts "Found: #{movie.title}. Score: #{movie.score}" + puts "Average score of #{movie_score_average.round(2)} for #{@movies.count} movies on your list." + end + + def movie_score_average + @movies.each do |movie| + @scores << movie.score + end + @scores.inject{ | sum, n | sum + n}.to_f / @scores.size + end +end \ No newline at end of file diff --git a/movie_json.rb b/movie_json.rb index d8a91d7..150bed1 100644 --- a/movie_json.rb +++ b/movie_json.rb @@ -1,21 +1,14 @@ -require_relative "lib/movie" -require_relative "lib/api" +require_relative "lib/movie_clerk" -def find_movie - puts "OH HAI. Search?" - movie_title = gets - movie = Api.search_by_title(movie_title) - puts "Found: #{movie.title}. Score: #{movie.score}" -end - -find_movie +clerk = MovieClerk.new +clerk.find_movie while true do - puts "Search Again (Y/N)" + puts "Search Again (Y/N)" answer = gets.upcase[0] - if answer == "Y" - find_movie - else + if answer == "N" break + else + clerk.find_movie end end diff --git a/spec/api_spec.rb b/spec/api_spec.rb index 4af62b6..7ccbb40 100644 --- a/spec/api_spec.rb +++ b/spec/api_spec.rb @@ -25,8 +25,6 @@ it "should return the year" do movie.year.should eq(1994) end - - it "should add the search result to movie_list" end context "when title not found" do diff --git a/spec/movie_clerk_spec.rb b/spec/movie_clerk_spec.rb new file mode 100644 index 0000000..3656910 --- /dev/null +++ b/spec/movie_clerk_spec.rb @@ -0,0 +1,17 @@ +require_relative '../lib/movie_clerk' + +describe MovieClerk do + it "finds a movie" do + clerk = MovieClerk.new + clerk.search_by_title("pulp fiction").first.title.should eq("Pulp Fiction") + end + + it "should provide the average score from the movie list" do + clerk = MovieClerk.new + clerk.search_by_title("baseketball") + clerk.search_by_title("goonies") + clerk.movie_score_average.should eq(54.5) + end + + $stdout = StringIO.new +end \ No newline at end of file From fbd0c6193589feb79b32766507a7d8e0238b3a1b Mon Sep 17 00:00:00 2001 From: jason perez Date: Sun, 9 Feb 2014 16:41:02 -0800 Subject: [PATCH 5/6] add taste analyzer --- lib/movie_clerk.rb | 20 +++++++++++++++++++- movie_json.rb | 2 ++ spec/movie_clerk_spec.rb | 17 +++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/lib/movie_clerk.rb b/lib/movie_clerk.rb index 020b262..a1f51ce 100644 --- a/lib/movie_clerk.rb +++ b/lib/movie_clerk.rb @@ -1,10 +1,12 @@ require_relative "api" class MovieClerk + attr_reader :welcome_message, :taste_measurement + def initialize @movies = [] @scores = [] - puts "Welcome to The Movie Clerk!" + @welcome_message = "Welcome to The Movie Clerk!" end def find_movie @@ -14,6 +16,22 @@ def find_movie send_movie_details(@movies.last) end + def analyze_taste + last_two_movies = @movies.last(2) + first_movie = last_two_movies.first + last_movie = last_two_movies.last + @taste_measurement = (first_movie.score - last_movie.score).to_f / (first_movie.year - last_movie.year).to_f + if @taste_measurement < 0 + puts "Your taste is diminishing over time." + else + puts "Your taste is improving over time." + end + end + + def perform_taste_analysis? + @movies.size == 2 + end + def search_by_title(movie_title) @movies << Api.search_by_title(movie_title) end diff --git a/movie_json.rb b/movie_json.rb index 150bed1..76ef7ca 100644 --- a/movie_json.rb +++ b/movie_json.rb @@ -1,6 +1,7 @@ require_relative "lib/movie_clerk" clerk = MovieClerk.new +puts clerk.welcome_message clerk.find_movie while true do @@ -10,5 +11,6 @@ break else clerk.find_movie + clerk.analyze_taste if clerk.perform_taste_analysis? end end diff --git a/spec/movie_clerk_spec.rb b/spec/movie_clerk_spec.rb index 3656910..dbf8c01 100644 --- a/spec/movie_clerk_spec.rb +++ b/spec/movie_clerk_spec.rb @@ -13,5 +13,22 @@ clerk.movie_score_average.should eq(54.5) end + describe "#analyze_taste" do + it "should tell the user their taste is improving over time" do + clerk = MovieClerk.new + clerk.search_by_title("fargo") + clerk.search_by_title("spaceballs") + clerk.analyze_taste + clerk.taste_measurement.should eq(4.444444444444445) + end + it "should tell the user their taste is diminishing over time" do + clerk = MovieClerk.new + clerk.search_by_title("gigli") + clerk.search_by_title("fargo") + clerk.analyze_taste + clerk.taste_measurement.should eq(-12.571428571428571) + end + end + $stdout = StringIO.new end \ No newline at end of file From 95e7612345c8b954f30179bc4e2d60ba59f4490d Mon Sep 17 00:00:00 2001 From: jason perez Date: Thu, 13 Feb 2014 12:22:32 -0800 Subject: [PATCH 6/6] update spec to allow for approximate value, uupdate #movie_score_average to use local variable and map inject --- lib/movie_clerk.rb | 7 ++----- spec/movie_clerk_spec.rb | 4 ++-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/lib/movie_clerk.rb b/lib/movie_clerk.rb index a1f51ce..1074315 100644 --- a/lib/movie_clerk.rb +++ b/lib/movie_clerk.rb @@ -5,7 +5,6 @@ class MovieClerk def initialize @movies = [] - @scores = [] @welcome_message = "Welcome to The Movie Clerk!" end @@ -42,9 +41,7 @@ def send_movie_details(movie) end def movie_score_average - @movies.each do |movie| - @scores << movie.score - end - @scores.inject{ | sum, n | sum + n}.to_f / @scores.size + scores = @movies.map {|m| m.score} + scores.inject(:+).to_f / scores.size end end \ No newline at end of file diff --git a/spec/movie_clerk_spec.rb b/spec/movie_clerk_spec.rb index dbf8c01..255fd1e 100644 --- a/spec/movie_clerk_spec.rb +++ b/spec/movie_clerk_spec.rb @@ -19,14 +19,14 @@ clerk.search_by_title("fargo") clerk.search_by_title("spaceballs") clerk.analyze_taste - clerk.taste_measurement.should eq(4.444444444444445) + clerk.taste_measurement.should be_within(0.01).of(4.44) end it "should tell the user their taste is diminishing over time" do clerk = MovieClerk.new clerk.search_by_title("gigli") clerk.search_by_title("fargo") clerk.analyze_taste - clerk.taste_measurement.should eq(-12.571428571428571) + clerk.taste_measurement.should be_within(0.01).of(-12.57) end end