Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Panda - fix search results to not throw an error if movie not found #25

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions lib/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,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"]
)
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
NotFoundMovie.new
end
end

def self.get_url_as_json(url)
JSON.parse(open(url).read)
Expand Down
9 changes: 9 additions & 0 deletions lib/movie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
47 changes: 47 additions & 0 deletions lib/movie_clerk.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
require_relative "api"

class MovieClerk
attr_reader :welcome_message, :taste_measurement

def initialize
@movies = []
@welcome_message = "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 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

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
scores = @movies.map {|m| m.score}
scores.inject(:+).to_f / scores.size
end
end
23 changes: 9 additions & 14 deletions movie_json.rb
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
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
puts clerk.welcome_message
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
clerk.analyze_taste if clerk.perform_taste_analysis?
end
end
45 changes: 30 additions & 15 deletions spec/api_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,41 @@
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") }

before do
Api.stub(:get_url_as_json) { JSON.parse(File.read("spec/fixtures/no_result.json")) }
end

it "should return the year" do
movie.year.should eq(1994)
it "should return a not found title" do
movie.title.should eq("no results")
end
end
end
end
8 changes: 8 additions & 0 deletions spec/fixtures/no_result.json
Original file line number Diff line number Diff line change
@@ -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}"
}
34 changes: 34 additions & 0 deletions spec/movie_clerk_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
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

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 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")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:)

clerk.analyze_taste
clerk.taste_measurement.should be_within(0.01).of(-12.57)
end
end

$stdout = StringIO.new
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good stuff on $stdout.... usually, when you re-assign stdout, you want to only do it temporarily, so you can do your thing, check your thing, and reset your thing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe use this technique on http://thinkingdigitally.com/archive/capturing-output-from-puts-in-ruby/

require 'stringio'

module Kernel

  def capture_stdout
    out = StringIO.new
    $stdout = out
    yield
    return out
  ensure
    $stdout = STDOUT
  end

end

results = capture_stdout do
  puts "hi!"
end

results.string
=> "hi!\n"

Only real tricky part is the "\n".... if you hate that, you could change to

results = capture_stdout do
  print "hi"
end
results.string
=> "hi"

end