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

时间:2018-01-09 21:48:39

标签: ruby-on-rails ruby rack

作为一项学习练习,我正在制作一个简化的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文件中进行操作。我该怎么做呢?我试过的一切都会引发错误。

1 个答案:

答案 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"}