Skip to content
Open
Show file tree
Hide file tree
Changes from 4 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
32 changes: 32 additions & 0 deletions lib/movie_clerk.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require_relative "api"

class MovieClerk
def initialize
@movies = []
@scores = []
puts "Welcome to The Movie Clerk!"
Copy link
Member

Choose a reason for hiding this comment

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

Here the output is directly tied to the MovieClerk; meaning movie_clerk cannot be re-used elsewhere.

Can you think of a way you could do this same thing, but not use "puts" anywhere in the code?

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

Choose a reason for hiding this comment

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

I couldn't see where you used @scores later... I think a map then inject might work:

scores = @movies.map{|m| m.score}
scores.inject(:+).to_f / scores.size

And of course, this is where ruby excels at one-liner-golf

@movies.map{|m| m.score}.tap{|s| s.inject(:+).to_f / s.size}

Or:

module Enumerable
  def average
     self.inject(:+).to_f / count
  end
end

@movies.map{|m| m.score}.average

@scores << movie.score
end
@scores.inject{ | sum, n | sum + n}.to_f / @scores.size
end
end
21 changes: 7 additions & 14 deletions movie_json.rb
Original file line number Diff line number Diff line change
@@ -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
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}"
}
17 changes: 17 additions & 0 deletions spec/movie_clerk_spec.rb
Original file line number Diff line number Diff line change
@@ -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
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