Let’s say your company manages books. And not like account records, but perhaps books in a store, or a catalog of books available to check out.
Books present a more complicated data model because there are so many of them! And there are many attributes that you might want to track, starting with the title and author, and moving into important but obscure items like ISBN, Dewey Decimal Number, and binding type. Let’s design a system that can handle a small number of books, but scales as our library grows.
I’m going to create a new rails project called BookData, and then I’ll create a Book model that we’ll use throughout this tutorial. You can get the source code here: https://github.com/johnbeatty/book_data_tutorial/
$ rails new BookData --webpack=stimulus
$ cd BookData
$ rails g model Book title:string author:string publisher:string category:string isbn:string dewey_decimal_number:string binding:integer
$ rails db:migrate
We’re going to make binding
an enum since there are only a few options, so change book.rb
to this:
class Book < ApplicationRecord
enum binding: [:hardcover, :paperback]
end
In order to test our system with a lot of books, I’m going to use the Faker gem to create about 2000 fake books.
In our Gemfile
:
gem 'faker'
Then run
bundle install
Then we’ll create the books in our db/seeds/rb
file.
2_000.times do |i|
Book.create!( title: Faker::Book.title,
author: Faker::Book.author,
publisher: Faker::Book.publisher,
category: Faker::Book.genre,
isbn: "#{Faker::Number.number(3)}-#{Faker::Number.number(1)}-#{Faker::Number.number(2)}-#{Faker::Number.number(6)}-#{Faker::Number.number(1)}",
dewey_decimal_number: "#{Faker::Number.number(3)}.#{Faker::Number.number(3)}",
binding: Faker::Number.between(0,1))
print '.' if i % 100 == 0
end
Now we have a lot of books records that we can use.
Let’s build an index page so that we can look at our books.
We need to update routes.rb
:
Rails.application.routes.draw do
resources :books
end
And we need a app/controllers/books_controller.rb
file with an index action, and we’ll start by loading all the books.
class BooksController < ApplicationController
def index
@books = Book.all
end
end
And finally, a view at app/views/books/index.html.erb
.
<h1>All Books</h1>
<table>
<thead>
<tr>
<th>Title</th>
<th>Author</th>
<th>Publisher</th>
<th>Category</th>
</tr>
</thead>
<tbody>
<% @books.each do |book| %>
<tr>
<td><%= book.title %></td>
<td><%= book.author %></td>
<td><%= book.publisher %></td>
<td><%= book.category %></td>
</tr>
<% end %>
</tbody>
</table>
Run rails s
and visit it in the browser.
I hope this gives you an idea of how you can take a data set with a lot of variation, and model it with just one database table.
Feel free to leave a comment or question below.
More To Come
I’m going to work on some more tutorials on how to slice and dice this data in more user friendly ways. Sign up to get the tutorial when it’s ready.
4 comments on “Modeling More Complex Datasets In Rails”
[…] Modeling More Complex Datasets In Rails […]
[…] Modeling More Complex Datasets In Rails […]
[…] going to work from my previous tutorial, which you can find on […]
[…] continuing to work from my previous tutorials, modeling a complex dataset, and using multi select to pare down a large dataset, which you can find on […]