Ruby-on-rails Rails 4 - 仅响应 JSON 而不是 HTML
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21978580/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Rails 4 - Respond only to JSON and not HTML
提问by Tom Brunoli
I'm trying to build an API in rails 4, and am having an issue where rails returns a 500 error instead of a 406 when using respond_to :jsonand trying to access the html version.
我正在尝试在 rails 4 中构建 API,并且遇到一个问题,即在使用respond_to :json和尝试访问 html 版本时,rails 返回 500 错误而不是 406 。
Here's an example controller demonstrating the problem:
这是一个演示问题的示例控制器:
class PostsController < ApplicationController
respond_to :json
def index
@posts = Post.all
end
end
I also have a jbuilder view for indexthat works when accessing via JSON. If I try accessing the route without the JSON extension, It attempts to load the HTML template (which doesn't exist) and returns a 500 error, instead of just rendering JSON or returning a 406 error.
index当通过 JSON 访问时,我也有一个 jbuilder 视图。如果我尝试访问没有 JSON 扩展名的路由,它会尝试加载 HTML 模板(不存在)并返回 500 错误,而不是仅呈现 JSON 或返回 406 错误。
What could be causing this? Cheers for any help.
什么可能导致这种情况?为任何帮助干杯。
回答by csi
I believe there are 2 parts here:
1) json only requestsin rails
2) json only responsesin rails
我相信这里有 2 个部分:
1) json 只在 rails 中请求
2) json 只在 rails 中 响应
1) Configure your application controller to ensure json requestsonly
1) 配置您的应用程序控制器以确保仅 json 请求
# app/controller/application_controller.rb
before_action :ensure_json_request
def ensure_json_request
return if request.format == :json
render :nothing => true, :status => 406
end
2) Configure your Rails API routes to ensure json responsesonly
2) 配置您的 Rails API 路由以确保仅 json 响应
# config/routes.rb
MyApp::Application.routes.draw do
namespace :api, constraints: { format: 'json' } do
namespace :v1 do
resources :posts
end
end
end
回答by Chance Feick
To avoid loading the non-existent HTML template, set the default resource type as JSON in config/routes.rb:
为避免加载不存在的 HTML 模板,请在 config/routes.rb 中将默认资源类型设置为 JSON:
resources :posts, :defaults => { :format => :json }
回答by Sia
In Rails 4, you need to pass a lambda to enforce the constraint on a route.
在 Rails 4 中,您需要传递一个 lambda 来对路由实施约束。
Unfortunately, this will NOT work because it will still try to serve up (or attempt to serve up) an html template since the format is an optional parameter:
不幸的是,这将不起作用,因为它仍然会尝试提供(或尝试提供)一个 html 模板,因为格式是一个可选参数:
resources :posts, constraints: { format: 'json' }
This DOES work (uses the lambda):
这确实有效(使用 lambda):
resources :posts, constraints: lambda { |req| req.format == :json }
See the second (final) note in this section of the Rails guide.
请参阅Rails 指南本部分中的第二个(最后)注释。
回答by Franzé Jr.
As you are using a before_filter, you will have a 406 Not Acceptable if a request for a format is made which is not defined.
当您使用 before_filter 时,如果请求未定义的格式,您将收到 406 Not Acceptable。
Example:
例子:
class SomeController < ApplicationController
respond_to :json
def show
@record = Record.find params[:id]
respond_with @record
end
end
The other way would be to add a before_filter to check for the format and react accordingly.
另一种方法是添加一个 before_filter 来检查格式并做出相应的反应。
Example:
例子:
class ApplicationController < ActionController::Base
before_filter :check_format
def check_format
render :nothing => true, :status => 406 unless params[:format] == 'json'
end
end
But i think, you can just do it:
但我认为,你可以这样做:
respond_to do |format|
format.json { render :json => @posts }
end
Further informations: http://guides.rubyonrails.org/layouts_and_rendering.html
更多信息:http: //guides.rubyonrails.org/layouts_and_rendering.html
回答by A H K
constraintswas not working for POST requests and then I tried defaultsit works for all.
constraints不适用于 POST 请求,然后我尝试defaults它适用于所有人。
namespace :api, :defaults => { :format => 'json' } do
namespace :v1 do
resources :users do
collection do
get 'profile'
end
end
post 'signup' => 'users#create'
post 'login' => 'user_sessions#create'
end
end
回答by Shubham Abrol
You can try this, as I was also facing this issue and now it is solved by using this solution.
你可以试试这个,因为我也遇到了这个问题,现在使用这个解决方案解决了。
class PostsController < ApplicationController
respond_to :json
def index
@posts = Post.all
render json: @posts
end
end
回答by Piotr Usewicz
You can set it by having a before filter that sets the request to JSON explicitly.
您可以通过使用 before 过滤器将请求显式设置为 JSON 来设置它。
request.format = :json
request.format = :json
回答by Ezequiel García
when you try a responses in json is beacuse you only need some properties i used this
当您在 json 中尝试响应时,因为您只需要一些我使用过的属性
@my_model=Model.select(:attributeN, :attributeN......, attributeN)
respond_to do |format|
format.json {
render json: @my_model
}
end
回答by 7urkm3n
I would suggest you to try gem 'active_model_serializers'. Its really awesome and keeps clean.
我建议你试试gem 'active_model_serializers'。它真的很棒并且保持清洁。
ApplicationController:
应用控制器:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception, if: Proc.new { |c| c.request.format != 'application/json' }
protect_from_forgery with: :null_session, if: Proc.new { |c| c.request.format == 'application/json' }
end
Routes:
路线:
namespace :api, defaults: { format: :json } do
resource :posts
end
Posts Controller:
帖子控制器:
def index
render json: Post.all
end

