Skip to content
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

Seb's Chitter Challenge #2181

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
58aa6f7
Project setup
sebwylleman Apr 9, 2023
03e9560
setting up my test seeds
sebwylleman Apr 9, 2023
52a309e
sinatra app setup
sebwylleman Apr 9, 2023
51fa443
unit test peep_repository expectations set
sebwylleman Apr 9, 2023
a8f4338
correctly returns all peeps in reverse chronological order
sebwylleman Apr 9, 2023
3fdcc0b
create method to add a new peep
sebwylleman Apr 9, 2023
1556933
all method created and tested on for UserRepository clas
sebwylleman Apr 10, 2023
7c6a683
create method tested
sebwylleman Apr 10, 2023
8a93d76
reformatted
sebwylleman Apr 10, 2023
007e292
test written for find_by_email method
sebwylleman Apr 11, 2023
729e5f1
succesfully finds a valid email
sebwylleman Apr 11, 2023
16d4b85
raise error when given invalid email to find
sebwylleman Apr 11, 2023
1822058
homepage added
sebwylleman Apr 11, 2023
2e18278
homepage renders page correctly
sebwylleman Apr 11, 2023
50c518f
signup form created
sebwylleman Apr 11, 2023
ce2856a
get request for sign up page tested
sebwylleman Apr 12, 2023
bed960d
first test failing for creating a new user
sebwylleman Apr 12, 2023
68226bc
succesfully tested post /signup
sebwylleman Apr 12, 2023
78150e8
displays most recent peeps and redirects to post page
sebwylleman Apr 12, 2023
b2e2413
created and tested new page to input peeps
sebwylleman Apr 12, 2023
01165b7
trying to fix 500 post request error
sebwylleman Apr 12, 2023
0506920
http requests completed. App is now completed
sebwylleman Apr 13, 2023
2b45955
updated seed data to match changes in my real database tables
sebwylleman Apr 13, 2023
5eee738
changed route names
sebwylleman Apr 13, 2023
2569c8f
renaming
sebwylleman Apr 13, 2023
484f701
gemfile gems added/tweaked
sebwylleman Apr 13, 2023
15e7639
Setup for deploy
sebwylleman Apr 13, 2023
43c5f7c
testing git
sebwylleman Apr 24, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,10 @@ end
group :development, :test do
gem 'rubocop', '1.20'
end

gem "pg", "~> 1.4"
gem "sinatra", "~> 3.0"
gem "sinatra-contrib", "~> 3.0"
gem "webrick", "~> 1.8"
gem "rack-test", "~> 2.1"
gem 'bcrypt', '~> 3.1.18'
31 changes: 31 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,21 @@ GEM
specs:
ansi (1.5.0)
ast (2.4.2)
bcrypt (3.1.18)
diff-lcs (1.4.4)
docile (1.4.0)
multi_json (1.15.0)
mustermann (3.0.0)
ruby2_keywords (~> 0.0.1)
parallel (1.20.1)
parser (3.0.2.0)
ast (~> 2.4.1)
pg (1.4.6)
rack (2.2.6.4)
rack-protection (3.0.5)
rack
rack-test (2.1.0)
rack (>= 1.3)
rainbow (3.0.0)
regexp_parser (2.1.1)
rexml (3.2.5)
Expand Down Expand Up @@ -36,6 +46,7 @@ GEM
rubocop-ast (1.11.0)
parser (>= 3.0.1.1)
ruby-progressbar (1.11.0)
ruby2_keywords (0.0.5)
simplecov (0.21.2)
docile (~> 1.1)
simplecov-html (~> 0.11)
Expand All @@ -46,18 +57,38 @@ GEM
terminal-table
simplecov-html (0.12.3)
simplecov_json_formatter (0.1.3)
sinatra (3.0.5)
mustermann (~> 3.0)
rack (~> 2.2, >= 2.2.4)
rack-protection (= 3.0.5)
tilt (~> 2.0)
sinatra-contrib (3.0.5)
multi_json
mustermann (~> 3.0)
rack-protection (= 3.0.5)
sinatra (= 3.0.5)
tilt (~> 2.0)
terminal-table (3.0.1)
unicode-display_width (>= 1.1.1, < 3)
tilt (2.1.0)
unicode-display_width (2.0.0)
webrick (1.8.1)

PLATFORMS
ruby
x86_64-linux

DEPENDENCIES
bcrypt (~> 3.1.18)
pg (~> 1.4)
rack-test (~> 2.1)
rspec
rubocop (= 1.20)
simplecov
simplecov-console
sinatra (~> 3.0)
sinatra-contrib (~> 3.0)
webrick (~> 1.8)

RUBY VERSION
ruby 3.0.2p107
Expand Down
50 changes: 50 additions & 0 deletions app.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
require_relative 'lib/database_connection'
require_relative 'lib/user_repository.rb'
require_relative 'lib/peep_repository.rb'
require 'sinatra/base'
require 'sinatra/reloader'

DatabaseConnection.connect('chitter')

class Application < Sinatra::Base
# Sessions are disabled by default, so this line is needed.
enable :sessions

configure :development do
register Sinatra::Reloader
end

get '/signup' do
return erb(:signup)
end

post '/signup' do
new_user = User.new
new_user.username = params['username']
new_user.email = params['email']
new_user.password = params['password']
created_user = UserRepository.new.create(new_user)
session[:user_id] = created_user.id
redirect '/homepage'
end

get '/homepage' do
repo = PeepRepository.new
@peeps = repo.all
return erb(:homepage)
end

get '/peep' do
return erb(:peep)
end

post '/peep' do
new_peep = Peep.new
new_peep.peep = params[:peep]
new_peep.timestamp = Time.now
new_peep.username_id = session[:user_id]
PeepRepository.new.create(new_peep)
redirect '/homepage'
end
end

Binary file added backup.tar
Binary file not shown.
2 changes: 2 additions & 0 deletions config.ru
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
require './app'
run Application
35 changes: 35 additions & 0 deletions lib/database_connection.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
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(database_name)
@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

def self.setup(dbname)
@connection = PG.connect(dbname: dbname)
@connection.exec("CREATE TABLE IF NOT EXISTS users(id SERIAL PRIMARY KEY, username VARCHAR(60), email VARCHAR(60), password VARCHAR(255));")
end

def self.clear(dbname)
@connection.exec("TRUNCATE TABLE users;")
end
end
3 changes: 3 additions & 0 deletions lib/peep.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class Peep
attr_accessor :id, :peep, :date, :username_id, :timestamp
end
29 changes: 29 additions & 0 deletions lib/peep_repository.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
require_relative 'peep'
require_relative 'database_connection'

class PeepRepository

def all
# returns all rows in reverse chronological order
sql = 'SELECT peep, timestamp, username_id FROM peeps;'
result_set = DatabaseConnection.exec_params(sql, [])

peeps = []
result_set.each do |row|
new_peep = Peep.new
new_peep.id = row['id']
new_peep.peep = row['peep']
new_peep.timestamp = row['timestamp']
new_peep.username_id = row['username_id']
peeps << new_peep
end

return peeps
end

def create(message)
sql = 'INSERT INTO peeps (peep, username_id, timestamp) VALUES ($1, $2, $3);'
result_set = DatabaseConnection.exec_params(sql, [message.peep, message.username_id, message.timestamp])
return message
end
end
3 changes: 3 additions & 0 deletions lib/user.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class User
attr_accessor :id, :username, :email, :password
end
60 changes: 60 additions & 0 deletions lib/user_repository.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
require_relative 'database_connection'
require_relative 'user'
require 'bcrypt'

class UserRepository
def all
sql = 'SELECT * FROM users;'
result_set = DatabaseConnection.exec_params(sql, [])

users = []
result_set.each do |row|
user = User.new
user.id = row['id']
user.username = row['username']
user.email = row['email']
user.password = row['password']
users << user
end

return users
end

def create(user)
encrypted_password = BCrypt::Password.create(user.password)

sql = '
INSERT INTO users (username, email, password)
VALUES($1, $2, $3)
RETURNING id;
'
sql_params = [
user.username,
user.email,
encrypted_password
]
result_set = DatabaseConnection.exec_params(sql, sql_params)

user.id = result_set[0]['id'].to_i

return user
end


def find_by_email(email)
sql = 'SELECT username FROM users WHERE email = $1;'
params = [email]
result = DatabaseConnection.exec_params(sql, params)

if result.ntuples > 0
record = result[0]
user = User.new
user.username = record['username']
user.email = record['email']
user.password = record['password']
return user
else
fail 'No such user with given email.'
end
end
end
53 changes: 53 additions & 0 deletions spec/integration/app_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
require_relative '../../app'
require "spec_helper"
require "rack/test"

describe Application do
# 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 }

describe 'GET /signup' do
it 'returns the signup page' do
response = get('/signup')
expect(response.status).to eq 200
expect(response.body).to include '<input type="username" id="username" name="username" required>'
end
end
describe 'POST /signup' do
it 'creates a new user' do
response = post(
'/signup',
username: 'user1',
email: '[email protected]',
password: '12345678'
)
expect(response.status).to eq(302) # 302 automatically redirects to another URL
expect(UserRepository.new.find_by_email('[email protected]').username).to eq 'user1'
end
end
describe 'GET /homepage' do
it 'returns all peeps from most recent date' do
response = get('/homepage')
expect(response.status).to eq 200
expect(response.body).to include '<h3>Most Recent Peeps</h3>'
end
end
describe 'GET /peep' do
it 'returns the post peep page' do
response = get('/peep')
expect(response.status).to eq 200
expect(response.body).to include '<label for="peep">What are you doing?</label>'
end
end
describe 'POST /peep' do
it 'creates a new peep' do
post '/peep', { peep: 'This is a new peep' }, { 'rack.session' => { user_id: 1 } }
expect(last_response.status).to eq(302)
expect(PeepRepository.new.all.last.peep).to eq('This is a new peep')
end
end
end
39 changes: 39 additions & 0 deletions spec/peep_repository_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
require 'peep_repository.rb'
require 'peep.rb'

def reset_peeps_table
seed_sql = File.read('spec/seeds.sql')
connection = PG.connect({ host: '127.0.0.1', dbname: 'peeps_test' })
connection.exec(seed_sql)
end

describe PeepRepository do
before(:each) do
reset_peeps_table
end

let(:repo) {PeepRepository.new}
let(:new_peep) {Peep.new}

describe '#all' do
it 'returns all peeps in reverse chronological order' do
peeps = repo.all
expect(peeps[0].peep).to eq 'Test peep 1'
expect(peeps[1].peep).to eq 'Test peep 2'
end
end

describe '#create' do
it 'creates and stores a new peep' do
new_peep.peep = 'Test peep 1'
new_peep.timestamp = '2023-04-10 12:34:56'
new_peep.username_id = '1'
repo.create(new_peep)

peeps = repo.all
expect(peeps.last.peep).to eq 'Test peep 1'
expect(peeps.last.timestamp).to eq '2023-04-10 12:34:56'
expect(peeps.last.username_id).to eq '1'
end
end
end
12 changes: 12 additions & 0 deletions spec/seeds.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
TRUNCATE TABLE peeps RESTART IDENTITY CASCADE;
TRUNCATE TABLE users RESTART IDENTITY CASCADE;

INSERT INTO users (username, email, password) VALUES
('user1', '[email protected]', '<hashed_password>'),
('user2', '[email protected]', '<hashed_password>');

INSERT INTO peeps (peep, username_id, timestamp) VALUES
('Test peep 1', 1, '2023-04-10 12:34:56'),
('Test peep 2', 2, '2023-04-11 15:30:00'),
('Test peep 3', 2, '2023-04-12 20:30:00');

Loading