Skip to content

jmromer/recipe_finder

Repository files navigation

recipe finder

https://circleci.com/gh/jkrmr/recipe_finder.svg?style=svg

A client web app for the Recipe Puppy API.

Queries the API for the given search term, displaying the first 20 results found with complete data (in particular: including a thumbnail image url).

Demo

https://user-images.githubusercontent.com/4433943/28446489-06203b9a-6d99-11e7-8c5a-aad9cf927521.gif

Libraries

Request handling

Route

# config/routes.rb L4-L5 (37302a48)

  resources :recipes, only: %i(index)
  root to: "static_pages#home"

config/routes.rb#L4-L5 (37302a48)

Controller

# app/controllers/recipes_controller.rb L4-L11 (37302a48)

  def index
    recipes = RecipePuppy
              .query_for_n_entries(n: 20,
                                   query: params[:query],
                                   ingredients: params[:ingredients])

    render :index, locals: { recipes: recipes }, layout: false
  end

app/controllers/recipes_controller.rb#L4-L11 (37302a48)

Models

RecipePuppy: API facade

# app/models/recipe_puppy.rb L3-L5 (37302a48)

class RecipePuppy
  include HTTParty
  base_uri "http://www.recipepuppy.com/api"

app/models/recipe_puppy.rb#L3-L5 (37302a48)

RecipePuppyRecipe API result model

# app/models/recipe_puppy_recipe.rb L3-L17 (888583e0)

class RecipePuppyRecipe
  DEFAULT_THUMBNAIL_URL = "http://img.recipepuppy.com/9.jpg"

  attr_accessor :ingredients_list, :url, :title, :thumbnail_url

  def self.new_collection(attrs_list)
    attrs_list.map { |attrs| new(attrs.with_indifferent_access) }
  end

  def initialize(attrs)
    self.ingredients_list = (attrs[:ingredients] || "").split(/,\s?/).uniq
    self.url = attrs[:href]
    self.thumbnail_url = attrs[:thumbnail].presence || DEFAULT_THUMBNAIL_URL
    self.title = attrs[:title]
  end

app/models/recipe_puppy_recipe.rb#L3-L17 (888583e0)

Client

Client-side code listens for form submissions and for click events emitted from ingredient links:

// app/assets/javascripts/recipe_search.js.es6 L7-L24 (37302a48)

$(() => {
  const $form = $(".js-search-form").first()
  const $resultsContainer = $(".js-search-results").first()

  $form.on("submit", (event) => {
    event.preventDefault()
    const queryParams = $(event.target).serialize()
    queryForRecipes(queryParams, $resultsContainer)
  })

  $resultsContainer.on("click", ".js-search-link", (event) => {
    event.preventDefault()
    const searchTerm = $(event.target).text()
    $form.find("input").val(searchTerm)
    $(document).scrollTop(0)
    queryForRecipes(`ingredients=${searchTerm}`, $resultsContainer)
  })
})

app/assets/javascripts/recipe_search.js.es6#L7-L24 (37302a48)