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

Chitter solo challenge #231

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ group :test do
gem 'rspec'
gem 'simplecov', require: false
gem 'simplecov-console', require: false
gem 'timecop'
end

group :development, :test do
Expand Down
5 changes: 5 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ GEM
mini_mime (1.1.1)
mustermann (1.1.1)
ruby2_keywords (~> 0.0.1)
nokogiri (1.12.3-arm64-darwin)
racc (~> 1.4)
nokogiri (1.12.3-x86_64-darwin)
racc (~> 1.4)
parallel (1.20.1)
Expand Down Expand Up @@ -78,11 +80,13 @@ GEM
terminal-table (3.0.1)
unicode-display_width (>= 1.1.1, < 3)
tilt (2.0.10)
timecop (0.9.5)
unicode-display_width (2.0.0)
xpath (3.2.0)
nokogiri (~> 1.8)

PLATFORMS
arm64-darwin-21
x86_64-darwin-20

DEPENDENCIES
Expand All @@ -93,6 +97,7 @@ DEPENDENCIES
simplecov
simplecov-console
sinatra
timecop

RUBY VERSION
ruby 3.0.2p107
Expand Down
64 changes: 20 additions & 44 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,66 +1,42 @@
## Chitter Challenge
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice README, it's very clear.

# Chitter

* Challenge time: until the end of the day
* Feel free to use google, your notes, books etc but please work on your own
* Please raise a pull request when you start this challenge, and keep pushing updates as and when you make commits throughout the day
* There is _no expectation_ to finish all or any of the user stories, please use this time to reflect on where you feel you are with the skill and what may support your learning.
* If you get blocked, please reflect on what blocked you and any strategies you adopted that helped you make progress.
Chitter is a databased backed web application that allows a user to view and post messages (peeps).

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

## Set up
```
git clone https://github.com/olliefreeman94/chitter-challenge-apprenticeships.git
```

To setup the database:

* Connect to psql
* Create the database using the psql command `CREATE DATABASE chitter;`
* Connect to the database using the psql command `\c chitter`;
* Run the query we have saved in the file 01_create_chitter_table.sql
* Populate your table with a row by running `INSERT INTO peeps (message) values ('This is a peep!');`

To check you have everything set up ok, please take a look at the peeps table inside the chitter database. You should see one row in there.
* Connect to the database using the psql command `\c chitter`
* Run the query saved in 01_create_chitter_table.sql
* Run the query saved in 02_add_date_to_peeps.sql

To setup the test database:
* Connect to psql
* Create the database using the psql
command `CREATE DATABASE chitter_test;`;
* Create the database using the psql command `CREATE DATABASE chitter_test;`
* Connect to the database using the psql command `\c chitter_test`
* Run the query we have saved in the file 01_create_chitter_table.sql

* `bundle install`
* `rspec`

You should see 1 passing test.

## User stories
* Run the query saved in 01_create_chitter_table.sql
* Run the query saved in 02_add_date_to_peeps.sql

```
As a Maker
So that I can see what people are doing
I want to see all the messages (peeps)
in a browser
bundle install
```

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

```
As a Maker
So that I can see when people are doing things
I want to see the date the message was posted
rackup
```
(Hint the database table will need to change to store the date too)

Navigate to `http://localhost:9292/`

## Running tests

```
As a Maker
So that I can easily see the latest peeps
I want to see a list of peeps in reverse chronological order
```
```
As a Maker
So that I can find relevant peeps
I want to filter on a specific keyword
rspec
```
29 changes: 29 additions & 0 deletions app.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,38 @@
require 'sinatra/base'
require_relative './lib/peep'

class Chitter < Sinatra::Base
get '/test' do
'Test page'
end
Comment on lines 5 to 7
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's always a good idea to remove test code from code you submit for code review (anywhere, not just at Makers)


get '/' do
erb :index
end

get '/peeps' do
@peeps = Peep.all
erb :'peeps/index'
end

post '/peeps' do
Peep.add(message: params[:message], date: params[:date])
redirect '/peeps'
end

get '/peeps/new' do
erb :'peeps/new'
end

get '/peeps/search' do
erb :'peeps/search'
end

get '/peeps/filtered' do
@peeps = Peep.filter(params[:keyword])
@view_all_button = 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw further down that you're using this as a kind of boolean flag, in which case it would be better to make your intention explicit here and set this to true rather than one.

erb :'peeps/index'
end
Comment on lines +23 to +35
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You've shown good use of RESTful routes 👍🏽


Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clean and concise. I can follow the workflow from how the methods are structured.

run! if app_file == $0
end
66 changes: 66 additions & 0 deletions challenge_outline.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
## Chitter Challenge

* Challenge time: until the end of the day
* Feel free to use google, your notes, books etc but please work on your own
* Please raise a pull request when you start this challenge, and keep pushing updates as and when you make commits throughout the day
* There is _no expectation_ to finish all or any of the user stories, please use this time to reflect on where you feel you are with the skill and what may support your learning.
* If you get blocked, please reflect on what blocked you and any strategies you adopted that helped you make progress.

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

## Set up

To setup the database:

* Connect to psql
* Create the database using the psql command `CREATE DATABASE chitter;`
* Connect to the database using the psql command `\c chitter`;
* Run the query we have saved in the file 01_create_chitter_table.sql
* Populate your table with a row by running `INSERT INTO peeps (message) values ('This is a peep!');`

To check you have everything set up ok, please take a look at the peeps table inside the chitter database. You should see one row in there.

To setup the test database:
* Connect to psql
* Create the database using the psql
command `CREATE DATABASE chitter_test;`;
* Connect to the database using the psql command `\c chitter_test`
* Run the query we have saved in the file 01_create_chitter_table.sql

* `bundle install`
* `rspec`

You should see 1 passing test.

## User stories

```
As a Maker
So that I can see what people are doing
I want to see all the messages (peeps)
in a browser
```

```
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 when people are doing things
I want to see the date the message was posted
```
(Hint the database table will need to change to store the date too)

```
As a Maker
So that I can easily see the latest peeps
I want to see a list of peeps in reverse chronological order
```
```
As a Maker
So that I can find relevant peeps
I want to filter on a specific keyword
```
1 change: 1 addition & 0 deletions db/migrations/02_add_date_to_peeps.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE peeps ADD COLUMN date DATE;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Separate migration file -- great. And DATE is an appropriate datatype to use. Another option would have been to use TIMESTAMP. That would give you flexibility in the future if it ever becomes necessary to show time information too.

50 changes: 50 additions & 0 deletions lib/peep.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
require 'pg'

class Peep

attr_reader :id, :message, :date

def initialize(id:, message:, date:)
@id = id
@message = message
@date = date
end

def self.all
if ENV['ENVIRONMENT'] == 'test'
connection = PG.connect(dbname: 'chitter_test')
else
connection = PG.connect(dbname: 'chitter')
end
Comment on lines +14 to +18
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're using this same piece of code in more than one place in this file. How might you get rid of this duplication?


result = connection.exec("SELECT * FROM peeps ORDER BY date DESC")
result.map { |peep| Peep.new(id: peep['id'], message: peep['message'], date: peep['date']) }
end

def self.add(message:, date:)
if ENV['ENVIRONMENT'] == 'test'
connection = PG.connect(dbname: 'chitter_test')
else
connection = PG.connect(dbname: 'chitter')
end

result = connection.exec_params(
"INSERT INTO peeps (message, date) VALUES($1, $2) RETURNING id, message, date;",
[message, date]
).first
Peep.new(id: result['id'], message: result['message'], date: result['date'])
end

def self.filter(keyword)
if ENV['ENVIRONMENT'] == 'test'
connection = PG.connect(dbname: 'chitter_test')
else
connection = PG.connect(dbname: 'chitter')
end

result = connection.exec(
"SELECT * FROM peeps WHERE message ILIKE '%#{keyword}%' ORDER BY date DESC"
)
Comment on lines +45 to +47
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice use of ILIKE!

result.map { |peep| Peep.new(id: peep['id'], message: peep['message'], date: peep['date']) }
end
end
13 changes: 13 additions & 0 deletions notes.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Next steps
- review format in which date is displayed to user
- add validation to forms
- consolidate helper classes into one file?
- merge or link '/' and 'peeps' routes?
- pathing between routes

Additional features
- record time as well as date
- message character limit validation
- cf. Bookmark Manager extensions,
e.g. update (inc. logging?), delete, user authentication
- equivilent of Twitter #

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good use of notes and to do to plan next steps

7 changes: 7 additions & 0 deletions spec/database_helpers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require 'pg'

def persisted_data(id:)
connection = PG.connect(dbname: 'chitter_test')
result = connection.query("SELECT * FROM peeps WHERE id = #{id};")
return result.first
end
13 changes: 13 additions & 0 deletions spec/features/creating_messages_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
require 'timecop'

feature 'adding a new message' do
scenario 'a user can add a message to Chitter' do
Timecop.freeze(Time.local(2022, 7, 15)) do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool! Timecop is useful. Another option that doesn't require a gem would have been to stub the return value of Time.now, e.g.

@date = Time.local(2022, 7, 15)
allow(Time).to receive(:now).and_return(@date)

visit('/peeps/new')
fill_in('message', with: 'Example peep')
click_button('Submit')
end

expect(page).to have_content 'Example peep (2022-07-15)'
end
end
14 changes: 14 additions & 0 deletions spec/features/filtering_messages_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
feature 'filtering messages' do
scenario 'a user can filter messages by keyword' do
Peep.add(message: 'Banana peep', date: '2022-07-15')
Peep.add(message: 'Apple', date: '2022-07-10')
Peep.add(message: 'Another banana peep', date: '2022-07-05')

visit('/peeps/search')
fill_in('keyword', with: 'banana')
click_button('Search')

expect(page).to have_content "Banana peep (2022-07-15)"
expect(page).to have_content "Another banana peep (2022-07-05)"
Comment on lines +11 to +12
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is good but doesn't exclude the possibility that the other non-banana peeps are also on the page! How could you test for that?

end
end
43 changes: 43 additions & 0 deletions spec/features/pathing_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
feature 'pathing between routes' do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very thorough, nice!

scenario 'from homepage user can view all messages' do
add_row_to_test_database
visit '/'
click_button 'View all peeps'

expect(page).to have_content "This is a peep!"
end

scenario 'from homepage user can add a new message' do
visit '/'
click_button 'Add a new peep'

expect(page).to have_content "New peep"
end

scenario "from '/peeps' user can add a new message" do
visit '/peeps'
click_button 'Add a new peep'

expect(page).to have_content "New peep"
end

scenario "from '/peeps' user can filter messages by keyword" do
visit '/peeps'
click_button 'Filter peeps by keyword'

expect(page).to have_content "Search"
end

scenario 'from filtered search results, user can view all messages' do
Peep.add(message: 'Banana peep', date: '2022-07-15')
Peep.add(message: 'Apple peep', date: '2022-07-10')
visit '/peeps/search'
fill_in('keyword', with: 'banana')
click_button 'Search'

click_button 'View all peeps'

expect(page).to have_content "Apple peep"
end

end
2 changes: 1 addition & 1 deletion spec/features/test_page_spec.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
feature 'Viewing test page' do
feature 'viewing test page' do
scenario 'visiting the test page' do
visit('/test')
expect(page).to have_content "Test page"
Expand Down