模块化Sinatra应用程序:我可以用方法替换块吗?

时间:2015-02-13 16:46:27

标签: ruby module sinatra modular

您是否已成功以这种方式重构Sinatra应用程序?:

require 'sinatra/base'

class UserApp < Sinatra::Base
  get '/' do
    content_type :json
    User.all.to_json
  end

  get '/:id' do |id|
    content_type :json
    User.find(id).to_json
  end

  # etc, etc.  (there are many routes)
end

后?

require 'sinatra/base'
require 'user_routes'

class UserApp < Sinatra::Base
  register UserRoutes
end

# ----- a separate file -----
module UserRoutes
  def list
    content_type :json
    User.all.to_json
  end

  def find(id)
    content_type :json
    User.find(id).to_json
  end

  def self.registered(app)
    app.get '/', &UserRoutes.list # <-- this is the piece I cannot figure out
    app.get '/:id', &UserRoutes.find # <-- this is the piece I cannot figure out

    # etc, etc.  (there are many routes)
  end
end

我似乎无法弄清楚如何将UserModule的方法传递给app.get,使得调用这些方法的范围与简单传递一个块相同(例如,这些方法怎么样?可以访问content_type和其他Sinatra功能。)


ruby 2.0.0

这是问题的简化版本

1 个答案:

答案 0 :(得分:1)

首先,为了能够用Module.method idiom调用模块方法,你应该在模块范围内声明它们:

module UserRoutes
  #   ⇓⇓⇓⇓⇓
  def self.list
    content_type :json
    User.all.to_json
  end
  ...
end

现在你可以:

app.get '/', &proc{ |_, *args| UserRoutes.send(:list, *args) }

请注意,结果为performance penalties

Further reading