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

Glenn Meyer - Songify ex #446

Open
wants to merge 8 commits into
base: master
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ ruby '2.0.0'

gem 'rspec', '~> 2.14.1'
gem 'pry-byebug'
gem 'pg'
gem 'sinatra'
gem 'rake'
13 changes: 13 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,18 @@ GEM
debugger-linecache (1.2.0)
diff-lcs (1.2.5)
method_source (0.8.2)
pg (0.17.1)
pry (0.10.1)
coderay (~> 1.1.0)
method_source (~> 0.8.1)
slop (~> 3.4)
pry-byebug (2.0.0)
byebug (~> 3.4)
pry (~> 0.10)
rack (1.5.2)
rack-protection (1.5.3)
rack
rake (10.3.2)
rspec (2.14.1)
rspec-core (~> 2.14.0)
rspec-expectations (~> 2.14.0)
Expand All @@ -25,11 +30,19 @@ GEM
rspec-expectations (2.14.5)
diff-lcs (>= 1.1.3, < 2.0)
rspec-mocks (2.14.5)
sinatra (1.4.5)
rack (~> 1.4)
rack-protection (~> 1.4)
tilt (~> 1.3, >= 1.3.4)
slop (3.6.0)
tilt (1.4.1)

PLATFORMS
ruby

DEPENDENCIES
pg
pry-byebug
rake
rspec (~> 2.14.1)
sinatra
50 changes: 50 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@

task :environment do
require './lib/songify.rb'
end

task :console => :environment do
require 'irb'
ARGV.clear
IRB.start
end


namespace :db do

task :create do
`createdb songify_test`
`createdb songify_dev`
puts "Created."
end

task :drop do
`dropdb songify_test`
`dropdb songify_dev`
puts "Dropped."
end

task :create_tables => :environment do
db1 = Songify.create_db_connection('songify_test')
db2 = Songify.create_db_connection('songify_dev')
Songify.create_tables(db1)
Songify.create_tables(db2)
puts "Created tables."
end

task :drop_tables => :environment do
db1 = Songify.create_db_connection('songify_test')
db2 = Songify.create_db_connection('songify_dev')
Songify.drop_tables(db1)
Songify.drop_tables(db2)
puts "Dropped tables."
end

task :clear => :environment do
# The test db clears all the time, so there's no point in doing it here.
db = Songify.create_db_connection('songify_dev')
Songify.drop_tables(db)
puts "Cleared tables."
end

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

module Songify
def self.create_db_connection(dbname)
PG.connect(host: 'localhost', dbname: dbname)
end

def self.clear_db(db)
db.exec <<-SQL
DELETE FROM album_genres;
DELETE FROM songs;
DELETE FROM albums;
DELETE FROM genres;
/* TODO: Clear rest of the tables (books, etc.) */
SQL
end

def self.create_tables(db)
db.exec <<-SQL
CREATE TABLE IF NOT EXISTS albums(
id SERIAL PRIMARY KEY,
title VARCHAR
);
CREATE TABLE IF NOT EXISTS songs(
id SERIAL PRIMARY KEY,
album_id integer REFERENCES albums (id),
title VARCHAR
);
CREATE TABLE IF NOT EXISTS genres(
id SERIAL PRIMARY KEY,
name VARCHAR
);
/* TODO: Create song_genres table */
CREATE TABLE IF NOT EXISTS album_genres(
id SERIAL PRIMARY KEY,
album_id integer REFERENCES albums (id),
genre_id integer REFERENCES genres (id)
);
SQL
end

def self.drop_tables(db)
db.exec <<-SQL
DROP TABLE album_genres;
DROP TABLE songs;
DROP TABLE albums;
DROP TABLE genres;
/* TODO: Drop song_genres table */
SQL
end
end

require_relative 'songify/album_repo'
require_relative 'songify/genre_repo'
require_relative 'songify/song_repo'
56 changes: 56 additions & 0 deletions lib/songify/album_repo.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
require 'pry-byebug'

module Songify
class AlbumRepo

def self.add_genres(db, album_data)
album_id = album_data['id']
album_data['genre_ids'].each do |genre_id|
db.exec("INSERT INTO album_genres (album_id, genre_id) VALUES ($1, $2)", [album_id, genre_id])
end
end

def self.all(db)
db.exec("SELECT * FROM albums").to_a
end

def self.find(db, album_id)
genres = []
result = db.exec("SELECT * FROM albums WHERE id = $1", [album_id]).first
if result
album_genres = db.exec("SELECT * FROM album_genres a JOIN genres g ON g.id = a.genre_id WHERE a.album_id = $1", [album_id]).to_a
album_genres.each do |line|
genres << {'id' => line['genre_id'], 'name' => line['name']}
end
result['genres'] = genres
end
result
end

def self.save(db, album_data)
if album_data['id']
result = db.exec("UPDATE albums SET title = $2 WHERE id = $1", [album_data['id'], album_data['title']])
self.find(db, album_data['id'])
elsif album_data['genre_ids']
album_id = db.exec("INSERT INTO albums (title) VALUES ($1) RETURNING id", [album_data['title']]).first
album_data['id'] = album_id['id']
album_data['genre_ids'].each do |genre|
db.exec("INSERT INTO album_genres (album_id, genre_id) VALUES ($1, $2)", [album_id['id'], genre])
end
album_id
else
raise "title is required." if album_data['title'].nil? || album_data['title'] == ''
result = db.exec("INSERT INTO albums (title) VALUES ($1) RETURNING id", [album_data['title']])
album_data['id'] = result.entries.first['id']
album_data
end
end

def self.destroy(db, album_id)
db.exec("DELETE FROM album_genres WHERE album_id = $1", [album_id])
db.exec("DELETE FROM songs WHERE album_id = $1", [album_id])
db.exec("DELETE FROM albums WHERE id = $1", [album_id])
end

end
end
42 changes: 42 additions & 0 deletions lib/songify/genre_repo.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
module Songify
class GenreRepo
def self.albums(db, genre_id)
db.exec("SELECT g.name AS genre, a.title AS title, a.id AS album_id, g.id AS genre_id FROM genres g JOIN album_genres j ON g.id = j.genre_id JOIN albums a ON a.id = j.album_id WHERE g.id = $1", [genre_id])
end

def self.all(db)
# Other code should not have to deal with the PG:Result.
# Therefore, convert the results into a plain array.
db.exec("SELECT * FROM genres").to_a
end

def self.find(db, genre_id)
db.exec("SELECT * FROM genres WHERE id=$1", [genre_id]).first
end

def self.genres_by_album(db, album_id)
db.exec("SELECT g.name, g.id FROM album_genres a JOIN genres g ON g.id = a.genre_id WHERE a.album_id = $1", [album_id]).to_a
end

def self.save(db, genre_data)
if genre_data['id']
result = db.exec("UPDATE genres SET name = $2 WHERE id = $1", [genre_data['id'], genre_data['name']])
self.find(db, genre_data['id'])
else
raise "name is required." if genre_data['name'].nil? || genre_data['name'] == ''

result = db.exec("INSERT INTO genres (name) VALUES ($1) RETURNING id", [genre_data['name']])
genre_data['id'] = result.entries.first['id']
genre_data
end
end

def self.destroy(db, genre_id)
# TODO: Delete SQL statement
# ALSO DELETE JOIN TABLE ENTRIES BETWEEN THIS GENRE AND ITS ALBUMS
db.exec("DELETE FROM album_genres WHERE genre_id = $1", [genre_id])
db.exec("DELETE FROM genres WHERE id = $1", [genre_id])
end

end
end
36 changes: 36 additions & 0 deletions lib/songify/song_repo.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
module Songify
class SongRepo

def self.all(db)
# Other code should not have to deal with the PG:Result.
# Therefore, convert the results into a plain array.
db.exec("SELECT * FROM songs").to_a
end

def self.find(db, song_id)
db.exec("SELECT * FROM songs WHERE id=$1", [song_id]).first
end

def self.list(db, album_id)
db.exec("SELECT a.title AS title, s.title AS name, a.id AS album_id FROM songs s JOIN albums a ON a.id = s.album_id WHERE album_id = $1", [album_id]).to_a
end

def self.save(db, song_data)
if song_data['id']
result = db.exec("UPDATE songs SET title = $2 WHERE id = $1", [song_data['id'], song_data['title']])
self.find(db, song_data['id'])
else
raise "title is required." if song_data['title'].nil? || song_data['title'] == ''

# Ensure album exists
album = AlbumRepo.find(db, song_data['album_id'])
raise "A valid album_id is required." if album.nil?

result = db.exec("INSERT INTO songs (title, album_id) VALUES ($1, $2) RETURNING id", [song_data['title'], song_data['album_id']])
song_data['id'] = result.entries.first['id']
song_data
end
end

end
end
101 changes: 101 additions & 0 deletions server.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
require 'sinatra'
require './lib/songify.rb'
# Rack::MethodOverride

set :bind, '0.0.0.0' # This is needed for Vagrant

get '/' do
erb :index
end

get '/albums' do
@db = Songify.create_db_connection('songify_dev')
@albums = Songify::AlbumRepo.all(@db)
@genres = Songify::GenreRepo.all(@db)
erb :"albums/index"
end

post '/albums' do
db = Songify.create_db_connection('songify_dev')
album = Songify::AlbumRepo.save(db, {
'title' => params[:title],
'genre_ids' => params[:genre_ids]
})
redirect to '/albums'
end

get '/albums/:id' do
db = Songify.create_db_connection('songify_dev')
@albums = Songify::AlbumRepo.find(db, params[:id])
@songs = Songify::SongRepo.list(db, params[:id])
@genres_join = Songify::GenreRepo.genres_by_album(db, params[:id])
erb :"albums/album"
end

delete '/albums/:id' do
db = Songify.create_db_connection('songify_dev')
Songify::AlbumRepo.destroy(db, params[:album_id])
redirect to '/albums'
end

get '/albums/:id/edit' do
db = Songify.create_db_connection('songify_dev')
@albums = Songify::AlbumRepo.find(db, params[:id])
@genres_join = Songify::GenreRepo.genres_by_album(db, params[:id])
@genres = Songify::GenreRepo.all(db)
erb :"albums/edit"
end

post '/albums/:id/edit' do
db = Songify.create_db_connection('songify_dev')
puts params[:id].class
puts params[:genre_ids].class
Songify::AlbumRepo.add_genres(db, {
'id' => params[:id],
'genre_ids' => params[:genre_ids]
})
redirect to "/albums/#{params[:id]}/edit"
end

get '/songs' do
db = Songify.create_db_connection('songify_dev')
@songs = Songify::SongRepo.all(db)
@albums = Songify::AlbumRepo.all(db)
erb :"songs/index"
end

post '/songs' do
db = Songify.create_db_connection('songify_dev')
song = Songify::SongRepo.save(db, {
'title' => params[:title],
'album_id' => params[:album_id]
})
redirect to '/songs'
end

get '/genres' do
db = Songify.create_db_connection('songify_dev')
@genres = Songify::GenreRepo.all(db)
erb :"genres/index"
end

post '/genres' do
db = Songify.create_db_connection('songify_dev')
album = Songify::GenreRepo.save(db, {
'name' => params[:name]
})
redirect to '/genres'
end

get '/genres/:id' do
db = Songify.create_db_connection('songify_dev')
@genres = Songify::GenreRepo.find(db, params[:id])
@genres_join = Songify::GenreRepo.albums(db, params[:id])
erb :"genres/genre"
end

delete '/genres/:id' do
db = Songify.create_db_connection('songify_dev')
Songify::GenreRepo.destroy(db, params[:genre_id])
redirect to '/genres'
end
Empty file removed spec/.gitkeep
Empty file.
Loading