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

Ruby 模块化Sinatra应用程序,设置错误处理和;全局配置,ruby,sinatra,rack,Ruby,Sinatra,Rack,我正在使用Sinatra构建一个小型RubyAPI,我希望将一些错误和配置设置为在全局级别上工作,这样我就不需要在每个类的开头设置它们 我的结构是: content_api.rb require 'sinatra/base' require 'sinatra/namespace' require 'sinatra/json' require 'service_dependencies' require 'api_helpers' require 'json' module ApiApp c

我正在使用Sinatra构建一个小型RubyAPI,我希望将一些错误和配置设置为在全局级别上工作,这样我就不需要在每个类的开头设置它们

我的结构是:

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
当我运行它时,它会正常运行,但当我强制执行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错误,这是我想要接收的。 然而,当我构建这个模块时,我不想在每堂课的顶端重复我自己


有没有一个简单的方法可以让它工作

最简单的方法是重新打开
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模块,则会导致问题

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

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
#需要首先定义它的文件
类ContentApi
作为替代,继承:

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
classjsonerrorcontrollerfalse
结束
错误{err{Rack::Response.new([{'error'=>err.message}.to_json],500,{'Content-type'=>'application/json'})。完成}
结束
类ContentApi
从Sinatra启动并运行p73:

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


谢谢,把它作为一个扩展来创建是一种享受,我认为这样做更干净,因为它只是在每个类的顶部重复一行。感谢againthanks iain,我自己也离这个解决方案不远,我个人喜欢扩展的想法,因为我们在API中使用了sinatra,我已经将带有自定义错误类的扩展变成了一个供我们使用的宝石internally@Vade当然,我想我可能也会为这样一个单一的需求做一个扩展。您可以考虑将两者混合,创建多个扩展,以便在API中使用,并创建一个ApCopter类,您可以从其中继承它们来创建新API。
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