Skip to content

Commit

Permalink
Implement MyAttrAccessor Class
Browse files Browse the repository at this point in the history
  • Loading branch information
jdmoody committed Feb 14, 2014
0 parents commit 64c030a
Show file tree
Hide file tree
Showing 17 changed files with 685 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .rspec
@@ -0,0 +1,2 @@
--color
--format documentation
3 changes: 3 additions & 0 deletions README.md
@@ -0,0 +1,3 @@
After the project, you can review the solution here:

* https://github.com/appacademy-solutions/active_record_lite/tree/solution
Binary file added cats.db
Binary file not shown.
36 changes: 36 additions & 0 deletions cats.sql
@@ -0,0 +1,36 @@
CREATE TABLE cats (
id INTEGER PRIMARY KEY,
name VARCHAR(255) NOT NULL,
owner_id INTEGER NOT NULL,

FOREIGN KEY(owner_id) REFERENCES human(id)
);

CREATE TABLE humans (
id INTEGER PRIMARY KEY,
fname VARCHAR(255) NOT NULL,
lname VARCHAR(255) NOT NULL,
house_id INTEGER NOT NULL,

FOREIGN KEY(house_id) REFERENCES human(id)
);

CREATE TABLE houses (
id INTEGER PRIMARY KEY,
address VARCHAR(255) NOT NULL
);

INSERT INTO
houses (address)
VALUES
("26th and Guerrero"), ("Dolores and Market");

INSERT INTO
humans (fname, lname, house_id)
VALUES
("Devon", "Watts", 1), ("Matt", "Rubens", 1), ("Ned", "Ruggeri", 2);

INSERT INTO
cats (name, owner_id)
VALUES
("Breakfast", 1), ("Earl", 2), ("Haskell", 3), ("Markov", 3);
8 changes: 8 additions & 0 deletions lib/active_record_lite/00_attr_accessor_object.rb
@@ -0,0 +1,8 @@
class AttrAccessorObject
def self.my_attr_accessor(*names)
names.each do |name|
define_method(name) { instance_variable_get("@#{name}") }
define_method("#{name}=") { |arg| instance_variable_set("@#{name}", arg) }
end
end
end
16 changes: 16 additions & 0 deletions lib/active_record_lite/01_mass_object.rb
@@ -0,0 +1,16 @@
# deprecated for Rails 4
# require_relative '00_attr_accessor_object.rb'
#
# class MassObject < AttrAccessorObject
# def self.my_attr_accessible(*new_attributes)
# # ...
# end
#
# def self.attributes
# # ...
# end
#
# def initialize(params = {})
# # ...
# end
# end
55 changes: 55 additions & 0 deletions lib/active_record_lite/02_sql_object.rb
@@ -0,0 +1,55 @@
require_relative 'db_connection'
require_relative '01_mass_object'
require 'active_support/inflector'

class MassObject
def self.parse_all(results)
# ...
end
end

class SQLObject < MassObject
def self.columns
# ...
end

def self.table_name=(table_name)
# ...
end

def self.table_name
# ...
end

def self.all

end

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

def attributes
# ...
end

def insert
# ...
end

def initialize
# ...
end

def save
# ...
end

def update
# ...
end

def attribute_values
# ...
end
end
12 changes: 12 additions & 0 deletions lib/active_record_lite/03_searchable.rb
@@ -0,0 +1,12 @@
require_relative 'db_connection'
require_relative '02_sql_object'

module Searchable
def where(params)
# ...
end
end

class SQLObject
# Mixin Searchable here...
end
50 changes: 50 additions & 0 deletions lib/active_record_lite/04_associatable.rb
@@ -0,0 +1,50 @@
require_relative '03_searchable'
require 'active_support/inflector'

# Phase IVa
class AssocOptions
attr_accessor(
:foreign_key,
:class_name,
:primary_key,
)

def model_class
# ...
end

def table_name
# ...
end
end

class BelongsToOptions < AssocOptions
def initialize(name, options = {})
# ...
end
end

class HasManyOptions < AssocOptions
def initialize(name, self_class_name, options = {})
# ...
end
end

module Associatable
# Phase IVb
def belongs_to(name, options = {})
# ...
end

def has_many(name, options = {})
# ...
end

def assoc_options
# Wait to implement this in Phase V. Modify `belongs_to`, too.
end
end

class SQLObject
# Mixin Associatable here...
end
10 changes: 10 additions & 0 deletions lib/active_record_lite/05_associatable2.rb
@@ -0,0 +1,10 @@
require_relative '04_associatable'

# Phase V
module Associatable
# Remember to go back to 04_associatable to write ::assoc_options

def has_one_through(name, through_name, source_name)
# ...
end
end
52 changes: 52 additions & 0 deletions lib/active_record_lite/db_connection.rb
@@ -0,0 +1,52 @@
require 'sqlite3'

# https://tomafro.net/2010/01/tip-relative-paths-with-file-expand-path
ROOT_FOLDER = File.join(File.dirname(__FILE__), "../..")
CATS_SQL_FILE = File.join(ROOT_FOLDER, "cats.sql")
CATS_DB_FILE = File.join(ROOT_FOLDER, "cats.db")

class DBConnection
def self.open(db_file_name)
@db = SQLite3::Database.new(db_file_name)
@db.results_as_hash = true
@db.type_translation = true

@db
end

def self.reset
commands = [
"rm #{CATS_DB_FILE}",
"cat #{CATS_SQL_FILE} | sqlite3 #{CATS_DB_FILE}"
]

commands.each { |command| `#{command}` }
DBConnection.open(CATS_DB_FILE)
end

def self.instance
self.reset if @db.nil?

@db
end

def self.execute(*args)
puts args[0]

self.instance.execute(*args)
end

def self.execute2(*args)
puts args[0]

self.instance.execute2(*args)
end

def self.last_insert_row_id
self.instance.last_insert_row_id
end

private
def initialize(db_file_name)
end
end
29 changes: 29 additions & 0 deletions spec/00_attr_accessor_object_spec.rb
@@ -0,0 +1,29 @@
require 'active_record_lite/00_attr_accessor_object'

describe AttrAccessorObject do
before(:all) do
class MyAttrAccessorObject < AttrAccessorObject
my_attr_accessor :x, :y
end
end

subject(:obj) { MyAttrAccessorObject.new }

it "#my_attr_accessor adds #x and #y" do
expect(obj).to respond_to(:x)
expect(obj).to respond_to(:y)
end

it "#my_attr_accessor adds #x= and #y=" do
expect(obj).to respond_to(:x=)
expect(obj).to respond_to(:y=)
end

it "#my_attr_accessor methods really get and set" do
obj.x = "xxx"
obj.y = "yyy"

expect(obj.x).to eq("xxx")
expect(obj.y).to eq("yyy")
end
end
54 changes: 54 additions & 0 deletions spec/01_mass_object_spec.rb
@@ -0,0 +1,54 @@
# deprecated in favor of Rails 4 stuff
# require 'active_record_lite/01_mass_object'
#
# # Use these if you like.
# describe MassObject do
# before(:all) do
# class EmptyMassObject < MassObject
# end
#
# class MyMassObject < MassObject
# my_attr_accessor :x, :y
#
# # removed during upgrade to rails 4
# # my_attr_accessible :x, :y
# end
# end
#
# it "::attributes starts out empty" do
# expect(EmptyMassObject.attributes).to be_empty
# end
#
# it "::attriburtes cannot be called directly on MassObject" do
# expect {
# MassObject.attributes
# }.to raise_error("must not call #attributes on MassObject directly")
# end
#
# # removed during upgrade to rails 4
# # it "::my_attr_accessible sets self.attributes" do
# # expect(MyMassObject.attributes).to eq([:x, :y])
# # end
#
# it "#initialize performs mass-assignment" do
# obj = MyMassObject.new(:x => "xxx", :y => "yyy")
#
# expect(obj.x).to eq("xxx")
# expect(obj.y).to eq("yyy")
# end
#
# it "#initialize doesn't mind string keys" do
# obj = MyMassObject.new("x" => "xxx", "y" => "yyy")
#
# expect(obj.x).to eq("xxx")
# expect(obj.y).to eq("yyy")
# end
#
#
# # removed during upgrade to rails 4
# # it "#initialize rejects unregistered keys" do
# # expect {
# # obj = MyMassObject.new(:z => "zzz")
# # }.to raise_error("mass assignment to unregistered attribute 'z'")
# # end
# end

0 comments on commit 64c030a

Please sign in to comment.