Skip to content
Open
Show file tree
Hide file tree
Changes from 7 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key.rb
2 changes: 2 additions & 0 deletions .rspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
--color
--format documentation
18 changes: 11 additions & 7 deletions lib/api.rb
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
require "open-uri"
require "json"
require "ostruct"
require_relative "./movie"
require_relative "./api_key"

class Api

APIKEY="4t6456xa33z8qhcqyuqgnkjh"
APIKEY=API_KEY
Copy link
Member

Choose a reason for hiding this comment

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

I like the moving the key into a git-ignored file. But, you can just have that set your variable... in api_key.rb have it set APIKEY directly. This line ends up looking odd (and future-you won't remember what this is)


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"]
)
struct.id.nil? ? "Sorry we could not find that movie" : store_movie(struct)
end


def self.get_url_as_json(url)
JSON.parse(open(url).read)
end

def self.store_movie(movie_struct)
Movie.new(id: movie_struct.id.to_i,
title: movie_struct.title,
year: movie_struct.year,
score: movie_struct.ratings["critics_score"]
)
end
end
121 changes: 107 additions & 14 deletions movie_json.rb
Original file line number Diff line number Diff line change
@@ -1,21 +1,114 @@
require_relative "lib/movie"
require_relative "lib/api"

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
class MovieJson

attr_reader :movies
def initialize
@movies = []
end

def run
search
end

find_movie
def movie_search_by_title
puts "OH HAI. Please add a movie you like"
print ">>"
movie_title = gets.downcase.chomp
return "Sorry, but you have to actually enter something to search" if movie_title.empty?
puts "Cool, searching for #{movie_title}"
search = add_to_movie_list(movie_title)
return search if search.class == String
Copy link
Member

Choose a reason for hiding this comment

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

I don't love this -- checking a specific class isn't done usually in Ruby. If you wanted something like this, you could check the signature of the object.

movie.respond_to? :title

That way it can be any object, as long as it following the protocol/interface you need.


More broadly, I'd rather you use a NilClass pattern than return a string. Here's an example library I like: https://github.com/avdi/naught

puts movie_title != search.title ? "This is the closest we could find: #{search.title} was released in #{search.year}. It recieved a critics score of #{search.score}" : "#{search.title} was released in #{search.year}. It recieved a critics score of #{search.score}"
end

def add_to_movie_list(movie)
found_movie = Api.search_by_title(movie)
Copy link
Member

Choose a reason for hiding this comment

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

One of the things you can do in ruby is "tap" an object. I think it could work well here:

def add_to_movie_list(movie)
  Api.search_by_title(movie).tap {|found_movie| @movies << found_movie }
end

This method seems to do 2 things though: it searches for movies, and adds to a list. Is this the right name for that method?

@movies << found_movie
found_movie
end

def search_again(response)
if response == "yes"
movie_search_by_title
elsif response == "no"
false
else
puts "I don't understand that"
end
end

while true do
puts "Search Again (Y/N)"
answer = gets.upcase[0]
if answer == "Y"
find_movie
else
break
def search
puts "Would you like to: \n1) Search\n2) Average rating?\n3) Average year?\n4) Calculate movie happiness?\n5) Exit?"
print ">>"
u_start = gets.chomp
if u_start == "1"
puts movie_search_by_title
while true
puts "Search Again? Yes or No"
re_search = gets.downcase.chomp
break if search_again(re_search) == false
end
search
elsif u_start == "2"
puts average_raiting
search
elsif u_start == "3"
puts average_year
search
elsif u_start == "4"
puts calculate_happiness
search
else
puts "Exiting..."
end
end

def average_raiting
@movies.map {|movie| movie.score}.reduce(:+).to_f / @movies.size
end

def average_year
avg_year = @movies.map { |movie| movie.year}.reduce(:+).to_f / @movies.size
avg_year.to_i
end

def calculate_happiness
Copy link
Member

Choose a reason for hiding this comment

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

This method definitely works; it's hard to read though.

Could you rewrite it using the constraint that a method should be no more than 3 lines long?

# ratings = @movies.map { |movie| movie.score }
year_avg = {}
@movies.each { |movie| year_avg[movie.year] = [] }
@movies.each { |movie| year_avg[movie.year].push(movie.score) }
years = @movies.map { |movie| movie.year}.sort
oldest_year_avg = year_avg[years[0]].reduce(:+).to_f / year_avg[years[0]].size
youngest_year_avg = year_avg[years[-1]].reduce(:+).to_f / year_avg[years[-1]].size
slope = years[0] - years[-1] != 0 ? (youngest_year_avg - oldest_year_avg).to_f / (years[-1] - years[0]).to_f : 0
if slope == 0
return "You're neutral"
elsif slope > 0
return "You're getting happier!"
else
return "You're getting sadder"
end
end

end
MovieJson.new.run if __FILE__ == $PROGRAM_NAME
# 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

# while true do
# puts "Search Again (Y/N)"
# answer = gets.upcase[0]
# if answer == "Y"
# find_movie
# else
# break
# end
# end
9 changes: 8 additions & 1 deletion spec/api_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

describe Api 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")) }
Expand All @@ -24,4 +24,11 @@
it "should return the year" do
movie.year.should eq(1994)
end

it "should return a warning statement if movie was not found" do
Api.stub(:get_url_as_json) { JSON.parse(File.read("spec/fixtures/no_movie.json")) }
no_movie = Api.search_by_title("dfsfsfdf")
expect(no_movie.class).to eq(String)
end

end
1 change: 1 addition & 0 deletions spec/fixtures/no_movie.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"total":0,"movies":[],"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies.json?q=Forrest+Gump&page_limit=1&page=1","next":"http://api.rottentomatoes.com/api/public/v1.0/movies.json?q=Forrest+Gump&page_limit=1&page=2"},"link_template":"http://api.rottentomatoes.com/api/public/v1.0/movies.json?q={search-term}&page_limit={results-per-page}&page={page-number}"}
95 changes: 95 additions & 0 deletions spec/movie_json_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
require_relative "../movie_json"
require_relative "../lib/api"
require_relative "../lib/movie"

describe MovieJson do

let(:movie) { Movie.new(id: "111",
title: "Forrest Gump",
year: 1994,
score: 71)
}
let(:happy_movie) { Movie.new(id: "112",
title: "Happy movie",
year: 1995,
score: 99)
}
let(:sad_movie) { Movie.new(id: "113",
title: "Sad movie",
year: 1995,
score: 1)}

before do
# Api.stub(:get_url_as_json) { JSON.parse(File.read("spec/fixtures/forrest.json")) }
Api.stub(:search_by_title) {movie}
# MovieJson.stub(:gets).and_return("")
end

describe "#movie_search_by_title" do
it "should return a warning when no movie is entered into the search" do
movie_search1 = MovieJson.new
movie_search1.stub(:gets).and_return("")
movie_search1.movie_search_by_title.should == "Sorry, but you have to actually enter something to search"
end
end

it "should allow the user to add two movies they like" do
movie_search2 = MovieJson.new
movie_search2.add_to_movie_list(movie)
movie_search2.add_to_movie_list(movie)
expect(movie_search2.movies.length).to eq(2)
end

describe "#average_raiting" do
it "should give average rating of the movies in your list" do
movie_search3 = MovieJson.new
movie_search3.add_to_movie_list(movie)
movie_search3.add_to_movie_list(movie)
expect(movie_search3.average_raiting).to eq(71)
end
end

describe "#average_year" do
it "should give the average year of the movies in your list" do
movie_search4 = MovieJson.new
movie_search4.add_to_movie_list(movie)
movie_search4.add_to_movie_list(movie)
expect(movie_search4.average_year).to eq(1994)
end
end

describe "#calculate_happiness" do
it "should say your neutral at neutral slope" do
movie_search5 = MovieJson.new
movie_search5.add_to_movie_list(movie)
movie_search5.add_to_movie_list(movie)
movie_search5.calculate_happiness.should == "You're neutral"
end

it "should say your happier at postive slope" do
movie_search6 = MovieJson.new
Copy link
Member

Choose a reason for hiding this comment

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

You don't have to name these each time --- every spec can be movie = MovieJson.new

movie_search6.add_to_movie_list(movie)
Api.stub(:search_by_title) {happy_movie}
movie_search6.add_to_movie_list(happy_movie)
movie_search6.calculate_happiness.should == "You're getting happier!"
end

it "should say your sadder at negative slope" do
movie_search7 = MovieJson.new
movie_search7.add_to_movie_list(movie)
Api.stub(:search_by_title) {sad_movie}
movie_search7.add_to_movie_list(sad_movie)
movie_search7.calculate_happiness.should == "You're getting sadder"
end

it "should take the average of years that are the same and determine slope" do
movie_search7 = MovieJson.new
movie_search7.add_to_movie_list(movie)
Api.stub(:search_by_title) {sad_movie}
movie_search7.add_to_movie_list(sad_movie)
Api.stub(:search_by_title) {happy_movie}
movie_search7.add_to_movie_list(happy_movie)
movie_search7.calculate_happiness.should == "You're getting sadder"
end
end
end
4 changes: 4 additions & 0 deletions spec/movie_spec.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
require_relative "../lib/movie"




describe Movie do

it "should store the title, year, and score" do
Expand Down