在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
看起来不会更好?
答案 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
结合使用。你只能使用其中一种。
这应该清楚地表明您在控制器中尝试做太多事情。例如,如果您正在为csv
和xml
响应执行常见操作,那么您可能应该在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
语法:
是标准Rails Way™
负责渲染正确的文件
不仅看起来更好,而且更易于维护
你应该试着坚持下去。
答案 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]) }
或类似的东西。