看了一下之前有一本 rebuilding rails 的书籍。但是由于是外文的并且售价略昂贵。所以我在阅读完之后整理了一番。不知道这样算不算侵权。没有抄袭。对书中知识进行了一遍整理。现在贴出整理好的一部分。如有侵权嫌疑 还请管理员大大尽快删除。谢谢!
*捡起你的知识并且把他们拼凑成你自己的 rails 吧!
了解一个框架越深,就越能让你掌握它,并且使用它,如果你能够自己打造一个自己的‘rails’,岂不是一件非常值得去做的事情吗? 当然,RAILS 是一个非常顽固的框架,甚至他的制作团队也是这么说的。(约束>配置)但是现在你有机会自己制作一个你认定的约束框架,并且在这基础之上能够添加一些小插件。
如果你觉得自己能够熟练使用 rails,但是对内部一些机制不大了解,阅读本分文档会对你有一些很大的帮助。
以上工具如在其他环境 可以找合适的替代品。在此不多做赘述。
想一个名字是很难的,暂时就以 Shuriken 作为我们的"框架"的名字 首先在你的终端创建一个 gem
bundle gem Shuriken
create rulers/Gemfile
create shuriken/Rakefile
create shuriken/LICENSE.txt
create shuriken/README.md
create shuriken/.gitignore
create shuriken/shuriken.gemspec
create shuriken/lib/shuriken.rb
create shuriken/lib/shuriken/shuriken.rb
Initializating git repo in shuriken
其实 rails 也是一个 gem,我们创建了一个叫 Shuriken(手里剑)的 gem。并且目前的依赖都在 shuriken.gemspec 中
#shuriken.gemspec
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'Shuriken/version'
Gem::Specification.new do |spec|
spec.name = "Shuriken"
spec.version = Shuriken::VERSION
spec.authors = ["icepoint0"]
spec.email = ["[email protected]"]
spec.summary = "RUBY FRAME WORK"
spec.description = "Gay BING"
spec.homepage = "http://thunderjava.com"
spec.license = "MIT"
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
# delete this section to allow pushing this gem to any host.
if spec.respond_to?(:metadata)
spec.metadata['allowed_push_host'] = "TODO: Set to 'http://github.com/icepoint0'"
else
raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
end
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.add_development_dependency "bundler", "~> 1.11"
spec.add_dependency "rake", "~> 10.0"
spec.add_development_dependency "rspec", "~> 3.0"
spec.add_dependency "rack"
spec.add_dependency "erubis"
并且我们加入了 rack, erubis 等依赖。这个后续会提到作用。
####创建我们的应用项目 现在我们的 gem 已经创建好了。接下来就是创建我们的应用项目来使用这个 gem。
在终端创建一个文件夹
> mkdir shuriken-demo
> cd shuriken-demo
> mkdir config
> mkdir app
> touch Gemfile #创建gemfile
在你的 Gemfile 里加上我吗现在要用的这个 gem
#shuriken-demo/Gemfile
source 'https://rubygems.org'
gem 'Shuriken', path: '~code/Shuriken'
gem 之后的 path 为 本地 gem 路径 由于还在开发阶段 所以暂不上传到你的 git / ruby gems 网站
然后执行 bundle
> cd shuriken-demo
> bundle
学过 java 的同学都知道。java 有 servelt , 那么 ruby 有什么呢?对了。是 rack。
我们现在暂时要打造的是一个很小的基于 rack 的框架 因此少不了 rack。
在 shuriken-demo 里创建 config.ru 并且添加如下内容
#shuriken-demo/config.ru
run proc{
[200,{'Content-Type'=>'text/html'},
["Hello,Shuriken"]]
}
Rack 的启动代表着 对于每个请求执行这个脚本,在这个例子里所有的请求都返回 hello shuriken 的 200 返回 html
在 shuriken-demo 项目目录下 启动他
rackup -p 3001
打开你的浏览器 输入 localhost:3001 就可以看到 hello shuriken 的字样了!
进入你的 Shuriken 路径下 打开 lib/Shuriken.rb
# Shuriken/lib/Shuriken.rb
require 'Shuriken/version'
module Shuriken
class Application
def call(env)
[200, {'Content-Type' => 'text/html'},
["Hello from Ruby on Shuriken!"]
end
end
end
然后在你的 shuriken-demo 项目里 创建 config/application.rb 并且添加
require 'Shuriken'
module ShurikenDemo
class Application < Shuriken::Application
end
end
然后修改你的 conifg.ru
#shuriken-demo/config.ru
require './config/application'
run ShurikenDemo::Application.new
然后执行 rack up -p 3001 就可以看到"Hello from ruby on shuriken"的字样了----第一章结束 -2016.11.14
##第二章
首先,我们梳理一下思路,路由从浏览器进入。到我们的 rack run env 里。这些路由带着参数。带着特有的 path_info . 所以我们首先要拿到 path_info 并且去进行解析。然后去和我们的 action 以及 controller 进行匹配。此外,我们还要能确保 controller 能够自动加载。不用手动去 require。还要能够渲染页面模板。而不是单纯的渲染 html 字符串。并且能够像 rails 那样去使用 action 里 的实例变量。让我们一步一步来吧。
#####rails 里的自动加载
首先我们要理解自动加载,通常我们用 const_get() 去获取 contstant。但是如果没有 require 进来则会抛出异常。现在我们在 lib/Shuriken/loader 里加入如下代码
class Object
def self.const_missing(c)
require Shuriken.to_underscore(c.to_s)
Object.const_get(c)
end
end
然后在我们的 lib/Shuriken.rb 里 require 进去
# lib/Shuriken.rb
require 'Shuriken/loader'
然后我们现在要根据路由去执行对应的 controller 以及 action
还是修改这个文件
#lib/Shuriken.rb
module Rulers
class Application
def call(env)
klass, act = get_controller_and_action(env)
controller = klass.new(env)
text = controller.send(act)
[200, {'Content-Type' => 'text/html'},
[text]]
end
end
end
然后还是在 Application class 里添加 get_controller_and_action 这个方法
def get_controller_and_action(env)
_, cont, action, after =
env["PATH_INFO"].split('/', 4)
cont = cont.capitalize # "User"
cont += "Controller" # "UserController"
[Object.const_get(cont), action]
end
我们需要一个基础 controller 来让我们的应用进行继承,所以创建 lib/Shuriken/controller.rb 并且在lib/Shuriken.rb require 进去
#lib/Shuriken/controller.rb
module Shuirken
class Controller
def initialize(env)
end
end
end
打开我们的 shuriken-demo 创建我们的控制器 **app/controllers/user_controller
class UserController < Shuriken::Controller
def hello
'hello'
end
end
现在我们的控制器加好了 自动加载的代码也写好了。那么怎么像 rails 那样自动加载这个 controller 呢。你需要在config/application.rb 下加这些内容
#config/application.rb
#在 require 'Shuirken'之后添加以下代码
$LOAD_PATH << File.join(File.dirname(__FILE__),
"..", "app","controllers")
然后执行 rackup -p 3001
打开你的浏览器 输入 "localhost:3001/user/hello" 你会发现一个错误:
NameError: wrong constant name
Favicon.icoController
.../gems/rulers-0.0.3/lib/rulers/routing.rb:9:in
`const_get'
.../gems/rulers-0.0.3/lib/rulers/routing.rb:9:in
`get_controller_and_action'
.../gems/rulers-0.0.3/lib/rulers.rb:7:in `call'
.../gems/rack-1.4.1/lib/rack/lint.rb:48:in
`_call'
(...more lines...)
是的。我们有一个站点图标请求忘记了。马上补上: 打开 Shuriken 项目 里的 lib/Shuriken.rb
# rulers/lib/Shuriken.rb
module Rulers
class Application
def call(env)
if env['PATH_INFO'] == '/favicon.ico'
return [404,
{'Content-Type' => 'text/html'}, []]
end
klass, act = get_controller_and_action(env)
controller = klass.new(env)
text = controller.send(act)
[200, {'Content-Type' => 'text/html'},[text]]
end
end
end
也许你会觉得这是一个糟糕的设定。不过最后我们会修复它。至少现在让他可以先工作起来。