Copy this recipe template to design and implement Model and Repository classes for a database table.
already done
## 2. Create Test SQL seeds
Your tests will depend on data stored in PostgreSQL to run.
If seed data is provided (or you already created it), you can skip this step.
```sql
-- EXAMPLE
-- (file: spec/seeds.sql)
-- Write your SQL seed here.
-- First, you'd need to truncate the table - this is so our table is emptied between each test run,
-- so we can start with a fresh state.
-- (RESTART IDENTITY resets the primary key)
TRUNCATE TABLE books RESTART IDENTITY; -- replace with your own table name.
-- Below this line there should only be `INSERT` statements.
-- Replace these statements with your own seed data.
INSERT INTO books (title, author_name) VALUES ('Piranesi', 'Suzanne Clarke');
INSERT INTO books (title, author_name) VALUES ('Born a Crime', 'Trevor Noah');
Run this SQL file on the database to truncate (empty) the table, and insert the seed data. Be mindful of the fact any existing records in the table will be deleted.
psql -h 127.0.0.1 book_store_test < seeds.sql
Usually, the Model class name will be the capitalised table name (single instead of plural). The same name is then suffixed by Repository
for the Repository class name.
# EXAMPLE
# Table name: books
# Model class
# (in lib/book.rb)
class Book
end
# Repository class
# (in lib/book_repository.rb)
class BookRepository
end
Define the attributes of your Model class. You can usually map the table columns to the attributes of the class, including primary and foreign keys.
# EXAMPLE
# Table name: books
# Model class
# (in lib/book.rb)
class Book
# Replace the attributes by your own columns.
attr_accessor :id, :title, :author_name
end
# The keyword attr_accessor is a special Ruby feature
# which allows us to set and get attributes on an object,
# here's an example:
#
# student = Student.new
# student.name = 'Jo'
# student.name
You may choose to test-drive this class, but unless it contains any more logic than the example above, it is probably not needed.
Your Repository class will need to implement methods for each "read" or "write" operation you'd like to run against the database.
Using comments, define the method signatures (arguments and return value) and what they do - write up the SQL queries that will be used by each method.
# EXAMPLE
# Table name: books
# Repository class
# (in lib/book_repository.rb)
class BookRepository
# Selecting all records
# No arguments
def all
# Executes the SQL query:
# SELECT id, title, author_name FROM books;
# Returns an array of Book objects.
end
# Gets a single record by its ID
# One argument: the id (number)
end
Write Ruby code that defines the expected behaviour of the Repository class, following your design from the table written in step 5.
These examples will later be encoded as RSpec tests.
# EXAMPLES
# 1
# Get all students
repo = BookRepository.new
books = repo.all
books.length # => 2
books[0].id # => 1
books[0].title # => 'Piranesi'
books[0].author_name # => 'Suzanne Clarke'
books[1].id # => 2
books[1].title # => 'Born a Crime'
books[1].author_name # => 'Trevor Noah'
Encode this example as a test.
Running the SQL code present in the seed file will empty the table and re-insert the seed data.
This is so you get a fresh table contents every time you run the test suite.
# EXAMPLE
# file: spec/book_repository_spec.rb
def reset_books_table
seed_sql = File.read('spec/seeds.sql')
connection = PG.connect({ host: '127.0.0.1', dbname: 'books_test' })
connection.exec(seed_sql)
end
describe BookRepository do
before(:each) do
reset_books_table
end
# (your tests will go here).
end
After each test you write, follow the test-driving process of red, green, refactor to implement the behaviour.