Skip to content

How to build a Recipe Finder Web Application with Ruby on Rails

Reading Time: 7 minutes

The purpose of this post is to walk you through the creation of a basic but fully functional Ruby on Rails Web Application.

At the end of the tutorial we will have a live Recipe Finder App like the one I generated myself and which you can find and explore here.

Specifically, the process I will illustrate is the result of the 3-week Coursera course “Ruby on Rails: an introduction”, which I just completed and highly recommend. The course is addressed to developers who are totally new to both Ruby and the Rails framework and it guides the student through the whole pipeline from software installation to final app deployment on the web.

Let’s get started then!

Software Installation

The first part is unavoidably software installation and environment setup. I worked on a Windows 7 machine hence all the below instructions apply to Windows operating system only. The tools you will need are the following:

  • Ruby – version 2+
  • Rails – version 4.2.3
  • Git
  • Phantomjs (headless browser for testing purposes)
  • A text editor (I used Sublime Text 3, very nice discovery I would say)

The first three points can be installed as a unique package navigating to http://railsinstaller.org/en,  while for the other two the links are embedded in the above list.

Ruby, Git and Phantomjs are pretty straightforward. As for Rails you need to upgrade from 4.1 (downloaded as part of the rails installer package) to at least 4.2.3. This can be achieved running the below on the command line:

> gem install rails -v 4.2.3

When you are done with the process you can check if the versions installed are the expected ones and then test the whole infrastructure:

> rails -v
Rails 4.2.3
> ruby -v
ruby 2.1.5
> git -- version
git version 1.9.4.msysgit.2
> rails new test_install 
#CREATE TEST WEB APP. OUTPUT SHOWING RAILS BUILDING APP FOLDER STRUCTURE
> cd test_install
> rails server

The very last command starts rails server for our brand new test app. You can check it out navigating to http://localhost:3000/ on your browser. You should be able to see a “Welcome aboard! You are riding Ruby on Rails” web page which is the final confirmation that everything is ready to go.

Basic Ruby on Rails concepts

Before diving into the code I would like to give some very brief context about how Rails works.

The Rails framework lays its foundations on two very important concepts:

  • Convention Over Configuration (CoC): the CoC is a development paradigm  consisting in moving all the decision making about software architecture into a pre-established framework. The idea is to set rules and conventions which the developer follows to build a specific application, with the great advantage of having the framework writing code on behalf of the engineer or not writing code at all. Examples of those commonly agreed assumptions are the following: application dependencies are declared in the Gemfile, Views belong in the app/views directory, Controllers in the app/controllers directory, Models in the app/models directory and so on so forth. A structure like this one is extremely powerful as the developer is freed of the app architecture and of the communication among the parts, resulting in a much faster and painless deployment.
  • Model-View-Controller (MVC): as Wikipedia suggests “the central component of MVC, the model, captures the behavior of the application in terms of its problem domain, independent of the user interface. The model directly manages the data, logic and rules of the application. A view can be any output representation of information, such as a chart or a diagram; multiple views of the same information are possible, such as a bar chart for management and a tabular view for accountants. The third part, the controller, accepts input and converts it to commands for the model or view.”  The interactions between the parts is showed in the below image and it can be summarized as follows.

    The browser sends a request which comes into the rails application. If it is a static page it is automatically redirected to the app/public directory containing static HTML content. If the request is dynamic Rails asks to the router (another independent component of the application) which maps the incoming URL to the correspondent controller with its appropriate action. The controller talks to the model which digests the inputs, involves the data layer (a DB or an external API) and sends the answer back to the controller. After parsing the output from the model the controller passes the chewed information to the view, in charge of the final visualization into the browser.

mvc1

Recipe Finder Development and Deployment

Now we are ready to move to the actual code. Our intent is to write a Recipe Finder application which would let the user specify an ingredient and fetch the relevant recipes from the food2fork API (f2f). The gathered data is then going to be formatted into an HTML table showing the recipe thumbnail, its title and its Social Ranking (as per f2f Ranking Algorithm). Also, image and title will be directly linked to the actual recipe on foof2fork.com. For your reference the whole application is available on Github.

This is the process we are going to follow:

1- Create a new Rails application called recipefinder.

> rails new recipefinder

You can replace the Gemfile generated automatically by Rails with the Gemfile I used for the final deployment on Heroku. It definitely contains the correct dependencies and it should avoid you a couple of future headaches. Make sure to run “bundle install” after that to install all the required dependencies

2- Generate a recipes controller with an index action running the following commands

> cd recipefinder
> rails g controller recipes index

with the below output. As you can see the “rails g controller” command did several things. The screenshot is pretty self explanatory. What happened is that Rails, according to the CoC, generated files (plus folders where needed) which the programmer is supposed to complete during the actual application development. Each one of those files implements a specific part of the app (controller, model, view). It is worth noticing that also the Routing has been taken care of: Rails added a line to the routes.rb file to correctly map the URL in the browser (/recipes/index) to the actual controller’s action.

cap

3- The RecipesController index action checks if a request parameter search is passed in. Use the search term as the keyword if supplied, and use a default value of chocolate if not supplied.

#contents of app/controllers/recipes_controller.rb
class RecipesController < ApplicationController
  def index
  	@search_term = params[:looking_for] || 'chocolate'
  	@recipes = Recipe.for(@search_term)
  end
end

4- Create a model, Recipe (recipe.rb) that contains a for class method. This method takes a keyword to query the Food2Fork API for a result. For this purpose we need to get an API key from the food2fork API service and make use of the very powerful HTTParty gem.

#contents of app/models/recipe.rb
class Recipe
 include HTTParty
 ENV["FOOD2FORK_KEY"] = 'your API key'
 base_uri 'http://food2fork.com/api'
 default_params key: ENV["FOOD2FORK_KEY"]
 format :json

 def self.for term
 get("/search", query: { q: term})["recipes"]
 end
end

5- Create a view that lists each recipe as a row in an HTML table. Each row will have 3 columns, where column 1 contains the thumbnail of the recipe, column 2 its title and column 3 its social rank. In addition do that each entry in column 1 and 2 will be linked to the actual recipe on the f2f website. As a way to keep things as clean as possible we are also taking care of the following situation: if the search term passed to the API does not return any results (basically if the output array is either nil or empty) the application will display a “No recipes found.. Sorry” message.

#contents of app/views/recipes/index.html.erb
<h1>Searching for - <%= @search_term %></h1>
<p>Powered By Food2Fork.com</p>
<% if (@recipes.nil? or @recipes == []) %>
<p> <h2>No recipes found.. Sorry</h2></p>
<% else %>

<table border="1">
 <tr>
 <th>Image</th>
 <th>Name</th>
 <th>Rank</th>
 </tr>
 <% @recipes.each do |course| %>
 <tr class=<%= cycle('even', 'odd') %>>
 <td><%= link_to(image_tag(course["image_url"], height: '100', width: '100'), course["f2f_url"])%></td>
 <td><%= link_to(course["title"], course["f2f_url"]) %></td>
 <td><%= course["social_rank"] %></td>
 </tr>
 <% end %>
</table>
<% end %>

5- Test the recipe finder locally navigating to the app folder and typing “rails server”. The command is going to start the web server our application lives on. You can go to http://localhost:3000/ in a browser window and check the result. You should see a fully functional website responding to modifications to the search parameter in the URL. Pretty cool! Of course we may now want to show what we were capable of putting together to our friends out there. To achieve that the only missing passage is deployment to the cloud.

6- Running the application on Heroku. Heroku is a cloud service which lets users deploy their apps onto its platform. To do that we need to take care of a couple of things

  • Register for a free account to heroku.com
  • Download and install the heroku toolbelt, a Coomand Line Application tool allowing the user to perform admin actions via a shell prompt.
  • Check (and in case correct) the gems being used by Heroku in the production environment. Specifically rails_12factor and postgresql which Heroku relies upon as opposed to sqlite, only supported in development mode. By the way, we already have everything in place as the Gemfile (pasted below for your reference) I provided at the beginning of the tutorial takes care of exactly those caveats.
#contents of app/Gemfile
source 'https://rubygems.org'

gem 'rails', '4.2.3'
gem 'sqlite3', group: :development
gem 'tzinfo-data'
gem 'sass-rails', '~> 5.0'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '~> 4.1.0'
gem 'jquery-rails'
gem 'turbolinks'
gem 'jbuilder', '~> 2.0'
gem 'sdoc', '~> 0.4.0', group: :doc
gem 'therubyracer', platforms: :ruby
gem 'capybara', '~> 2.4.4'
gem 'poltergeist', '~> 1.6.0'
gem 'phantomjs', '~> 1.9.8.0'

group :development, :test do
 # Call 'byebug' anywhere in the code to stop execution and get a debugger console
 gem 'byebug'

 # Access an IRB console on exception pages or by using <%= console %> in views
 gem 'web-console', '~> 2.0'

 gem 'spring'
end

group :production do
 gem 'pg'
 gem 'rails_12factor'
end

gem 'httparty'

After that we are ready to go and start the actual deployment. For this to happen we have to open a shell, navigate to the app folder and type the following commands:

> heroku login
> heroku create your-app-name

The first one is going to ask you for credentials in order to remotely connect to the Heroku platform. Whereas the second one creates the ruby application within the Heroku environment and generates a remote Git repository to which you can push to actually deploy the code. Let’s do that then!

> git push heroku master

With this very last command Heroku detects the Ruby app, checks that everything is in place and pushes the code to the platform. If everything goes as expected you should see around the end of the output a couple of lines like the following:

remote:    https://your-app-name.kerokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.

Congratulations! Your app is live on the web. You can go visit it at the URL specified above (https://your-app-name.herokuapp.com/), start playing with ingredients and get your recipes back.

The web interface is of course very primitive and the user is obliged to directly edit the URL to get dynamic content displayed. Having the contrary was not the purpose of this short post tough. The main point of it was to illustrate the great easiness and flexibility in development and deployment provided by the Ruby on Rails framework. Mission accomplished I would say!

 

Tags:

Discover more from

Subscribe now to keep reading and get access to the full archive.

Continue reading