Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
...
Checking mergeability… Don't worry, you can still create the pull request.
  • 12 commits
  • 19 files changed
  • 0 commit comments
  • 1 contributor
View
16 config.ru
@@ -1,7 +1,17 @@
-class App
+$:.unshift "."
+require "front_controller"
+
+class Logger
+ def initialize(app)
+ @app = app
+ end
+
def call(env)
- # Return the response array here
+ puts "Calling " + env["PATH_INFO"]
+ @app.call(env)
end
end
-run App.new
+use Logger
+
+run FrontController.new
View
15 controller.rb
@@ -0,0 +1,15 @@
+require "not_active_record"
+require "filters"
+require "rendering"
+
+class ControllerBase
+ attr_accessor :request, :response
+
+ def process(action)
+ send(action)
+ end
+end
+
+class Controller < ControllerBase
+ include Filters, Rendering
+end
View
5 controllers/echo_controller.rb
@@ -0,0 +1,5 @@
+class EchoController < Controller
+ def index
+ response.write "You said: " + request["text"]
+ end
+end
View
28 controllers/home_controller.rb
@@ -0,0 +1,28 @@
+class HomeController < Controller
+ # around_filter :layout
+ before_filter :header
+ after_filter :footer
+
+ def index
+ @message = "This is cool!"
+ # render :index
+ end
+
+ def nice
+ response.write "This is nice!"
+ end
+
+ def header
+ response.write "<h1>My App</h1>"
+ end
+
+ def footer
+ response.write "<p>&copy; me</p>"
+ end
+
+ # def layout
+ # response.write "<html><body>"
+ # yield
+ # response.write "</body></html>"
+ # end
+end
View
14 controllers/users_controller.rb
@@ -0,0 +1,14 @@
+require "models/user"
+
+class UsersController < Controller
+ def index
+ User.all.each do |user|
+ response.write "<p>#{user.name}</p>"
+ end
+ end
+
+ def show
+ user = User.find(request["id"])
+ response.write "<p>#{user.name}</p>"
+ end
+end
View
31 filters.rb
@@ -0,0 +1,31 @@
+require "active_support/concern"
+require "active_support/callbacks"
+
+module Filters
+ extend ActiveSupport::Concern
+
+ included do
+ include ActiveSupport::Callbacks
+ define_callbacks :process
+ end
+
+ module ClassMethods
+ def before_filter(method)
+ set_callback :process, :before, method
+ end
+
+ def after_filter(method)
+ set_callback :process, :after, method
+ end
+
+ def around_filter(method)
+ set_callback :process, :around, method
+ end
+ end
+
+ def process(*)
+ run_callbacks :process do
+ super
+ end
+ end
+end
View
32 front_controller.rb
@@ -0,0 +1,32 @@
+require "controller"
+require "router"
+require "routes"
+
+class FrontController
+ def call(env)
+ request = Rack::Request.new(env)
+ response = Rack::Response.new
+
+ # controller_name, action_name = route(request.path_info)
+ controller_name, action_name = Routes.recognize(request.path_info)
+
+ controller_class = load_controller_class(controller_name)
+
+ controller = controller_class.new
+ controller.request = request
+ controller.response = response
+ controller.process(action_name)
+
+ response.finish
+ end
+
+ def route(path)
+ _, controller, action = path.split("/") # /home/index => ["", "home", "index"]
+ [controller || "home", action || "index"]
+ end
+
+ def load_controller_class(name)
+ require "controllers/#{name}_controller"
+ Object.const_get(name.capitalize + "Controller") # "HomeController"
+ end
+end
View
3  models/user.rb
@@ -0,0 +1,3 @@
+class User < NotActiveRecord::Base
+
+end
View
47 not_active_record.rb
@@ -0,0 +1,47 @@
+require "connection_adapter"
+
+module NotActiveRecord
+ class Base
+ @@connection = SqliteAdapter.new
+
+ def initialize(attributes={})
+ @attributes = attributes
+ end
+
+ def method_missing(name, *args)
+ if self.class.columns.include?(name)
+ @attributes[name]
+ else
+ super
+ end
+ end
+
+ def self.find(id)
+ find_by_sql("SELECT * FROM #{table_name} WHERE id = #{id.to_i} LIMIT 1").first
+ end
+
+ def self.all
+ find_by_sql("SELECT * FROM #{table_name}")
+ end
+
+ def self.find_by_sql(sql)
+ rows = @@connection.execute(sql)
+ rows.map do |row|
+ attributes = map_values_to_columns(row)
+ new(attributes)
+ end
+ end
+
+ def self.map_values_to_columns(values)
+ Hash[columns.zip(values)]
+ end
+
+ def self.columns
+ @@connection.columns(table_name)
+ end
+
+ def self.table_name
+ name.downcase + "s" # "users"
+ end
+ end
+end
View
16 patterns.gemspec
@@ -0,0 +1,16 @@
+$:.push File.expand_path(".", __FILE__)
+
+# Describe your gem and declare its dependencies:
+Gem::Specification.new do |s|
+ s.name = "patterns"
+ s.version = "1.0"
+ s.authors = ["Marc-Andre Cournoyer"]
+ s.email = ["marc@codedinc.com"]
+ s.homepage = "http://owningrails.com/"
+ s.summary =
+ s.description = "The Patterns mini-framework"
+
+ s.require_paths = %w( . )
+
+ s.add_runtime_dependency 'sqlite3'
+end
View
28 rendering.rb
@@ -0,0 +1,28 @@
+module Rendering
+ def process(action)
+ super
+ render(action) unless rendered?
+ end
+
+ def render(action)
+ @rendered = true
+ response.write render_to_string(action)
+ end
+
+ def rendered?
+ @rendered
+ end
+
+ def render_to_string(action)
+ path = template_path(action)
+ ERB.new(File.read(path)).result(binding)
+ end
+
+ def template_path(action)
+ File.expand_path("../views/#{controller_name}/#{action}.erb", __FILE__)
+ end
+
+ def controller_name
+ self.class.name[/^(\w+)Controller/, 1].downcase # home
+ end
+end
View
15 router.rb
@@ -0,0 +1,15 @@
+class Router
+ def initialize(&block)
+ @routes = {}
+ instance_eval(&block) if block
+ end
+
+ def match(options) # {'/' => 'home#index}
+ path, action = options.first # [key, value]
+ @routes[path] = action.split('#') # home, index
+ end
+
+ def recognize(path_info)
+ @routes[path_info]
+ end
+end
View
6 routes.rb
@@ -0,0 +1,6 @@
+Routes = Router.new do
+ match '/' => 'home#index'
+ match '/yo' => 'home#index'
+ match '/users' => 'users#index'
+ match '/echo' => 'echo#index'
+end
View
62 tests/filters_test.rb
@@ -0,0 +1,62 @@
+require File.dirname(__FILE__) + '/test_helper'
+require "controller"
+
+class TestController < Controller
+ around_filter :around1
+ around_filter :around2
+ before_filter :one
+ before_filter :two
+ after_filter :three
+
+ def initialize(out)
+ @out = out
+ end
+
+ def one
+ @out << :one
+ end
+
+ def two
+ @out << :two
+ end
+
+ def three
+ @out << :three
+ end
+
+ def around1
+ @out << "{"
+ yield
+ @out << "}"
+ end
+
+ def around2
+ @out << "["
+ yield
+ @out << "]"
+ end
+
+ def index
+ @out << :index
+
+ @rendered = true # to skip rendering
+ end
+end
+
+class TestController2 < Controller
+ before_filter :four
+end
+
+class FiltersTest < Test::Unit::TestCase
+ def test_store_filters
+ assert_equal [:one, :two], TestController.before_filters
+ assert_equal [:four], TestController2.before_filters
+ assert_equal [:three], TestController.after_filters
+ end
+
+ def test_filtering
+ out = []
+ TestController.new(out).process(:index)
+ assert_equal ["{", "[", :one, :two, :index, :three, "]", "}"], out
+ end
+end
View
20 tests/front_controller_test.rb
@@ -0,0 +1,20 @@
+require File.dirname(__FILE__) + '/test_helper'
+require "front_controller"
+
+class FrontControllerTest < Test::Unit::TestCase
+ def setup
+ @front = FrontController.new
+ end
+
+ def test_routing
+ assert_equal ["home", "index"], @front.route("/home/index")
+ assert_equal ["home", "index"], @front.route("/")
+ assert_equal ["users", "new"], @front.route("/users/new")
+ assert_equal ["users", "index"], @front.route("/users")
+ end
+
+ def test_load_controller_class
+ klass = @front.load_controller_class("home") # => HomeController
+ assert_equal HomeController, klass
+ end
+end
View
22 tests/rendering_test.rb
@@ -0,0 +1,22 @@
+require File.dirname(__FILE__) + '/test_helper'
+require "controller"
+require "controllers/home_controller"
+
+class RenderingTest < Test::Unit::TestCase
+ def setup
+ @controller = HomeController.new
+ end
+
+ def test_controller_name
+ assert_equal "home", @controller.controller_name
+ end
+
+ def test_template_path
+ assert_equal File.expand_path("../../views/home/index.erb", __FILE__),
+ @controller.template_path("index")
+ end
+
+ def test_render
+ assert_not_nil @controller.render_to_string("index")
+ end
+end
View
18 tests/router_test.rb
@@ -0,0 +1,18 @@
+require File.dirname(__FILE__) + '/test_helper'
+require "router"
+
+class RouterTest < Test::Unit::TestCase
+ def test_match_simple_routes
+ router = Router.new
+ router.match '/' => 'home#index'
+ assert_equal ["home", "index"], router.recognize('/')
+ end
+
+ def test_dsl
+ router = Router.new do
+ match '/' => 'home#index'
+ end
+
+ assert_equal ["home", "index"], router.recognize('/')
+ end
+end
View
43 tests/user_test.rb
@@ -0,0 +1,43 @@
+require File.dirname(__FILE__) + '/test_helper'
+require "not_active_record"
+require "models/user"
+
+class UserTest < Test::Unit::TestCase
+ def test_intialize_with_attributes
+ user = User.new(:id => 1, :name => "Marc")
+ assert_equal 1, user.id
+ assert_equal "Marc", user.name
+ end
+
+ def test_find
+ user = User.find(1)
+ assert_equal 1, user.id
+ end
+
+ def test_all
+ user = User.all.first
+ assert_equal 1, user.id
+ end
+
+ def test_map_values_to_columns
+ values = [1, "Marc"]
+ columns = [:id, :name]
+
+ # attributes = {}
+ # columns.each_with_index do |column, index|
+ # attributes[column] = values[index]
+ # end
+
+ attributes = User.map_values_to_columns(values)
+
+ assert_equal({:id => 1, :name => "Marc"}, attributes)
+ end
+
+ def test_columns
+ assert_equal [:id, :name], User.columns
+ end
+
+ def test_table_name
+ assert_equal "users", User.table_name
+ end
+end
View
2  views/home/index.erb
@@ -0,0 +1,2 @@
+<p>Hello from a view!</p>
+<p><%= @message %></p>

No commit comments for this range

Something went wrong with that request. Please try again.