模块化Sinatra应用程序,设置错误处理&全局配置

时间:2014-07-28 14:13:19

标签: ruby sinatra rack

我正在使用Sinatra构建一个小的Ruby API,我想让一些错误和配置设置为在全局级别工作,这样我就不需要在每个的开头设置它们了。类。

我的结构是:

content_api.rb

require 'sinatra/base'
require 'sinatra/namespace'
require 'sinatra/json'
require 'service_dependencies'
require 'api_helpers'
require 'json'

module ApiApp
  class ContentApi < Sinatra::Base

    helpers Sinatra::JSON
    helpers ApiApp::ApiHelpers
    include ApiApp::ServiceDependencies

    before do
      content_type :json
    end

    get '/' do
      content = content_service.get_all_content
      content.to_json
    end

    get '/audio' do
      package =content_service.get_type 'Audio'
      package.to_json
    end

    get '/video' do
      package =content_service.get_type 'Video'
      package.to_json
    end

    get '/document' do
      package =content_service.get_type 'Document'
      package.to_json
    end

  end
end

config.ru:

$LOAD_PATH.unshift *Dir[File.join(File.dirname(__FILE__), '/src/**')]
$LOAD_PATH.unshift *Dir[File.join(File.dirname(__FILE__), '/src/api/**')]

require 'content_api'
require 'package_api'
require 'utility_api'
require 'sinatra/base'


configure do
  set :show_exceptions => false
end

error { |err| Rack::Response.new([{'error' => err.message}.to_json], 500, {'Content-type' => 'application/json'}).finish }

Rack::Mount::RouteSet.new do |set|
    set.add_route ApiApp::ContentApi, {:path_info => %r{^/catalogue*}}, {}, :catalogue
    set.add_route ApiApp::PackageApi, {:path_info => %r{^/package*}}, {}, :package
    set.add_route ApiApp::UtilityApi, {:path_info => %r{^/health_check*}}, {}, :health_check
  end

当我运行它时,它会运行正常,但当我强制500错误(关闭MongoDb)时,我得到一个标准的html类型错误,指出:

<p id="explanation">You're seeing this error because you have
enabled the <code>show_exceptions</code> setting.</p>

如果我添加

configure do
      set :show_exceptions => false
    end

    error { |err| Rack::Response.new([{'error' => err.message}.to_json], 500, {'Content-type' => 'application/json'}).finish }

在content_api.rb文件中,然后我收到一个JSON错误,因为我希望收到。 然而,当我构建这个模块时,我不想在每个班级的顶部重复自己。

有一种简单的方法可以使这项工作吗?

2 个答案:

答案 0 :(得分:3)

最简单的方法是重新打开Sinatra::Base并在那里添加代码:

class Sinatra::Base
  set :show_exceptions => false

  error { |err|
    Rack::Response.new(
      [{'error' => err.message}.to_json],
      500,
      {'Content-type' => 'application/json'}
    ).finish
  }
end

但这可能并不可取,如果您的应用包含其他非json模块,则会导致问题。

更好的解决方案可能是创建一个可以在模块中使用的Sinatra extension

module JsonExceptions

  def self.registered(app)
    app.set :show_exceptions => false

    app.error { |err|
      Rack::Response.new(
        [{'error' => err.message}.to_json],
        500,
        {'Content-type' => 'application/json'}
      ).finish
    }
  end
end

然后您可以在模块中注册它来使用它:

# require the file where it is defined first
class ContentApi < Sinatra::Base
  register JsonExceptions
  # ... as before
end

答案 1 :(得分:2)

作为替代方案,继承:

class JsonErrorController < Sinatra::Base
  configure do
    set :show_exceptions => false
  end

  error { |err| Rack::Response.new([{'error' => err.message}.to_json], 500, {'Content-type' => 'application/json'}).finish }

end

class ContentApi < JsonErrorController
  # rest of code follows…
end

Sinatra启动并运行 p73:

  

不仅设置,而且Sinatra类的每个方面都将是   由其子类继承。这包括所有的定义路线   错误处理程序,扩展,中间件等。