Last active
December 19, 2015 14:29
-
-
Save TGSmith/87e4a7b45e938885acf2 to your computer and use it in GitHub Desktop.
Revisions
-
TGSmith revised this gist
Jul 10, 2013 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -116,7 +116,7 @@ def insert! values = self.attributes.values marks = Array.new(fields.length) { '?' }.join(',') insert_sql = "INSERT INTO #{self.class.to_s}s (#{fields.join(',')}) VALUES (#{marks})" results = Database::Model.execute(insert_sql, *values) @@ -132,7 +132,7 @@ def update! values = self.attributes.values update_clause = fields.map { |field| "#{field} = ?" }.join(',') update_sql = "UPDATE #{self.class.to_s}s SET #{update_clause} WHERE id = ?" # We have to use the (potentially) old ID attribute in case the user has re-set it. Database::Model.execute(update_sql, *values, self.old_attributes[:id]) -
TGSmith revised this gist
Jul 10, 2013 . 4 changed files with 224 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1 +0,0 @@ This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,59 @@ class Cohort < Database::Model self.attribute_names = [:id, :name, :created_at, :updated_at] attr_reader :attributes, :old_attributes # e.g., Cohort.new(:id => 1, :name => 'Alpha', :created_at => '2012-12-01 05:54:30') def initialize(attributes = {}) attributes.symbolize_keys! raise_error_if_invalid_attribute!(attributes.keys) @attributes = {} Cohort.attribute_names.each do |name| @attributes[name] = attributes[name] end @old_attributes = @attributes.dup end def [](attribute) raise_error_if_invalid_attribute!(attribute) @attributes[attribute] end def []=(attribute, value) raise_error_if_invalid_attribute!(attribute) @attributes[attribute] = value end def students Student.where('cohort_id = ?', self[:id]) end def add_students(students) students.each do |student| student.cohort = self end students end def save if new_record? results = insert! else results = update! end # When we save, remove changes between new and old attributes @old_attributes = @attributes.dup results end end This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,151 @@ require 'sqlite3' module Database class InvalidAttributeError < StandardError;end class NotConnectedError < StandardError;end class Model def self.find(pk) self.where('id = ?', pk).first # get rid of array end # WHERE always returns array !!!!!! def self.create(attributes) record = self.new(attributes) record.save record end def new_record? self[:id].nil? end def self.all Database::Model.execute("SELECT * FROM #{self.to_s.downcase}s").map do |row| self.new(row) end end def self.where(query, *args) Database::Model.execute("SELECT * FROM #{self.to_s.downcase}s WHERE #{query}", *args).map do |row| self.new(row) end end def self.inherited(klass) end def self.connection @connection end def self.filename @filename end def self.database=(filename) @filename = filename.to_s @connection = SQLite3::Database.new(@filename) # Return the results as a Hash of field/value pairs # instead of an Array of values @connection.results_as_hash = true # Automatically translate data from database into # reasonably appropriate Ruby objects @connection.type_translation = true end def self.attribute_names @attribute_names end def self.attribute_names=(attribute_names) @attribute_names = attribute_names end # Input looks like, e.g., # execute("SELECT * FROM students WHERE id = ?", 1) # Returns an Array of Hashes (key/value pairs) def self.execute(query, *args) raise NotConnectedError, "You are not connected to a database." unless connected? prepared_args = args.map { |arg| prepare_value(arg) } Database::Model.connection.execute(query, *prepared_args) end def self.last_insert_row_id Database::Model.connection.last_insert_row_id end def self.connected? !self.connection.nil? end def raise_error_if_invalid_attribute!(attributes) # This guarantees that attributes is an array, so we can call both: # raise_error_if_invalid_attribute!("id") # and # raise_error_if_invalid_attribute!(["id", "name"]) Array(attributes).each do |attribute| unless valid_attribute?(attribute) raise InvalidAttributeError, "Invalid attribute for #{self.class}: #{attribute}" end end end def to_s attribute_str = self.attributes.map { |key, val| "#{key}: #{val.inspect}" }.join(', ') "#<#{self.class} #{attribute_str}>" end def valid_attribute?(attribute) self.class.attribute_names.include? attribute end private def insert! self[:created_at] = DateTime.now self[:updated_at] = DateTime.now fields = self.attributes.keys values = self.attributes.values marks = Array.new(fields.length) { '?' }.join(',') insert_sql = "INSERT INTO students (#{fields.join(',')}) VALUES (#{marks})" results = Database::Model.execute(insert_sql, *values) # This fetches the new primary key and updates this instance self[:id] = Database::Model.last_insert_row_id results end def update! self[:updated_at] = DateTime.now fields = self.attributes.keys values = self.attributes.values update_clause = fields.map { |field| "#{field} = ?" }.join(',') update_sql = "UPDATE students SET #{update_clause} WHERE id = ?" # We have to use the (potentially) old ID attribute in case the user has re-set it. Database::Model.execute(update_sql, *values, self.old_attributes[:id]) end def self.prepare_value(value) case value when Time, DateTime, Date value.to_s else value end end end end This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,14 @@ # Solution for Challenge: ActiveRecord, Jr. 2: SQL Be Gone. Started 2013-07-10T20:33:55+00:00 def update! self[:updated_at] = DateTime.now fields = self.attributes.keys values = self.attributes.values update_clause = fields.map { |field| "#{field} = ?" }.join(',') update_sql = "UPDATE students SET #{update_clause} WHERE id = ?" # We have to use the (potentially) old ID attribute in case the user has re-set it. Database::Model.execute(update_sql, *values, self.old_attributes[:id]) end -
TGSmith created this gist
Jul 10, 2013 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1 @@ # Solution for Challenge: ActiveRecord, Jr. 2: SQL Be Gone. Started 2013-07-10T20:33:55+00:00