Skip to content

Instantly share code, notes, and snippets.

@RobertoBarros
Created July 18, 2016 21:28
Show Gist options
  • Save RobertoBarros/7c11c3395fc7da4e8401764f68233990 to your computer and use it in GitHub Desktop.
Save RobertoBarros/7c11c3395fc7da4e8401764f68233990 to your computer and use it in GitHub Desktop.
require_relative 'cookbook' # You need to create this file!
require_relative 'controller' # You need to create this file!
require_relative 'router'
require 'pry'
csv_file = File.join(__dir__, 'recipes.csv')
cookbook = Cookbook.new(csv_file)
controller = Controller.new(cookbook)
router = Router.new(controller)
# Start the app
router.run
require_relative 'view'
require_relative 'recipe'
require_relative 'epicurious'
class Controller
def initialize(cookbook)
@cookbook = cookbook
@epicurious = Epicurious.new
@view = View.new
end
def list
# 1. ask the cookbook for the recipes
recipes = @cookbook.all
# 2. ask the view to print the recipes
@view.print_recipes(recipes)
end
def create
# 1. ask the name from the view
name = @view.ask_name
# 2. ask the description from the view
description = @view.ask_description
# 3. create a recipe with the values
recipe = Recipe.new(name: name, description: description)
# 4. add the recipe to the cookbook
@cookbook.add_recipe(recipe)
end
def destroy
# 1. ask the view the recipe's index to delete
index = @view.ask_recipe_index
# 2. remove the recipe from the cookbook
@cookbook.remove_recipe(index)
end
def mark_as_tested
index = @view.ask_mark_as_tested
@cookbook.mark_as_tested(index)
end
def search
search_term = @view.ask_for_search
filtered_reciped = @cookbook.search(search_term)
@view.print_recipes(filtered_reciped)
end
def import
search_term = @view.ask_search_term
results = @epicurious.search(search_term)
@view.print_results(results)
index = @view.ask_which_recipe
recipe = @epicurious.import(results[index])
@cookbook.add_recipe(recipe)
end
end
require 'csv'
class Cookbook
def initialize(csv_file)
@csv_file = csv_file
@recipes = []
load_csv
end
def all
@recipes
end
def add_recipe(recipe)
@recipes << recipe
write_csv
end
def remove_recipe(recipe_id)
@recipes.delete_at(recipe_id)
write_csv
end
def mark_as_tested(recipe_id)
@recipes[recipe_id].tested = true
write_csv
end
def search(search_term)
@recipes.select{|recipe| recipe.name.downcase.include?(search_term.downcase) }
end
private
def load_csv
CSV.foreach(@csv_file) do |row|
attributes = {
name: row[0],
description: row[1],
rating: row[2],
tested: (row[3] == 'true')
}
@recipes << Recipe.new(attributes)
end
end
def write_csv
CSV.open(@csv_file, "w") do |csv|
@recipes.each do |recipe|
csv << [recipe.name, recipe.description, recipe.rating, recipe.tested]
end
end
end
end
require 'nokogiri'
require 'open-uri'
class Epicurious
def initialize
end
def search(search_term)
doc = Nokogiri::HTML(open("http://www.epicurious.com/search?terms=#{search_term}"), nil, 'utf-8')
@results = {}
doc.css('.recipe-result-item a.view-complete-item').each do |element|
href = element["href"]
title = element["title"]
next if title == nil
@results[title] = "http://www.epicurious.com#{href}"
end
return @results.keys
end
def import(key)
url = @results[key]
doc = Nokogiri::HTML(open(url), nil, 'utf-8')
description = doc.css("div[itemprop=description] p").text
rating = doc.css('meta[itemprop=ratingValue]').first['content']
Recipe.new(name: key, description: description, rating: rating)
end
end
class Recipe
attr_reader :name, :description, :rating
attr_accessor :tested
def initialize(attributes = {})
@name = attributes[:name]
@description = attributes[:description]
@rating = attributes[:rating]
@tested = attributes[:tested] || false
end
end
class Router
def initialize(controller)
@controller = controller
@running = true
end
def run
puts "Welcome to the Cookbook!"
puts " -- "
while @running
display_tasks
action = gets.chomp.to_i
print `clear`
route_action(action)
end
end
private
def route_action(action)
case action
when 1 then @controller.list
when 2 then @controller.create
when 3 then @controller.destroy
when 4 then @controller.import
when 5 then @controller.mark_as_tested
when 6 then @controller.search
when 99 then stop
else
puts "Please press 1, 2, 3, 4, 5 or 99"
end
end
def stop
@running = false
end
def display_tasks
puts ""
puts "What do you want to do next?"
puts "1 - List all recipes"
puts "2 - Create a new recipe"
puts "3 - Destroy a recipe"
puts "4 - Import from epicurious"
puts "5 - Mark as tested"
puts "6 - Find a recipe"
puts "99 - Leave"
end
end
class View
def print_recipes(recipes)
puts '-------------------------------------'
recipes.each_with_index do |recipe, index|
puts "#{index + 1}. #{recipe.name} : #{recipe.description} - Rating: #{recipe.rating}/4 - Tested: #{recipe.tested ? 'OK' : 'No'}"
end
puts '-------------------------------------'
end
def ask_name
ask_something 'The recipe name?'
end
def ask_description
ask_something 'The recipe description?'
end
def ask_recipe_index
ask_something('Which recipe number to delete?').to_i - 1
end
def ask_search_term
ask_something('What would you like to search for?')
end
def print_results(results)
results.each_with_index do |result, index|
puts "#{index+1}. #{result}"
end
end
def ask_which_recipe
ask_something('Which recipe would you like to import?').to_i - 1
end
def ask_mark_as_tested
ask_something('Which recipe would you mark as tested?').to_i - 1
end
def ask_for_search
ask_something('Search by?')
end
private
def ask_something(label)
puts label
print '> '
gets.chomp
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment