This is a Bootcamp
Attending a coding bootcamp is like drinking water through a fire hose. Don't believe me? I prefer to write technically and there will be technical aspects in this post and things that were learned, however; I feel strongly that the comprehensive list that were were expected to learn over the last 3 weeks was just so incredible vast that the retention of the material is somewhere in the 30 - 40% range.
Three weeks... one language cool as students that were already accustomed to the pace of the boot camp lifestyle of coding and lectures 12 hours a day for 6 weeks with JavaScript and React under our belts feeling confident after finishing front end projects that did feel incomplete because we have yet to learn a backend language the cohort was excited to dive into Ruby a back end language and tie the life of a full-stack software engineer together. How I personally thought the phase was going to go ended up being quite the divergent path with slow progress learning a lot of small little steps and a lot of growing pains.
The divisions below are going to go into things that were learned in this project but it was not just Ruby. In order to leverage the most in this phase we had to learn a few more tools. ActiveRecord, and Sinatra...
Phase 3 Ruby
Excited to learn ruby. What is Ruby? It was designed with an emphasis on programming productivity and simplicity. in Ruby everything is an object, that is how we started learning new syntax which was fairly straight forward, easy to read and easy to code:
def greet_programmer
puts "Hello, programmer!"
end
def greet(name)
puts "Hello, #{name}!"
end
def greet_with_default(name = "programmer")
puts "Hello, #{name}!"
end
def add(num1, num2)
num1 + num2
end
A few simple methods with simple code. The puts command is a simple command in Ruby that just prints to the page. Ruby has implicit returns that the line before the end is automatically returned in the method. It seemed simple easy to read and easy to write. Practicing the syntax learning the new language was a growing pain but that is a growing pain is with every new language.
We were off to the races learning ruby writing methods and leveraging objects, everything that ruby promised us we would learn.
Active Record
This phase also gave us the incredible tool of Active Record. Active record was powerful, gave us the ability to create database tables, create associations between those tables with the easy to learn macros (belongs_to and has_many) giving us methods we could use to leverage those associations in Ruby. We learned how to call class and instance methods on our databases on the back end through the use of rake console.
Methods were working Associations were being made:
class Team < ActiveRecord::Base
belongs_to :owner
has_many :players
def drop(player_id)
self.update(team_id: nil)
end
def homerun_count
self.players.sum(&:homeruns)
end
def owner_name
puts "#{self.owner.user_name}"
end
end
The above code would allow us to run association methods such as Team.first.players
giving us all the players for the first team. Team.first.homerun_count
giving us all the homeruns for the first(given)team.
All of this felt natural. Giving commands in the rake console methods are working properly and associations were made.
Up to this point of the phase it was a lot of information we learned a lot of new things and were able to put an arsenal of skills in our brains that is our metaphorical bag of holding....
Project Week and learning Sinatra
I am going to start this segment with the metaphor my eyes were bigger than my stomach.
Project introduction
The project idea was a simple fantasy sports baseball app where you could create a team and add or remove players from your team and the app would keep track of the number of homeruns for your team and update standings as you add or drop players or homeruns are increased.
Checklist
- The frontend was updating state and puting data on the page.
- The backend methods were created with Active Record and Ruby and were all working in the rake console.
- ...Sinatra is where it all fell apart.
Sinatra Routing
The frontend and the back end of our project were not communicating. Were we forgetting steps? Was the browser our own worst enemy? Cors error? Were the wrong gems installed?
installed gems in our Gemfile
gem 'sinatra'
gem 'activerecord', '~> 5.2'
gem 'sinatra-activerecord', :require => 'sinatra/activerecord'
gem 'rake'
gem 'require_all'
gem 'sqlite3'
gem 'thin'
gem 'shotgun'
gem 'pry'
gem 'bcrypt'
gem 'tux'
gem 'faker'
gem 'dotenv'
gem 'rack-cors'
gem 'rack-contrib'
gem 'rerun'
Code in our config.ru
require './config/environment'
use Rack::Cors do
allow do
origins '*'
resource '*', headers: :any, methods: [:get, :post, :delete, :put, :patch, :options, :head]
end
end
use Rack::JSONBodyParser
use Rack::MethodOverride
if ActiveRecord::Base.connection.migration_context.needs_migration?
raise 'Migrations are pending. Run `rake db:migrate` to resolve the issue.'
end
run ApplicationController
use OwnersController
use TeamsController
use PlayersController
Step by step and line by line we check boxes as we coded in config.ru to avoid getting errors. Was this enough lets find out.
Our first Sinatra Route in our players controller:
get "/players" do
player = Player.all
player.to_json
end
Our fetch call on or React frontend Side:
useEffect(() => {
const fetchData = async () => {
try {
const resp = await fetch("http://localhost:9292/players")
const playersList = await resp.json()
setPlayers(playersList)
} catch (error) {
alert(error)
}
}
fetchData()
}, [])
...It worked!!!! after hours of wrestling with Sinatra to make sure we did everything correct we finally were getting our player database talking to our frontend and render information to the page.
later we changed the Sinatra route to
get "/players" do
player = Player.all
player.to_json(include: :team)
end
and what the (include: :team)
did was allow us to leverage the association between our players and teams table. This unfortunately did not come until hours later when the information came to light that we could do that.
For the week that was how the project went... slow coding a lot of research, find the answer, a lot of code, back down to a crawl again and then back to research. This loop repeated intensely all week with what sometimes felt backwards progress.
Table Associations in the project
Achieving full CRUD on one of our tables felt like a huge accomplishment. We had routes to Create, Read, Update and Destroy on our players table. This felt like a victory however the power of the backend of ruby and active record was about being able to leverage associations which we had yet to achieve. This was the biggest hurdle to date so my talented partner Dylan Curtis and myself got to work rolled up with our sleeves and this is what we learned.
Adding and Dropping Players from the team
There is no place in ding dong city for you.
The main focus of our app was to leverage players on our teams to see who could project the most homeruns on the season. We needed to be able to create teams, add or remove players from our teams, add new players to be selected in the data base and finally update homeruns on our players.
we did that with CRUD actions. Fetch calls in React didn't change much but we did need to create correct routing in Sinatra to be able to communicate with our frontend.
CRUD
GET
get "/players" do
ply = Player.all
ply.to_json(include: :team)
POST
Adding a player to the open roster.
post "/players" do
ply = Player.create(first_name: params[:firstName],
last_name: params[:lastName],
player_number: params[:playerNumber],
professional_team: params[:professionalTeam],
position: params[:position],
homeruns: 0,
team: nil,
img_url: params[:imgURL])
if ply.id
halt 201, {ply: ply}.to_json
else
halt 400, {message: ply.errors.full_messages.to_sentence}.to_json
end
end
Patches
(we had 2 for this project and one did double duty)
patch "/players/:id/add_player" do
player = Player.find_by(id: params[:id])
if player
player.update(team_id: params[:team_id])
halt 200, player.to_json(include: :team)
else
halt 400, player.errors.full_messages.to_sentence.to_json
end
end
and of corse we needed to add homeruns with our custom methods.
patch "/players/:id/homerun" do
# binding.pry
found_player = Player.find_by(id: params[:id])
if found_player && found_player.add_homerun
halt 200, found_player.to_json(include: :team)
else
halt 400, found_player.errors.full_messages.to_sentence.to_json
end
end
Delete
this allowed us to remove our players from the league. Gone from the database.
delete "/players/:id" do
ply = Player.find(params[:id])
ply.destroy
ply.to_json
Conclusion
This project had a huge learning curve for me and my partner. A lot of time was spent researching and debugging problems. Organization for this project got away from us at times, but in the end we achieved the minimum project and still have a lot of work to do with this project. This blog post will be updated and have more to come on a finished project as we refactor code and add features.
Top comments (0)