In this series, called Building a Ruby on Rails app, we'll create a web app that lists books about Ruby on Rails. It should also record the sales rank of the book daily (source from Amazon.com), and show the ranking movement. You can see the finished live site at Books on Rails website.
Our web app is called Books on Rails, so let's create a Rails app with that name:
rails new booksonrails
Isn't that exciting! The familiar command creates a nice new Rails web app for us, ready to be filled with the functionality we have planned.
Let's dive straight into it, by creating the book model.
We want to show a few details about our books: title, author, publication date, and an image. We also want to display a movement on the books' sales rankings. Let's add them to the model generator:
bundle exec rails g model book title:string author:string asin:string published_at:string amazon_image_url:string image_url:string previous_sales_rank:integer last_sales_rank:integer
And create the table on the database:
bundle exec db:migrate
We will create books data via a script that talks to Amazon API, so our controller will be quite small, with just one action:
This will create an empty controller with only the
index action and also the
We take the chance to setup our routes here:
# config/routes.rb Rails.application.routes.draw do resources :books, :only => :index root 'books#index' end
It's important we create only the routes we need, for faster caching, less testing, less code generated, etc..
We'll create a controller test as well:
# test/controllers/books_controller_test.rb class BooksControllerTest < ActionController::TestCase test "should get index" do get :index assert_response :success assert_not_nil assigns(:books) end end
and run the test:
bundle exec rake
The test should fail, complaining that our books is actually nil. So let's fix that:
# app/controllers/books_controller.rb class BooksController < ApplicationController def index @books = Book.order(:last_sales_rank) end end
This will allow us to show the books order by the highest ranked. If we run the test now, it should pass.
Please note that the command
bundle exec rake will run all our tests as it defaults to
bundle exec rake test. If we want to run only the controller test, we can use the command
bundle exec rake test:controllers.
We already have the books'
index.html.erb view created by the generator, and the
application.html.erb layout view. Let's change the latter so it looks like this:
<!DOCTYPE html> <html> <head> <title>Books on Rails</title> <%= stylesheet_link_tag 'application', media: 'all' %> <%= csrf_meta_tags %> </head> <body> <%= render "layouts/header" %> <section class="app-cont"> <%= yield %> </section> <%= render "layouts/footer" %> </body> </html>
bundle command to clean up the gems.
As we saw with our tests earlier, I like to use the conventions that come with Ruby on Rails, as they do a great job to have a full, well structured, and safe application.
Going back to our application layout, we have added a header, a footer, and wrapped the main
yield inside a
div with an
It's important we create these building blocks (header, and footer) into separate partials. This way we can keep our layout clean, and tidy, and organize our code better.
<!-- app/views/layout/_header.html.erb --> <% cache do %> <header class="app-header"> <div class="img"></div> <div class="app-cont"> <h1 class="app-logo"> <%= link_to :root do %> Books <b>on</b> Rails <% end %> </h1> </div> </header> <% end %>
We use the HTML5 semantic markup to create the header, and fill it with a logo and other elements we'll style later. We also wrap the html inside a
cache call, so that the HTML is cached on subsequent requests.
The footer is similar:
<!-- app/views/layout/_footer.html.erb --> <% cache do %> <footer class="app-footer"> <div class="img"></div> <div class="app-cont"> <h1 class="app-logo"> <%= link_to :root do %> Books <b>on</b> Rails <% end %> </h1> <div class="copy"> <%= Time.current.year %> © <%= link_to 'Lugo Labs', 'http://www.lugolabs.com' %>. Data by <%= link_to 'Amazon.com', 'http://www.amazon.com' %>. </div> </div> </footer> <% end %>
If we start the development server now, we can see the header and footer in action, albeit not styled.
In this tutorial we specified the requirements of our simple web app, we created the app, generated the first model, controller and views. At the end we added a simple header and footer with a logo.
In the second part of this series will add a paint of style to our views.
- Books on Rails live example