作为一项学习练习,我正在制作一个简化的Rails-like MVC框架。 这是流程的简化版本。框架和应用程序在这里结合在一起。
1)启动一个新的Rack应用程序。
# config.ru
require_relative 'config/application.rb'
run Application.new
2)实例化Rack请求对象,然后实例化一个新的Router类实例,传递请求对象,并调用resolve方法。
# config/application.rb
require_relative '../lib/router.rb'
class Application
def call(env)
request = Rack::Request.new(env)
Router.new(request).resolve
end
end
3)创建路由器实例时,我正在构建一个@routes变量,该变量分配给应用程序路由的散列及其相应的控制器和操作。像Rails一样,这是一个块。 draw和match方法在同一个Router类中定义。 Draw运行块,match方法将每个路由添加到@routes哈希。这很好。
# lib/router.rb
class Router
attr_reader :request, :routes
def initialize(request)
@request = request
@routes = {}
draw do
match "/", "pages#home"
match "/contact", "pages#contact"
match "/about", "pages#about"
end
end
def draw(&block)
instance_eval(&block)
end
def match(url, controller_action)
@routes["#{url}"] = controller_action
end
# more code... def resolve, etc.
end
和Rails一样,我想在它自己的文件中使用draw块,这样就可以在app的config / routes.rb文件中设置路由,并在框架的lib / router.rb文件中进行操作。我该怎么做呢?我试过的一切都会引发错误。
答案 0 :(得分:2)
虽然它不像Rails那么漂亮,你可以尝试根据你的情况进行调整:
档案 routes.rb :
class Routes
def self.routes
Proc.new do
match 'url', 'foo#bar'
match 'url2', 'foo#baz'
end
end
end
文件 router.rb :
require_relative './routes'
class Router
attr_reader :routes
def initialize
@routes = {}
draw Routes.routes
end
def draw(block)
instance_eval(&block)
end
def match(url, handler)
@routes[url] = handler
end
end
所以你可以在一个单独的文件路径中定义:
p Router.new.routes # => {"url"=>"foo#bar", "url2"=>"foo#baz"}