├── Gemfile ├── Gemfile.lock ├── README.md ├── application.html.slim ├── blogs_controller.rb ├── config.ru ├── index.html.slim ├── myrails.rb └── routes.rb /Gemfile: -------------------------------------------------------------------------------- 1 | source 'http://ruby.taobao.org' 2 | 3 | gem 'slim' 4 | gem 'rack' 5 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: http://ruby.taobao.org/ 3 | specs: 4 | rack (1.6.0) 5 | slim (3.0.3) 6 | temple (~> 0.7.3) 7 | tilt (>= 1.3.3, < 2.1) 8 | temple (0.7.5) 9 | tilt (2.0.1) 10 | 11 | PLATFORMS 12 | ruby 13 | 14 | DEPENDENCIES 15 | rack 16 | slim 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # myrails 2 | A mini rails for personal study and practice 3 | 4 | # How to run it 5 | ```shell 6 | $ bundle 7 | $ rackup 8 | ``` 9 | 10 | http://localhost:9292/blogs is a demo. 11 | -------------------------------------------------------------------------------- /application.html.slim: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | title Crazyjin's Blog 5 | body 6 | == yield 7 | -------------------------------------------------------------------------------- /blogs_controller.rb: -------------------------------------------------------------------------------- 1 | class BlogsController < MyRails::Controller 2 | def index 3 | @hello = "Hello My Rails" 4 | render :index 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | load 'myrails.rb' 2 | load 'blogs_controller.rb' 3 | load 'routes.rb' 4 | 5 | run MyRails::Application 6 | -------------------------------------------------------------------------------- /index.html.slim: -------------------------------------------------------------------------------- 1 | p = @hello 2 | -------------------------------------------------------------------------------- /myrails.rb: -------------------------------------------------------------------------------- 1 | #encoding utf-8 2 | require 'rubygems' 3 | require 'bundler/setup' 4 | require 'slim' 5 | 6 | module MyRails 7 | class Router 8 | @@routes = {} 9 | class << self 10 | #RSTfull route helpers, simply map path to controllers and actions 11 | #get "/blogs", "blogs_controller#index" 12 | #post "/blogs", "blogs_controller#create" 13 | %i{get post put delete}.each do |m| 14 | define_method(m) do |path, action| 15 | controller, action = action.split('#') 16 | controller = controller.split('_').collect(&:capitalize).join 17 | controller = Object.const_get controller 18 | 19 | @@routes[m] = {} if @@routes[m].nil? 20 | @@routes[m][path] = [controller, action.to_sym] 21 | end 22 | end 23 | 24 | def draw_routes(&block) 25 | self.instance_eval(&block) 26 | end 27 | 28 | def call_controller_action env 29 | method, path, params = env['REQUEST_METHOD'].downcase.to_sym, env["REQUEST_PATH"], env["QUERY_STRING"] 30 | return [404, {"content-type" => "text/html"}, ["404, you got it!!"]] if @@routes[method].nil? || @@routes[method][path].nil? 31 | 32 | controller = @@routes[method][path][0].new(params) 33 | action = @@routes[method][path][1] 34 | controller.send action 35 | 36 | [controller.http_status, controller.http_headers, [controller.http_body]] 37 | rescue 38 | [500, {"content-type" => "text/html"}, [$!.message]] 39 | end 40 | end 41 | end 42 | 43 | class Controller 44 | attr_accessor :http_status, :http_headers, :http_body, :params 45 | 46 | class ViewContext 47 | def create_accessable_instance_variable key 48 | singleton_class.class_eval {attr_accessor key} 49 | end 50 | end 51 | 52 | def initialize query_string="" 53 | key_value_strs = query_string.split('&') 54 | key_value_strs.each do |str| 55 | key_value_pair = str.split '=' 56 | @params[key_value_pair[0]] = key_value_pair[1] if 2 <= key_value_pair.length 57 | end 58 | 59 | @http_status = 200 60 | @http_headers = {"content-type" => "text/html"} 61 | end 62 | 63 | def render template 64 | layout = File.open("./application.html.slim", "rb").read 65 | content = File.open("./#{template.to_s}.html.slim", "rb").read 66 | 67 | l = Slim::Template.new { layout } 68 | 69 | variables = instance_variables 70 | env = ViewContext.new 71 | variables.each do |v| 72 | env.create_accessable_instance_variable v[1..-1] 73 | env.send("#{v[1..-1]}=", instance_variable_get(v)) 74 | end 75 | 76 | c = Slim::Template.new { content }.render(env) 77 | @http_body = l.render { c } 78 | end 79 | end 80 | 81 | class Application 82 | class << self 83 | def draw_routes &b 84 | Router.draw_routes &b 85 | end 86 | 87 | #rack server need this 88 | def call(env) 89 | Router.call_controller_action env 90 | rescue 91 | $!.backtrace.each {|l| puts l } 92 | end 93 | end 94 | end 95 | end 96 | -------------------------------------------------------------------------------- /routes.rb: -------------------------------------------------------------------------------- 1 | #encoding uft-8 2 | MyRails::Application.draw_routes do 3 | get "/blogs", "blogs_controller#index" 4 | end 5 | --------------------------------------------------------------------------------