Sinatra:处理每条路线的渲染功能?

时间:2013-12-06 09:31:31

标签: ruby routes sinatra output

我正在尝试解决辛特拉的respond_with和respond_to,路线等等。 doco似乎确实谈到了将代码移到某一点,但我无法弄清楚如何去做。

我有一系列路由都返回Json或XML,例如:

respond_with :index, data do |f|
  f.xml { XmlSimple.xml_out(data, {'XmlDeclaration' => true}) }
  f.on('application/json') { data.to_json }
end

XmlSimple调用可能会有一些不同的选项。在一种情况下,路由会执行自己的XML呈现(因为它很复杂)。接下来,我想添加可选的“漂亮”输出,也可以添加某种HTML模板化输出。

我想做的是让我的所有路由都返回哈希或字符串。如果它是一个字符串,那么我们可以将它传递给Sinatra,以便像往常一样输出。如果路由返回一个哈希值,那么它将以与上面类似的方式呈现,具体取决于请求或查询字符串参数。

我的问题是:如何在路由输出上配置某种“defualt”输出过滤器?

2 个答案:

答案 0 :(得分:1)

根据Sinatra文档,“在相同上下文中的每个请求之后评估过滤器后,还可以修改请求和响应。”因此,你可以编写一个全局的后置过滤器,根据它的类别,或者你想要的任何验证,以不同的方式处理这些数据。在路由中访问的实例变量可以在Before / After路由中使用。

get '/foo' do
  data = some_data
end

after do
  data if data.class == String
  data.do_more_things if data.class == Hash
end

如果这不起作用,我相信您可以简单地编写一个方法并在路径末尾的数据上调用它:

def format_for_response(data)
  data if data.class == String
  data.do_more_things if data.class == Hash
end

get '/foo' do
  format_for_response(data)
end

答案 1 :(得分:0)

回答我自己的问题......

在@ sean-larkin的帮助下,我在Sinatra Extension(http://www.sinatrarb.com/extensions.html)中使用了一种方法。这个想法是帮助者可以访问“参数”,“请求”,“响应”等,因此可以对所需的输出格式做出决策。

这是一个示例渲染方法(保存到lib / sinatra / render.rb中),除非在请求的查询字符串中指定“?pretty = true”,否则它将输出缩小的XML / JSON:

require 'sinatra/base'
require 'xmlsimple'

module Sinatra
  module OutputRender
    module Helpers
      def render_output(data, xml_opts = {})
        if data.class == String
          # If it's already rendered, then just output it
          return data
        end
        pretty = (params['pretty'] && params['pretty'] == 'true') ? true : false
        respond_with :index, data do |f|
          f.on(:xml) { XmlSimple.xml_out(data, xml_opts) }
          f.on(:json) { pretty ? ::JSON.pretty_generate(data) : data.to_json }
        end
      end
    end
    def self.registered(app)
      app.helpers OutputRender::Helpers
    end
  end
  register OutputRender::Helpers
end

...然后在有路径的文件中(例如lib / banana.rb)我有这个:

require "sinatra/base"
require "sinatra/render"
get '/banana', :provides => [:xml, :json] do
  x = Hash.new()
  x['one'] = two

  render_output x
end

所以我留下了一个我希望避免的'渲染功能',但这似乎是一种干净的方式来做我想要的事情。我现在要添加数据的HTML呈现,这样如果你使用浏览器来查找路径就有很好的浏览器输出,并且努力使XML输出始终有一个声明,总是低于特定的根节点等等。