在 Ruby 中,如何将一个块从 class 中移出到它自己的文件中?

In Ruby, how do I move a block out of a class into it's own file?

作为一项学习练习,我正在制作一个类似于 Rails 的简化 MVC 框架。 这是流程的简化版本。框架和应用在这里合并。

1) 启动一个新的机架应用程序。

# config.ru
require_relative 'config/application.rb'
run Application.new

2)实例化一个Rack请求对象,然后实例化一个新的Routerclass实例,传递请求对象,调用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) 创建 Router 实例时,我正在构建一个 @routes 变量,该变量分配给应用程序路由的哈希值及其相应的控制器和操作。像 Rails 这是一个块。绘制和匹配方法在同一个路由器 class 中定义。 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 我想要绘图块在它自己的文件中,这样就可以在应用程序的 config/routes.rb 文件中设置路由,并在框架的 lib/router.rb 文件中进行操作.我该怎么做呢?我尝试过的一切都会引发错误。

虽然它不像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"}