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

Alice Wood - Chitter Challenge #2198

Open
wants to merge 41 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
360d42e
Project setup
aliceswood May 5, 2023
d14ec56
setting up the chitter database
aliceswood May 9, 2023
e67e34f
organising project READMEs
aliceswood May 9, 2023
953dc11
amending initial approach and creating database connection file
aliceswood May 9, 2023
1092018
updating documentation to have same terminology - peeps
aliceswood May 9, 2023
604b3a0
adding pg gem requirement to Gemfile
aliceswood May 9, 2023
6595839
updating gemfile to have pg gem
aliceswood May 9, 2023
1767ba4
peep repository class - find all peeps tested and passing
aliceswood May 9, 2023
60eaaba
peep repository - add method tdd'ed
aliceswood May 9, 2023
508c071
fixing database connection file to link to correct database
aliceswood May 9, 2023
176f995
updating test to check that peeps are sorted reverse chronologically
aliceswood May 9, 2023
234a3b8
creating the first sinatra path for / test driven - user/name not yet…
aliceswood May 9, 2023
8e30ab1
first draft of homepage printing peeps
aliceswood May 9, 2023
0714fef
added the name and username display for the homepage
aliceswood May 9, 2023
7747e1a
trying to fix the readme initial plan image
aliceswood May 9, 2023
609fd71
Account model and Repository class TDD'ed
aliceswood May 9, 2023
a68c6c8
updating README.md
aliceswood May 10, 2023
a12ddf5
tidying up seed data
aliceswood May 10, 2023
914905f
refactoring some of the sql queries
aliceswood May 10, 2023
e5fe4ad
you can add a peep to the homepage and it redirects you back
aliceswood May 10, 2023
ad29f47
added redirection buttons after peep is submitted
aliceswood May 10, 2023
705a6c6
added sign up link to the homepage - still need to make this conditio…
aliceswood May 10, 2023
7369a9c
sign in page and log in page created ahead of session being implemented
aliceswood May 10, 2023
5a466f8
fixed the sorting of peeps to be via time not just id and unique chec…
aliceswood May 10, 2023
a7a440f
updating readme now that MVP is completed
aliceswood May 10, 2023
97890dd
updated seeds and tests to have test emails as @example.com
aliceswood May 10, 2023
164ed9b
adding my first box to erb file! Also added placeholders to forms and…
aliceswood May 10, 2023
0fcc8b7
some css for the background and font
aliceswood May 10, 2023
a8523c3
updated spec to reflect the css changes in app.rb
aliceswood May 11, 2023
3169b1a
updating view files with css
aliceswood May 11, 2023
2c3a8a4
successful log in working - errors for incorrect details being worked on
aliceswood May 11, 2023
78f04a5
safe navigation operator added for account login
aliceswood May 11, 2023
e084e74
makes the sign up, log in and post conditional on session id
aliceswood May 11, 2023
7fa1780
added a log out button and used sessions to implement
aliceswood May 11, 2023
1770878
fixed the html to try and improve layout - amended tests accordingly
aliceswood May 11, 2023
e493127
update readme
aliceswood May 11, 2023
cdf96be
added bcrypt for passwords
aliceswood May 11, 2023
fd97380
fixing sessions bug and updating html
aliceswood May 12, 2023
fce620c
html edit
aliceswood May 12, 2023
7cf72c3
adding reflection to my README
aliceswood May 12, 2023
e4fe7d0
fixing formatting
aliceswood May 12, 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
9 changes: 9 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,12 @@ end
group :development, :test do
gem 'rubocop', '1.20'
end

gem "sinatra", "~> 3.0"
gem "sinatra-contrib", "~> 3.0"
gem "webrick", "~> 1.8"
gem "rack-test", "~> 2.1"
gem "pg", "~> 1.3"

gem "bcrypt", "~> 3.1"
gem 'byebug'
32 changes: 32 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,22 @@ GEM
specs:
ansi (1.5.0)
ast (2.4.2)
bcrypt (3.1.18)
byebug (11.1.3)
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.5.3)
rack (2.2.7)
rack-protection (3.0.6)
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 +47,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 +58,38 @@ GEM
terminal-table
simplecov-html (0.12.3)
simplecov_json_formatter (0.1.3)
sinatra (3.0.6)
mustermann (~> 3.0)
rack (~> 2.2, >= 2.2.4)
rack-protection (= 3.0.6)
tilt (~> 2.0)
sinatra-contrib (3.0.6)
multi_json
mustermann (~> 3.0)
rack-protection (= 3.0.6)
sinatra (= 3.0.6)
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

DEPENDENCIES
bcrypt (~> 3.1)
byebug
pg (~> 1.3)
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
136 changes: 50 additions & 86 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,123 +1,87 @@
Chitter Challenge
=================

* Feel free to use Google, your notes, books, etc. but work on your own
* If you refer to the solution of another coach or student, please put a link to that in your README
* If you have a partial solution, **still check in a partial solution**
* You must submit a pull request to this repo with your code by 10am Monday morning
Write a small Twitter clone that will allow the users to post messages to a public stream.

Challenge:
-------

As usual please start by forking this repo.

We are going to write a small Twitter clone that will allow the users to post messages to a public stream.

Features:
-------
## How to use

```ruby
$ git clone https://github.com/aliceswood/chitter-challenge.git
$ cd chitter-challenge
$ bundle install
$ createdb chitter_test
$ psql -h 127.0.0.1 chitter_test < spec/seeds/accounts_and_peeps_tables.sql
$ rspec
$ rackup
$ http://localhost:('Port in use')/
```
STRAIGHT UP

As a Maker
So that I can let people know what I am doing
I want to post a message (peep) to chitter
## Initial plan

As a maker
So that I can see what others are saying
I want to see all peeps in reverse chronological order
![initial plan](./initial_plan.png "initial plan")

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
## Initial Approach

As a Maker
So that I can post messages on Chitter as me
I want to sign up for Chitter
1. Set up the Chitter database with test accounts and test peeps so that the homepage has some information prepopulated

HARDER
2. Create AccountRepository, Account & PeepRepository, Peep classes so that new instances of each can be made

As a Maker
So that only I can post messages on Chitter as me
I want to log in to Chitter
3. Create the homepage using GET request so that the test peeps are shown

As a Maker
So that I can avoid others posting messages on Chitter as me
I want to log out of Chitter
4. Create a form to add new peeps using POST request

ADVANCED
5. Once peep is submitted, return to homepage with list of peeps

As a Maker
So that I can stay constantly tapped in to the shouty box of Chitter
I want to receive an email if I am tagged in a Peep
```
6. Create a sign up page so that details are added to the database and user is registered, with error for non unique details

Technical Approach:
-----
7. Add a log in and log out page, which checks the database to match log in details

In the last two weeks, you integrated a database using the `pg` gem and Repository classes. You also implemented small web applications using Sinatra, RSpec, HTML and ERB views to make dynamic webpages. You can continue to use this approach when building Chitter Challenge.

You can refer to the [guidance on Modelling and Planning a web application](https://github.com/makersacademy/web-applications/blob/main/pills/modelling_and_planning_web_application.md), to help you in planning the different web pages you will need to implement this challenge. If you'd like to deploy your app to Heroku so other people can use it, [you can follow this guidance](https://github.com/makersacademy/web-applications/blob/main/html_challenges/07_deploying.md).
## Techonologies used

If you'd like more technical challenge now, try using an [Object Relational Mapper](https://en.wikipedia.org/wiki/Object-relational_mapping) as the database interface, instead of implementing your own Repository classes.
- Excalidraw
- Ruby
- RSpec
- PostgreSQL
- Sinatra
- HTML
- BCrypt
- rack
- rubocop

Some useful resources:
**Ruby Object Mapper**
- [ROM](https://rom-rb.org/)
## Reflection

**ActiveRecord**
- [ActiveRecord ORM](https://guides.rubyonrails.org/active_record_basics.html)
- [Sinatra & ActiveRecord setup](https://learn.co/lessons/sinatra-activerecord-setup)
This challenge to recreate Twitter was a rather daunting project from first look as it was very easy to compare to the platform and think of all the additional features.

Notes on functionality:
------
It was important and useful for me to keep referring back to the user stories to ensure that I was working on the most important and key features to have a MVP.

* You don't have to be logged in to see the peeps.
* Makers sign up to chitter with their email, password, name and a username (e.g. [email protected], password123, Sam Morgan, sjmog).
* The username and email are unique.
* Peeps (posts to chitter) have the name of the maker and their user handle.
* Your README should indicate the technologies used, and give instructions on how to install and run the tests.
I started making my initial plan on Excalidraw and to breakdown the requirements into steps to use as a starting to-do list.

Bonus:
-----
I found that usig the recipe templates helped me to plan my tables for the database (one for accounts and one for peeps)and create some base seed data to prepopulate the site with and test with.

If you have time you can implement the following:
I wrote the account model and repository classes and also the peep account and repository classes to achieve the main functionality of the app.

* In order to start a conversation as a maker I want to reply to a peep from another maker.
I found it useful to build up the HTML view files as I completed the http routes along side as sometimes I found myself encountering 500 status errors that would not give much away in the error message. It was useful for me to be able to have a bit more feedback from my web app itself.

And/Or:
I worked through the ability to add and display peeps before adding the opportunity to sign up, with the functionality to check for unique user details. At this point, the homepage had most of the details but it was not recognising whether a user was signed in.

* Work on the CSS to make it look good.
I was able to use sessions in Sinatra to register when a user was logged in and who it was, they were then able to post as this user.

Good luck and let the chitter begin!
At this point it was a priority for me to encrypt the passwords stored on the database using bcrypt. This took some playing around with to try and understand what was needed and where and it was interesting to use irb to ensure my seed data was also encrypted to ensure my rspec tests were passing also.

Code Review
-----------
I then tried to implement some basic CSS, this is something that I have never used before so it was nice to see some visual changes to my web app.

In code review we'll be hoping to see:

* All tests passing
* High [Test coverage](https://github.com/makersacademy/course/blob/main/pills/test_coverage.md) (>95% is good)
* The code is elegant: every class has a clear responsibility, methods are short etc.
## Goals going forward

Reviewers will potentially be using this [code review rubric](docs/review.md). Referring to this rubric in advance may make the challenge somewhat easier. You should be the judge of how much challenge you want at this moment.
As mentioned before, this project was a big one and there was always more I was wanting to achieve.

Notes on test coverage
----------------------
I would start by adding some better functionality for the sign up page. I would want to add tests to ensure that the user input is in the right format, for example including REGEXs for email addresses and ensuring that forms have no missing data or blank fields. I would also like to work on sanitising user input before storing it to the database.

Please ensure you have the following **AT THE TOP** of your spec_helper.rb in order to have test coverage stats generated
on your pull request:
Going on from this, I think it would be fun to have a looking into Sinatra flash messages to display error or confirmation messages to the user.

```ruby
require 'simplecov'
require 'simplecov-console'

SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([
SimpleCov::Formatter::Console,
# Want a nice code coverage website? Uncomment this next line!
# SimpleCov::Formatter::HTMLFormatter
])
SimpleCov.start
```
I would also like to have a go at the stretch goals of implementing user emailing notifications and implementing threads and replies on the homepage. This would make the web app more interactive with other users.

I would also like to put more time into the CSS styling as I am very aware it is basic at the moment. It would be fun to try implementing navigation bars or a side menu to help with the user direction and use of the site.

You can see your test coverage when you run your tests. If you want this in a graphical form, uncomment the `HTMLFormatter` line and see what happens!
In conclusion I would say that I am happy with the progress I have made on this project and I am glad I got to complete the MVP basic level product needed from the user stories.
110 changes: 110 additions & 0 deletions app.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
require 'sinatra/base'
require 'sinatra/reloader'
require_relative 'lib/account_repository'
require_relative 'lib/peep_repository'
require_relative 'lib/database_connection'

DatabaseConnection.connect

class Chitter < Sinatra::Base
enable :sessions
enable :raise_errors
enable :dump_errors
configure :development do
register Sinatra::Reloader
also_reload 'lib/'
end

# Homepage

get '/' do
p "/"
p session

repo = PeepRepository.new
@peeps = repo.all

accounts = AccountRepository.new

return erb(:homepage)
end

# Peeps

get '/add_peep' do
return erb(:add_a_peep)
end

post '/add_peep' do
repo = PeepRepository.new
peep = Peep.new
peep.time = Time.now
peep.contents = params[:contents]
peep.account_id = '1'

repo.add(peep)

return erb(:posted_peep)
end

# Sign up

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

post '/sign_up' do
repo = AccountRepository.new
account = Account.new
encrypted_password = BCrypt::Password.create(params[:password])
account.email_address = params[:email_address]
account.name = params[:name]
account.username = params[:username]
account.password = encrypted_password

if account.unique?
repo.add(account)
new_account = repo.find_by_email_address(account.email_address)
session[:account_id] = new_account.id
return erb(:new_account_confirmation)
else
status 400
return "This username and/or email address is already in use, please try again!"
end
end

# Log in

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

post '/login' do
accounts = AccountRepository.new
submitted_email = params[:email_address]
submitted_password = params[:password]
account = accounts.find_by_email_address(submitted_email)

if account == nil
status 400
return erb(:login_fail)
end

stored_password = BCrypt::Password.new(account.password)

if stored_password == submitted_password
session[:account_id] = account.id
return erb(:login_success)
else
status 400
return erb(:login_fail)
end
end

# Log out

post '/log_out' do
session[:account_id] = nil
return erb(:logged_out)
end
end
Loading