Skip to content

Commit

Permalink
Add student ORM
Browse files Browse the repository at this point in the history
  • Loading branch information
gglin committed Jun 24, 2013
1 parent a740785 commit 09696d8
Show file tree
Hide file tree
Showing 7 changed files with 251 additions and 0 deletions.
22 changes: 22 additions & 0 deletions app.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,32 @@
require 'sinatra/base'
require_relative 'lib/models/student.rb'

# Why is it a good idea to wrap our App class in a module?
module StudentSite
class App < Sinatra::Base

def initialize
super
@artists = ["Frank Sinatra", "Bing Crosby", "Bob\n\n\n\n", 1, 2, "dslajkffoiejfijasdlfl"]
end

def set_random_numbers(arg)
@random_numbers = arg
end

get '/' do
"hello world!"
end

get '/hello-world' do
set_random_numbers((1..20).to_a)
p @random_numbers
erb :hello
end

get '/artists' do
erb :artists
end

end
end
43 changes: 43 additions & 0 deletions lib/concerns/persistable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
module Persistable
module ClassMethods

def new_from_db(row)
new.tap do |s|
attributes.keys.each_with_index do |attribute, index|
s.send("#{attribute}=",row[index])
end
end
end

def table_name
"#{self.to_s.downcase}s"
end

def drop
database.execute "DROP TABLE IF EXISTS #{table_name};"
end

def table_exists?(table_name)
database.execute "SELECT * FROM sqlite_master WHERE type = 'table' AND name = ?", table_name
end

def create_table
database.execute "CREATE TABLE IF NOT EXISTS #{table_name} (
#{attributes_for_create}
)"
end

def attributes_for_create
self.attributes.collect{|k,v| [k,v].join(" ")}.join(",")
end

def attributes_for_update
self.attributes.keys.reject{|k| k == :id}.collect{|k| "#{k} = ?"}.join(",")
end

def column_names_for_insert
self.attributes.keys[1..-1].join(",")
end

end
end
80 changes: 80 additions & 0 deletions lib/models/student.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
require_relative '../concerns/persistable'

class Student
extend Persistable::ClassMethods

ATTRIBUTES = {
:id => "INTEGER PRIMARY KEY",
:name => "TEXT",
:tagline => "TEXT",
:bio => "TEXT",
:treehouse_profile => "TEXT"
}

def self.attributes
ATTRIBUTES
end

def self.find_by(*args)
args.flatten.each do |arg|
define_singleton_method("find_by_#{arg}") do |value|
result = self.database.execute "SELECT * FROM #{self.table_name} WHERE #{arg} = ?", value
new_from_db(result.first)
end
end
end

find_by(self.attributes.keys)

def self.find(id)
self.find_by_id(id)
end

def self.all
results = database.execute "SELECT * FROM students;"
results.collect{|row| new_from_db(row)}
end

def self.attr_accessors
self.attributes.keys.each do |k|
attr_accessor k
end
end
attr_accessors

def self.database
@@db ||= SQLite3::Database.new('student.db')
end

def persisted?
self.id
end

def save
persisted? ? update : insert
end

def attributes
self.class.attributes.keys.collect do |attribute|
self.send(attribute)
end
end

def attributes_for_sql
self.attributes[1..-1]
end

def question_marks_for_sql
("?," * attributes_for_sql.size)[0..-2]
end

private
def insert
self.class.database.execute "INSERT INTO #{self.class.table_name} (#{self.class.column_names_for_insert}) VALUES (#{self.question_marks_for_sql})", self.attributes_for_sql
self.id = self.class.database.last_insert_row_id
end

def update
self.class.database.execute "UPDATE #{self.class.table_name} SET #{self.class.attributes_for_update} WHERE id = ?", [attributes_for_sql, self.id].flatten
end
end
Binary file added student.db
Binary file not shown.
92 changes: 92 additions & 0 deletions test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
require 'fis/test'
require 'sqlite3'
require 'pry-debugger'

require_relative 'lib/concerns/persistable'

require_relative 'lib/models/student'

include Fis::Test

assert Student.drop
assert Student.create_table

test 'should create a table' do
assert !Student.table_exists?('students')

assert Student.table_exists?('students')
end

test 'should be able to instantiate a student' do
assert Student.new
end

test 'should be able to save a student with a name' do
s = Student.new
s.name = "Avi Flombaum"
s.save

assert_equal Student.find_by_name("Avi Flombaum").name, "Avi Flombaum"
end

test 'should be able to load all students' do
s = Student.new
s.name = "Avi Flombaum"
s.save

assert Student.all.collect{|s| s.name}.include?("Avi Flombaum")
end

test 'should be able to find a student by id' do
s = Student.new
s.name = "Avi Flombaum"
s.save

assert_equal Student.find(s.id).name, "Avi Flombaum"
end

test 'should be able to update a student' do
s = Student.new

s.name = "Avi Flombaum"
s.save

s.name = "Bob Whitney"
s.save

assert_equal Student.find(s.id).name, "Bob Whitney"
end

test 'should be able to retrive a student with a where statment' do
s = Student.new
s.name = "Jeff Baird"
s.save

assert_equal Student.where(:name => "Jeff Baird").map { |s| s.name }, [s.name]

end

test 'should be able to retrieve multiple students with the same name' do
s = Student.new
s.name = "Alice Adams"
s.save

s2 = Student.new
s2.name = "Alice Adams"
s2.save


assert_equal Student.where(:name => "Alice Adams").map {|s| s.name}, [s.name,s2.name]
end

test 'should be able to find_by any attribue' do
s = Student.new
s.name = "Avi Flombaum"
s.tagline = "Hello World"
s.bio = "Dean at Flatiron School"
s.save

assert_equal Student.find_by_tagline("Hello World").tagline, "Hello World"
assert_equal Student.find_by_bio("Dean at Flatiron School").bio, "Dean at Flatiron School"
assert_equal Student.find_by_name("Avi Flombaum").name, "Avi Flombaum"
end
7 changes: 7 additions & 0 deletions views/artists.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Artists:

<ul>
<% @artists.each do |artist| %>
<li><%= artist %></li>
<% end %>
</ul>
7 changes: 7 additions & 0 deletions views/hello.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Hello World!

<ul>
<% @random_numbers.each do |number| %>
<li><%= number %></li>
<% end %>
</ul>

0 comments on commit 09696d8

Please sign in to comment.