将 Rails 渲染格式限制为 html 的方法
Posted
技术标签:
【中文标题】将 Rails 渲染格式限制为 html 的方法【英文标题】:Methods for limiting the Rails render format to html 【发布时间】:2010-12-12 20:51:14 【问题描述】:我有一个只有 html 模板的 Rails 2.1.2 站点,例如jobs.html.erb,所以当我请求一个宁静的资源时:
www.mysite.com/jobs/1
如果我要求,它会以 html 呈现我的工作:
www.mysite.com/jobs/1.xml
我得到错误:
模板丢失 缺少模板 视图路径中的jobs/show.xml.erb c:/workspace/mysite/app/views
更糟糕的是我还可以请求类似的东西
www.mysite.com/jobs/1.xyz
确实我看到了错误:
模板丢失 缺少模板 视图路径中的作业/show.xyz.erb c:/workspace/mysite/app/views
要严格呈现 html 内容,告诉 Rails 我不想呈现 .html.erb 文件以外的任何内容的最简洁和最简单的方法是什么。
需要注意的是:
我的一些控制器操作包含对 render() 方法的条件调用,而其他操作使用默认的 Rails 行为,即如果您不调用 render(),那么名为 youraction.html.erb 的模板将被渲染。 我的代码没有使用 responds_to() 方法如果解决方案不在 render/responds_to 级别,那就太好了,因为我必须修改大量操作。也许有一种方法可以配置 Rails 以便只呈现 html 模板?
【问题讨论】:
【参考方案1】:在您的路线中,您可以简单地删除该行:
map.connect ':controller/:action/:id.:format'
并且“.xyz”将不再被路由,导致404错误/。
【讨论】:
删除这一行并不能解决 Rails 3.2.6 中的问题:它已经被注释掉了,但仍然出现 Template Missing 错误。【参考方案2】:您可以使用 Rails Per-Action Overwrite 功能。这是什么? --> 还可以通过将块传递给 respond_with 来覆盖标准资源处理,并指定该操作要覆盖的格式:
class UsersController < ApplicationController::Base
respond_to :html, :xml, :json
# Override html format since we want to redirect to a different page,
# not just serve back the new resource
def create
@user = User.create(params[:user])
respond_with(@user) do |format|
format.html redirect_to users_path
end
end
end
:except And :only 选项
您还可以传入 :except 和 :only 选项以仅支持特定操作的格式(就像使用 before_filter 一样):
class UsersController < ApplicationController::Base
respond_to :html, :only => :index
respond_to :xml, :json, :except => :show
...
end
:任何格式
如果您仍想在个人操作中使用 respond_to,请使用可用作通配符匹配任何未指定格式的 :any 资源格式:
class UsersController < ApplicationController::Base
def index
@users = User.all
respond_to do |format|
format.html
format.any(:xml, :json) render request.format.to_sym => @users
end
end
end
【讨论】:
Jared,您能否更具体地说明三个选项中的哪一个仅适用于 Rails 3!我在 Rails 2.3.4 上运行,并且 :any 选项有效。【参考方案3】:如果您不想使用 responds_to,可以这样做:
class ApplicationController < ActionController::Base
before_filter :allow_only_html_requests
...
def allow_only_html_requests
if params[:format] && params[:format] != "html"
render :file => "#RAILS_ROOT/public/404.html"
end
end
...
end
这将在所有请求之前运行,并且只让那些根本不指定格式或指定 html 格式的请求通过。所有其他人都得到404'd。如果您想返回 406 不可接受,您可以创建一个 public/406.html。
【讨论】:
这实际上并没有返回 404,但它只是将404.html
呈现为 200 响应。您需要添加:status => 404
(或:status => :not_found
)。同样,对于 406,您需要使用 :status => 406
(或 :status => :not_acceptable
)。
如果请求使用 'accept' 标头来请求响应类型,这也会失败,因为它没有存储在 params 中【参考方案4】:
Ben 的解决方案有效。
不过,请考虑 responds_to 解决方案。它更简洁,因为当您不可避免地需要为 javascript json 或 xml 调用打开一个操作时,它提供了灵活性。那你就不用加了
skip_before_filter :allow_only_html_requests, :only => [:show]
我个人喜欢 respond_to 块;它非常具有描述性。
respond_to do |wants|
wants.html
end
块中未指定的任何格式将自动导致返回 HTTP 406 Not Acceptable。挺好的。
【讨论】:
同意。 responds_to 块开辟了一个灵活的世界,如果您可以花时间为每个控制器操作添加一个 .html 文件,这是一个更具前瞻性的解决方案。【参考方案5】:我收到了对 HTML 文件的图像格式无意义的请求,触发了带有 MissingTemplate
的 500。我在行动结束时制定了以下内容:
def show
# [...]
respond_to :html
end
现在我们不会收到错误报告,而是向那个淘气的请求者发出 406。
【讨论】:
以上是关于将 Rails 渲染格式限制为 html 的方法的主要内容,如果未能解决你的问题,请参考以下文章