Rails:respond_to vs“case”条件

时间:2012-02-08 15:19:42

标签: ruby-on-rails

在Rails中使用respond_to而不是case语句有什么好处? 我有几个实例变量,我想为某些格式设置相同的方式,但不是HTML。这似乎不起作用:

respond_to do |format|
  format.html do
    # ...
  end
  format.any(:csv, :xml) do
    # common stuff
  end
  format.csv do
    # ...
  end
  format.xml do
    # ...
  end
end

我想我最终会使用几个case request.format而根本不使用respond_to

case request.format
when 'html'
  # ...
when 'csv', 'xml'
  # common stuff
end
# more common stuff
case request.format
when 'html'
  # render
when 'csv'
  # custom render csv
when 'xml'
  # render xml with a template
end

所以我想知道respond_to的好用例是什么,其中case request.format看起来不会更好?

4 个答案:

答案 0 :(得分:8)

respond_to不仅可以找出客户期望的响应类型,还可以告诉rails您愿意提供哪种类型的响应

例如,我们有这个控制器的简单场景:

class SimpleController < ApplicationController
  def index
    respond_to :html, :json
  end
end

客户端发送期望xml响应的请求

curl -H "Accept: application/xml" \
     -H "Content-Type: application/xml" \
     -X GET "host:port/simple/index"

Rails会以406

回复
Completed 406 Not Acceptable in 0ms (ActiveRecord: 0.0ms)

但是,如果您只是在示例中使用request.format过滤case,则客户端会收到500错误,因为rails无法找到请求格式的相应模板

当然,您也可以在级别调用respond_to,并在 routes.rb

中指定回复格式

如果您想对此进行更深入的解释,请深入了解rails源代码和api文档。

答案 1 :(得分:3)

首先,respond_to阻止无效的原因是因为您将format.any(:csv, :xml)format.csv结合使用。你只能使用其中一种。

这应该清楚地表明您在控制器中尝试做太多事情。例如,如果您正在为csvxml响应执行常见操作,那么您可能应该在lib目录中创建一个类:

# lib/foo_serializer.rb
class FooSerializer
  def initialize(bar)
    @bar = bar
  end

  def do_stuff
    @bar.to_s
  end
end

然后为每种类型的响应调用其中一种方法:

respond_to do |format|
  format.html do
    # ...
  end
  format.csv do
    FooSerializer.new(data).do_stuff
    # ...
  end
  format.xml do
    FooSerializer.new(data).do_stuff
    # ...
  end
end

respond_to语法:

  1. 是标准Rails Way™

  2. 的一部分
  3. 负责渲染正确的文件

  4. 不仅看起来更好,而且更易于维护

  5. 你应该试着坚持下去。

答案 2 :(得分:2)

request.format字段在respond_to块不合适的情况下非常有用。

例如,我正在使用sunspot gem进行搜索,我的控制器如下所示:

def index
  case request.format
  when 'xlsx'
    per_page: Person.count
  when 'html'
    per_page: 30
  end
  @search = Person.search do
    with :name, params[:name]
    fulltext params[:search_term]
    paginate page: params[:page], per_page: per_page
  end
  @people = @search.results
  respond_to do |format|
    format.xlsx {send_file @people.to_xlsx, filename: 'people.xlsx'}
    format.html
  end
end

答案 3 :(得分:0)

我已经和Rails合作了一段时间,我总是以这种形式看到respond_to:

respond_to do |format|
  format.js
  format.html # index.html.erb
  format.xml  { render :xml => @posts }
end

我不知道你会在哪里看到嵌套的东西。

编辑:

有关分页,请参阅

https://github.com/mislav/will_paginate

编辑2:

format.html { render :html => Post.paginate(:page => params[:page]) }

或类似的东西。