From 09696d8a880474837fab5848bbe3159eab0f906f Mon Sep 17 00:00:00 2001 From: gglin Date: Mon, 24 Jun 2013 14:22:45 -0400 Subject: [PATCH] Add student ORM --- app.rb | 22 +++++++++ lib/concerns/persistable.rb | 43 +++++++++++++++++ lib/models/student.rb | 80 +++++++++++++++++++++++++++++++ student.db | Bin 0 -> 8192 bytes test.rb | 92 ++++++++++++++++++++++++++++++++++++ views/artists.erb | 7 +++ views/hello.erb | 7 +++ 7 files changed, 251 insertions(+) create mode 100644 lib/concerns/persistable.rb create mode 100644 lib/models/student.rb create mode 100644 student.db create mode 100644 test.rb create mode 100644 views/artists.erb create mode 100644 views/hello.erb diff --git a/app.rb b/app.rb index f58fbb2..29535cd 100755 --- a/app.rb +++ b/app.rb @@ -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 \ No newline at end of file diff --git a/lib/concerns/persistable.rb b/lib/concerns/persistable.rb new file mode 100644 index 0000000..1af08af --- /dev/null +++ b/lib/concerns/persistable.rb @@ -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 \ No newline at end of file diff --git a/lib/models/student.rb b/lib/models/student.rb new file mode 100644 index 0000000..4d736fd --- /dev/null +++ b/lib/models/student.rb @@ -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 \ No newline at end of file diff --git a/student.db b/student.db new file mode 100644 index 0000000000000000000000000000000000000000..ead6e6fed2572b2189753b87100592c8bbc0a0e5 GIT binary patch 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+ literal 0 HcmV?d00001 diff --git a/test.rb b/test.rb new file mode 100644 index 0000000..6cf67ed --- /dev/null +++ b/test.rb @@ -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 \ No newline at end of file diff --git a/views/artists.erb b/views/artists.erb new file mode 100644 index 0000000..0146f63 --- /dev/null +++ b/views/artists.erb @@ -0,0 +1,7 @@ +Artists: + + \ No newline at end of file diff --git a/views/hello.erb b/views/hello.erb new file mode 100644 index 0000000..aab3633 --- /dev/null +++ b/views/hello.erb @@ -0,0 +1,7 @@ +Hello World! + + \ No newline at end of file