【问题标题】:Sinatra: Function to handle rendering of every route?Sinatra:处理每条路线渲染的功能?
【发布时间】:2013-12-23 14:20:43
【问题描述】:

我正在尝试计算 Sintra 的 respond_with 和 respond_to、路由等等。该文档似乎确实在谈论将代码移动到某个点,但我不知道该怎么做。

我有一系列路由都返回 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 进行输出。如果路由返回一个哈希,那么它将以与上述类似的方式呈现,具体取决于请求或查询字符串参数。

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

【问题讨论】:

    标签: ruby routes sinatra output


    【解决方案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
    

    【讨论】:

    • 谢谢。我无法让“后”过滤器工作 - 似乎每当路由器返回字符串以外的任何内容时,Sinatra 都会出错,因此“后”过滤器甚至都看不到。 format_for_response() 方法看起来像唯一的方法 - 我希望避免它,而是使用一些“自动”解决方案,但看起来我不走运。
    • 我现在遇到的问题是 format_for_response() 方法需要访问 'request'、'response'、'params' 等,如果它需要模板,则需要连接到模板系统.我刚刚偶然发现了 'Sinatra Extensions' doco - 它的细节有点薄,但它可能是一种方法。
    • 每当我需要从 POST 访问请求数据时,我总是使用“request.body”变量。
    【解决方案2】:

    回答我自己的问题...

    在@sean-larkin 的帮助下,我在 Sinatra 扩展 (http://www.sinatrarb.com/extensions.html) 中使用了一个方法。其想法是 Helpers 可以访问“params”、“request”、“response”等,因此可以对所需的输出格式进行决策。

    这是一个示例渲染方法(保存在 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 输出始终具有声明,始终位于特定根节点下方等。

    【讨论】:

      猜你喜欢
      • 2015-03-28
      • 2015-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-17
      • 2021-04-20
      • 2021-01-19
      相关资源
      最近更新 更多