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

Hannah's Chitter Challenge #232

Open
wants to merge 6 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
3 changes: 3 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 @@ -83,6 +85,7 @@ GEM
nokogiri (~> 1.8)

PLATFORMS
arm64-darwin-21
x86_64-darwin-20

DEPENDENCIES
Expand Down
118 changes: 99 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,35 @@
## 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.
- 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!');`
- 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 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`
- 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.

Expand All @@ -39,28 +40,107 @@ As a Maker
So that I can see what people are doing
I want to see all the messages (peeps)
in a browser


| Component | Responsibility | Refactor |
| ---------- | ------------------------------------------- | --------------------------------- |
| Model | Encapsulate logic with relevant data | Encapsulate peep data in a class |
| View | Display the result to a user | Show the peep data in a list |
| Controller | Get data from the model and put in the view | Render peep data into to the view |
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice to see your approach laid out like this, it shows good understanding of the MVC model.

```

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

- Adding a new message - /peeps/new
- Typing a message into a form on that page
- Submitting that form
- Seeing the message just submitted

```

```
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
```

# Hannah's Chitter Challenge

Brief description of what the project is

## Getting started

`git clone path-to-your-repo`

- list gems in the Gemfile:
source 'https://rubygems.org'

ruby '3.0.2'

gem 'pg'
gem 'sinatra'

group :test do
gem 'capybara'
gem 'rspec'
gem 'simplecov', require: false
gem 'simplecov-console', require: false
end

group :development, :test do
gem 'rubocop', '1.20'
end
Comment on lines +92 to +109
Copy link
Contributor

Choose a reason for hiding this comment

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

Typically you'd leave details like that out of the README since those are already in your code. Someone that just wants the code will skip straight to how to install depedencies, tests and how to run the app (what you have described below). Someone interested in more details can take a look at the code inside the files.


- bundle install
- rspec --init
- setup basic Sinatra app in app.rb (Root directory)

# in app.rb

require 'sinatra/base'
require 'sinatra/reloader'

class Chitter < Sinatra::Base
configure :development do
register Sinatra::Reloader
end

get '/' do
'Hello World'
end

run! if app_file == $0
end

- configure 'rackup' command to run the app in app.rb via config.ru file

# in config.ru

require_relative "./app"

run Chitter

## Usage

- ruby app.rb => Navigate to `http://localhost:4567/`

## Running tests

- rspec
30 changes: 28 additions & 2 deletions app.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,34 @@
require 'sinatra/base'
# require 'sinatra/reloader'
require './lib/peep'

class Chitter < Sinatra::Base
get '/test' do
'Test page'
# configure :development do
# register Sinatra::Reloader
# end

# get '/' do
# 'Hello World'
# end
Comment on lines +6 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.

It's always a good idea to remove test code and commented out code from your files before you submit for code review (anywhere, not just at Makers). It's all about clean code :)


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

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

post '/peeps' do
# p params
# p "Form data submitted to the /peeps route!"
# message = params['message']
# connection = PG.connect(dbname: 'chitter_test')
# connection.exec("INSERT INTO peeps (message) VALUES('#{message}')")
Peep.create(message: params[:message], username: params[:username])
Copy link
Contributor

Choose a reason for hiding this comment

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

Adding a username is a nice idea :)

redirect '/peeps'
end

run! if app_file == $0
Expand Down
1 change: 1 addition & 0 deletions db/migrations/02_add_username_to_peeps.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE peeps ADD COLUMN username VARCHAR(60);
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice migration, it's easy to forget to add those!

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

class Peep
attr_reader :id, :username, :message

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

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

result = connection.exec("SELECT * FROM peeps;")
result.map do
Peep.new(id: result[0]['id'], username: result[0]['username'], message: result[0]['message'])
end
end

def self.create(username:, message:)
if ENV['ENVIRONMENT'] == 'test'
connection = PG.connect(dbname: 'chitter_test')
else
connection = PG.connect(dbname: 'chitter')
end
Comment on lines +26 to +30
Copy link
Contributor

Choose a reason for hiding this comment

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

This piece of code appears several times in this file. How might you remove this duplication?


# I've broken it on to two lines to make it a bit more readable
result = connection.exec_params(
# The first argument is our SQL query template
# The second argument is the 'params' referred to in exec_params
# $1 refers to the first item in the params array
# $2 refers to the second item in the params array
"INSERT INTO peeps (username, message) VALUES($1, $2) RETURNING id, username, message;", [username, message]
Comment on lines +34 to +38
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice!

)
Peep.new(id: result[0]['id'], username: result[0]['username'], message: result[0]['message'])
end
end
8 changes: 8 additions & 0 deletions spec/database_helpers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# in spec/database_helpers.rb
require 'pg'

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

feature 'Adding a new peep' do
scenario 'A user can add a peep to Chitter' do
visit('/peeps/new')
fill_in('username', with: 'Username')
fill_in('message', with: 'An example of a peep')
click_button('Submit')

expect(page).to have_content 'Username, An example of a peep'
Copy link
Contributor

Choose a reason for hiding this comment

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

A solid feature test!

end
end
12 changes: 6 additions & 6 deletions spec/features/test_page_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
feature 'Viewing test page' do
scenario 'visiting the test page' do
visit('/test')
expect(page).to have_content "Test page"
end
end
# feature 'Viewing test page' do
# scenario 'visiting the test page' do
# visit('/')
# expect(page).to have_content "Hello World"
# end
# end
Copy link
Contributor

Choose a reason for hiding this comment

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

You can feel free to remove any seed files once you don't need them anymore :)

18 changes: 18 additions & 0 deletions spec/features/viewing_peeps_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
feature 'Viewing peeps' do
scenario 'A user can see peeps' do
# connection = PG.connect(dbname: 'chitter_test')

# # Add the test data
# connection.exec("INSERT INTO peeps VALUES(1, 'This is a peep!');")

# Peep.create(username: 'User1', message: 'This is a peep!')
# Peep.create(username: 'User2', message: 'Here is another peep!')
Peep.create(username: 'User3', message: 'One more peep!')

visit('/peeps')

# expect(page).to have_content("User1, This is a peep!")
# expect(page).to have_content("User2, Here is another peep!")
expect(page).to have_content("User3, One more peep!")
end
end
44 changes: 44 additions & 0 deletions spec/peep_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
require 'peep'
require 'database_helpers'

# describe Peep do
# describe '.all' do
# it 'returns all peeps' do
# peep = Peep.all

# expect(peep).to include("This is a peep!")
# end
# end
# end

describe '.all' do
it 'returns a list of peeps' do
connection = PG.connect(dbname: 'chitter_test')

# Add the test data
peep = Peep.create(username: "User1", message: "This is a peep!")
Peep.create(username: "User2", message: "Here is another peep!")
Peep.create(username: "User3", message: "One more peep!")

peeps = Peep.all

expect(peeps.length).to eq 3
expect(peeps.first).to be_a Peep
expect(peeps.first.id).to eq peep.id
expect(peeps.first.username).to eq 'User1'
expect(peeps.first.message).to eq 'This is a peep!'
Comment on lines +25 to +29
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 great that you checked that every field in the peep matches what you expect.
Could you go further?
What if, for example, a bug was introduced in the future that causes Peep.all to return the first peep 3 times? Would your test catch this bug?

Since peeps have three things in it, a thorough test would be to check that each item in the array matches what you expect, not just the first one.

Copy link
Author

Choose a reason for hiding this comment

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

Thank you Simo for your feedback!
This did happen (returning the first peep 3 times) and I didn't know how to deal with it.
I do hope to get the chance to come back and have another go at it 😊.

end
end

describe '.create' do
it 'creates a new peep message' do
peep = Peep.create(username: 'Username', message: 'An example of a peep')

persisted_data = persisted_data(id: peep.id)

expect(peep).to be_a Peep
expect(peep.id).to eq persisted_data['id']
expect(peep.username).to eq 'Username'
expect(peep.message).to eq 'An example of a peep'
end
end
2 changes: 2 additions & 0 deletions spec/setup_test_database.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
require 'pg'

def setup_test_database
p "Setting up test database..."
connection = PG.connect(dbname: 'chitter_test')
# Clear the peeps table
connection.exec("TRUNCATE peeps;")
end

Expand Down
3 changes: 2 additions & 1 deletion spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@
])
SimpleCov.start

ENV['RACK_ENV'] = 'test'
# ENV['RACK_ENV'] = 'test'
ENV['ENVIRONMENT'] = 'test'


# Bring in the contents of the `app.rb` file. The below is equivalent to: require_relative '../app.rb'
require File.join(File.dirname(__FILE__), '..', 'app.rb')

Expand Down
7 changes: 7 additions & 0 deletions views/index.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<ul>
<% @peeps.each do |peep| %>
<li>
<%= peep.username %>, <%= peep.message %>
</li>
<% end %>
</ul>
5 changes: 5 additions & 0 deletions views/new.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<form action="/peeps" method="post">
<input type="text" name="message" placeholder="Enter peep message" />
<input type="text" name="username" placeholder="Username" />
<input type="submit" value="Submit" />
</form>