From 417663c50cb5e99ee93f14604d0566ccb5d0af7d Mon Sep 17 00:00:00 2001 From: gglin Date: Tue, 25 Jun 2013 08:25:27 -0400 Subject: [PATCH] Working index and student profiles --- Gemfile | 3 +- Gemfile.lock | 2 + app.rb | 17 ++++++++- lib/concerns/persistable.rb | 50 ++++++++++++++++++++++--- lib/models/student.rb | 71 +++++++++--------------------------- student.db | Bin 8192 -> 28672 bytes test.rb | 26 +++++++++---- 7 files changed, 99 insertions(+), 70 deletions(-) diff --git a/Gemfile b/Gemfile index a4aeb27..bae01e6 100755 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,4 @@ source 'https://rubygems.org' -gem 'sinatra', require: 'sinatra/base' \ No newline at end of file +gem 'sinatra', require: 'sinatra/base' +gem 'sqlite3' \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock index 5c68765..f2555dd 100755 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -8,6 +8,7 @@ GEM rack (~> 1.5, >= 1.5.2) rack-protection (~> 1.4) tilt (~> 1.3, >= 1.3.4) + sqlite3 (1.3.7) tilt (1.4.1) PLATFORMS @@ -15,3 +16,4 @@ PLATFORMS DEPENDENCIES sinatra + sqlite3 diff --git a/app.rb b/app.rb index 29535cd..8fefaca 100755 --- a/app.rb +++ b/app.rb @@ -1,5 +1,10 @@ require 'sinatra/base' -require_relative 'lib/models/student.rb' +require 'sqlite3' + +require_relative 'lib/concerns/persistable' +require_relative 'lib/concerns/findable' + +require_relative 'lib/models/student' # Why is it a good idea to wrap our App class in a module? module StudentSite @@ -28,5 +33,15 @@ def set_random_numbers(arg) erb :artists end + get '/students' do + @students = Student.all + erb :'students/students' + end + + get '/students/:url' do + # @students = Student.all + @student = Student.find_by_url(params[:url]) + erb :'students/student_profile' + end end end \ No newline at end of file diff --git a/lib/concerns/persistable.rb b/lib/concerns/persistable.rb index 1af08af..ae445b0 100644 --- a/lib/concerns/persistable.rb +++ b/lib/concerns/persistable.rb @@ -14,30 +14,68 @@ def table_name end def drop - database.execute "DROP TABLE IF EXISTS #{table_name};" + db.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 + db.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} ( + db.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(",") + 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(",") + self.attributes.keys.reject{|k| k == :id}.collect{|k| "#{k} = ?"}.join(", ") end def column_names_for_insert - self.attributes.keys[1..-1].join(",") + self.attributes.keys[1..-1].join(", ") end end + + + module InstanceMethods + + 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.db.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.db.last_insert_row_id + end + + def update + self.class.db.execute "UPDATE #{self.class.table_name} SET #{self.class.attributes_for_update} WHERE id = ?", [attributes_for_sql, self.id].flatten + end + + end end \ No newline at end of file diff --git a/lib/models/student.rb b/lib/models/student.rb index 4d736fd..c5de947 100644 --- a/lib/models/student.rb +++ b/lib/models/student.rb @@ -1,40 +1,32 @@ require_relative '../concerns/persistable' +require_relative '../concerns/findable' class Student - extend Persistable::ClassMethods + + extend Persistable::ClassMethods + include Persistable::InstanceMethods + + extend Findable::ClassMethods ATTRIBUTES = { :id => "INTEGER PRIMARY KEY", :name => "TEXT", + :url => "TEXT", + :img => "TEXT", :tagline => "TEXT", :bio => "TEXT", - :treehouse_profile => "TEXT" + :prof_pic => "TEXT", + :twitter => "TEXT", + :linkedin => "TEXT", + :github => "TEXT", + :blog => "TEXT", + :quote => "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 @@ -42,39 +34,10 @@ def self.attr_accessors 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 + find_by(self.attributes.keys) - def question_marks_for_sql - ("?," * attributes_for_sql.size)[0..-2] + def self.db + @@db ||= SQLite3::Database.new('student.db') 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 \ No newline at end of file diff --git a/student.db b/student.db index ead6e6fed2572b2189753b87100592c8bbc0a0e5..b53cd8e64fbb711c23fb0a4fb3112b8191e28727 100644 GIT binary patch literal 28672 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 NB55Ptp9~P`e*k|z!;k;~ literal 8192 zcmeI%!AiqG5CG6kThk)QHobT%j8s9Pp7iF$w5D3EqG_P^Bpb7}i<_(@snTQb{)6A( zKll-zJ^K-EX#$1n56BEzc6Krh%e#g2Z+ar-Fj8^IQaB)0Vi@EYfDmHoRnRMsqE1Tr zLGQ*={#R;|{jcqfc{6<^`oTZ}6hHwKKmim$0Te(16hHwKK!N`*Fsm8m&3fIKy`;>S zJV_@3kJ2RH3vJi2JqJ9y)pH=P!tOd`Ap+=LdCsZh!nNDIwA~?GIKyVdLJppD>orsM zAVriNe4(;x%=uVN5`Om-tC5h4_u16F`L}t6wh8^FpY(&i(>MA`r@DZF0w{n2D1ZVe zfC4Ch0w{n2D1ZVeuq<#`G09Hjh}h2pI#Pu`n}lavN(BQI%ix5w2=u@8j%2BbRRsO} zu~O11o1~$~*izhcumct*mbp@@u9;*@cb)Um2wF_UfmK>GwUiHou}C96trhhJ=A)J_ LP%HdWGgfOqt=em+ diff --git a/test.rb b/test.rb index 6cf67ed..fc671a2 100644 --- a/test.rb +++ b/test.rb @@ -3,7 +3,7 @@ require 'pry-debugger' require_relative 'lib/concerns/persistable' - +require_relative 'lib/concerns/findable' require_relative 'lib/models/student' include Fis::Test @@ -57,13 +57,12 @@ assert_equal Student.find(s.id).name, "Bob Whitney" end -test 'should be able to retrive a student with a where statment' do +test 'should be able to retrieve a student with a where statement' 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 @@ -75,18 +74,29 @@ 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 +test 'should be able to find_by any attribute' 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" + 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 + +test 'should return nil when find_by method fails to match' do + assert_equal Student.find(3409), nil + assert_equal Student.find_by_tagline("Hello Worl"), nil + assert_equal Student.find_by_bio("Dean at Flatiron Scho"), nil + assert_equal Student.find_by_name("Avi Flomb"), nil +end + +test 'should return nil when where method fails to match & array otherwise' do + assert_equal Student.where(:name => "Avi Flombaum").class, Array + assert_equal Student.where(:name => "Avi Flombau"), nil end \ No newline at end of file