-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Chitter Challenge Pull Request #2196
Open
aubreysalmins
wants to merge
28
commits into
makersacademy:main
Choose a base branch
from
aubreysalmins:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
da281e4
Add database design recipe
aubreysalmins 126ab38
Add table seeds
aubreysalmins 13d25a5
Update table seeds
aubreysalmins 8d253c2
Modify recipe
aubreysalmins e54671a
Update seeds with test data
aubreysalmins b4960e5
Add project files
aubreysalmins 0edc6de
Create database connection and test database
aubreysalmins 8fabf15
Add User and Peep class info
aubreysalmins 8fd12cd
Add first test
aubreysalmins 0677095
Sinatra setup
aubreysalmins 71fa786
Add first test
aubreysalmins 48353ec
Rubocop errors fixed
aubreysalmins 2be3bba
First test passing
aubreysalmins bb62516
Fix peep class and adjust tests
aubreysalmins 69c57bd
Wrote second test
aubreysalmins de4e5f9
Second test passing
aubreysalmins 62425b5
Add all function to user repository
aubreysalmins 87d46bb
Add find by id
aubreysalmins 7038290
Add create user function
aubreysalmins 2cc8fa3
Add homepage
aubreysalmins 7dab1d6
Add peeps to homepage
aubreysalmins 0f38220
Reverse display order of peeps
aubreysalmins 7d5f23b
Add username to each peep
aubreysalmins 7a3aa2b
New peep test added
aubreysalmins 99f1b12
Update app.rb with new peep post route
aubreysalmins a0884af
Post test failing
aubreysalmins f346f0d
Post test passing
aubreysalmins ffa01c1
Add signup page
aubreysalmins File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
require 'sinatra/base' | ||
require 'sinatra/reloader' | ||
require_relative 'lib/peep_repository' | ||
require_relative 'lib/user_repository' | ||
require_relative 'lib/database_connection' | ||
|
||
DatabaseConnection.connect | ||
|
||
class Application < Sinatra::Base | ||
# This allows the app code to refresh | ||
# without having to restart the server. | ||
configure :development do | ||
register Sinatra::Reloader | ||
end | ||
|
||
get '/' do | ||
peep_repo = PeepRepository.new | ||
@user_repo = UserRepository.new | ||
@peep_list = peep_repo.all | ||
return erb(:index) | ||
end | ||
|
||
post '/' do | ||
repo = PeepRepository.new | ||
@user_repo = UserRepository.new | ||
peep = Peep.new | ||
peep.title = params[:title] | ||
peep.content = params[:content] | ||
peep.time_stamp = Time.new | ||
peep.user_id = 1 | ||
repo.create(peep) | ||
@peep_list = repo.all | ||
return erb(:index) | ||
end | ||
|
||
get "/signup" do | ||
return erb(:signup) | ||
end | ||
end | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# file: config.ru | ||
require './app' | ||
run Application |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
require 'pg' | ||
|
||
# This class is a thin "wrapper" around the | ||
# PG library. We'll use it in our project to interact | ||
# with the database using SQL. | ||
|
||
class DatabaseConnection | ||
# This method connects to PostgreSQL using the | ||
# PG gem. We connect to 127.0.0.1, and select | ||
# the database name given in argument. | ||
def self.connect | ||
if ENV['ENV'] == 'test' | ||
database_name = 'chitter_test' | ||
else | ||
database_name = 'chitter' | ||
end | ||
@connection = PG.connect({ host: '127.0.0.1', dbname: database_name }) | ||
end | ||
|
||
# This method executes an SQL query | ||
# on the database, providing some optional parameters | ||
# (you will learn a bit later about when to provide these parameters). | ||
def self.exec_params(query, params) | ||
if @connection.nil? | ||
raise 'DatabaseConnection.exec_params: Cannot run a SQL query as the connection to'\ | ||
'the database was never opened. Did you make sure to call first the method '\ | ||
'`DatabaseConnection.connect` in your app.rb file (or in your tests spec_helper.rb)?' | ||
end | ||
@connection.exec_params(query, params) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
class Peep | ||
attr_accessor :id, :title, :content, :time_stamp, :user_id | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
require_relative 'peep' | ||
|
||
class PeepRepository | ||
def all | ||
peeps = [] | ||
sql = 'SELECT * FROM peeps' | ||
result_set = DatabaseConnection.exec_params(sql, []) | ||
result_set.each do |record| | ||
peep = Peep.new | ||
peep.id = record['id'].to_i | ||
peep.title = record['title'] | ||
peep.content = record['content'] | ||
peep.time_stamp = record['time_stamp'] | ||
peep.user_id = record['user_id'].to_i | ||
|
||
peeps << peep | ||
end | ||
peeps | ||
end | ||
|
||
def create(peep) | ||
sql = 'INSERT INTO peeps(title, content, time_stamp, user_id) VALUES($1, $2, $3, $4);' | ||
params = [peep.title, peep.content, peep.time_stamp, peep.user_id] | ||
|
||
new_peep = DatabaseConnection.exec_params(sql, params) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
class User | ||
attr_accessor :id, :name, :username, :email, :password | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
require_relative 'user' | ||
|
||
class UserRepository | ||
def all | ||
users = [] | ||
|
||
sql = 'SELECT * FROM users;' | ||
result_set = DatabaseConnection.exec_params(sql, []) | ||
|
||
result_set.each do |record| | ||
user = User.new | ||
user.id = record['id'].to_i | ||
user.name = record['name'] | ||
user.username = record['username'] | ||
user.email = record['email_address'] | ||
user.password = record['password'] | ||
users << user | ||
end | ||
return users | ||
end | ||
|
||
def find(id) | ||
sql = 'SELECT * FROM users WHERE id = $1;' | ||
result = DatabaseConnection.exec_params(sql, [id]) | ||
user = User.new | ||
user.id = result[0]['id'].to_i | ||
user.name = result[0]['name'] | ||
user.username = result[0]['username'] | ||
user.email = result[0]['email'] | ||
user | ||
end | ||
|
||
def create(user) | ||
sql = 'INSERT INTO users(name, username, email, password) VALUES($1, $2, $3, $4);' | ||
params = [user.name, user.username, user.email, user.password] | ||
result = DatabaseConnection.exec_params(sql, params) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
Two Tables Design Recipe Template | ||
|
||
Copy this recipe template to design and create two related database tables from a specification. | ||
|
||
1. Extract nouns from the user stories or specification | ||
|
||
As a Maker | ||
So that I can let people know what I am doing | ||
I want to post a message (peep) to chitter | ||
|
||
As a maker | ||
So that I can see what others are saying | ||
I want to see all peeps in reverse chronological order | ||
|
||
As a Maker | ||
So that I can better appreciate the context of a peep | ||
I want to see the time at which it was made | ||
|
||
As a Maker | ||
So that I can post messages on Chitter as me | ||
I want to sign up for Chitter | ||
|
||
Nouns: peep, time, user, email, username, password | ||
|
||
A user can have many peeps, therefore a peep belongs to a user so the foreign key belongs in the peeps table. | ||
|
||
CREATE TABLE users ( | ||
id SERIAL PRIMARY KEY, | ||
name text, | ||
username text, | ||
email text, | ||
password text | ||
); | ||
|
||
CREATE TABLE peeps ( | ||
id SERIAL PRIMARY KEY, | ||
title text, | ||
content text, | ||
user_id int, | ||
constraint fk_user foreign key (user_id) | ||
references users(id) | ||
on delete cascade | ||
); | ||
|
||
psql -h 127.0.0.1 chitter < chitter_tables.sql | ||
|
||
- | ||
|
||
TRUNCATE TABLE users RESTART IDENTITY CASCADE; | ||
TRUNCATE TABLE peeps RESTART IDENTITY CASCADE; | ||
|
||
INSERT INTO users (name, username, email, password) VALUES ('Aubrey Salmins', 'aubreysalmins', '[email protected]', '123pswd'); | ||
INSERT INTO users (name, username, email, password) VALUES ('Budsy', 'meow-meow', '[email protected]', 'pswd234'); | ||
|
||
INSERT INTO peeps (title, content, user_id) VALUES ('Peep 1', 'Its a peep', 1); | ||
INSERT INTO peeps (title, content, user_id) VALUES ('Meep', 'Meow', 2); | ||
|
||
- | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
require 'spec_helper' | ||
require 'rack/test' | ||
require_relative '../../app' | ||
|
||
def reset_tables | ||
seed_sql = File.read('spec/seeds/chitter_tables.sql') | ||
connection = PG.connect({ host: '127.0.0.1', dbname: 'chitter_test' }) | ||
connection.exec(seed_sql) | ||
end | ||
|
||
describe Application do | ||
before(:each) do | ||
reset_tables | ||
end | ||
# This is so we can use rack-test helper methods. | ||
include Rack::Test::Methods | ||
|
||
# We need to declare the `app` value by instantiating the Application | ||
# class so our tests work. | ||
let(:app) { Application.new } | ||
|
||
context '/' do | ||
it 'should return the homepage' do | ||
response = get('/') | ||
expect(response.status).to eq(200) | ||
expect(response.body).to include('<title>Chitter</title>') | ||
expect(response.body).to include('<h1>Chitter</h1>') | ||
expect(response.body).to include ('<form method="POST" action="/">') | ||
end | ||
|
||
it 'should return all peeps' do | ||
response = get('/') | ||
expect(response.status).to eq(200) | ||
expect(response.body).to include "Peep 1" | ||
expect(response.body).to include "Meow" | ||
end | ||
end | ||
|
||
context 'POST /' do | ||
it 'posts a new peep' do | ||
response = post('/', title: 'New peep', content: 'new peep content') | ||
expect(response.status).to eq 200 | ||
expect(response.body).to include 'New peep' | ||
end | ||
end | ||
|
||
context 'GET /signup' do | ||
it 'gets the signup page' do | ||
response = get('/signup') | ||
|
||
expect(response.status).to eq 200 | ||
expect(response.body).to include '<h2>Sign up</h2>' | ||
expect(response.body).to include '<label>Password</label>' | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
require 'peep_repository' | ||
|
||
def reset_tables | ||
seed_sql = File.read('spec/seeds/chitter_tables.sql') | ||
connection = PG.connect({ host: '127.0.0.1', dbname: 'chitter_test' }) | ||
connection.exec(seed_sql) | ||
end | ||
|
||
describe PeepRepository do | ||
before(:each) do | ||
reset_tables | ||
end | ||
|
||
it "finds all peeps" do | ||
repo = PeepRepository.new | ||
|
||
peeps = repo.all | ||
|
||
expect(peeps.length).to eq(2) | ||
expect(peeps.first.title).to eq('Peep 1') | ||
expect(peeps.first.user_id).to eq(1) | ||
expect(peeps.last.title).to eq('Meep') | ||
expect(peeps.last.user_id).to eq(2) | ||
end | ||
|
||
it "creates a peep" do | ||
repo = PeepRepository.new | ||
peep = double(:peep, title: "Doubler", content: "This is a double", time_stamp: "2021-09-07 12:20:43", user_id: 1) | ||
repo.create(peep) | ||
peeps = repo.all | ||
|
||
peeps = repo.all | ||
expect(peeps.length).to eq 3 | ||
expect(peeps.last.title).to eq 'Doubler' | ||
expect(peeps.last.content).to eq 'This is a double' | ||
expect(peeps.last.time_stamp).to eq '2021-09-07 12:20:43' | ||
end | ||
end |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In order to tidy this up a bit more - by tidying, I mean moving some of the 'business logic' out of the app.rb - you could write something like peep = Peep.new(params[:title], params[:content], etc., passing in these parameters as arguments to a new Peep object, and storing the variables that way instead.
The benefit of doing this is that you push some of the responsibility to the Peep class instead of the app.rb. This will adhere more closely to 'Single Responsibility Principle', which guides us to try to give each class one overarching responsibility.
In the context of a full stack web app, the pattern we follow is Model View Controller, or MVC. In this case, app.rb is the Controller - it's responsible for responding to URL requests / button actions etc. and deciding which code to run - the Models are responsible for structuring our objects like Peeps and Users, and communicating with the database through the Repository classes. And the Views are responsible for what's visible to the user.