Ruby on rails Rails 4-只响应JSON而不响应HTML
我试图在rails 4中构建一个API,但遇到了一个问题,rails在使用Ruby on rails Rails 4-只响应JSON而不响应HTML,ruby-on-rails,ruby-on-rails-4,Ruby On Rails,Ruby On Rails 4,我试图在rails 4中构建一个API,但遇到了一个问题,rails在使用respond\u to:json并尝试访问html版本时返回500错误,而不是406错误 下面是一个示例控制器,演示了该问题: class PostsController < ApplicationController respond_to :json def index @posts = Post.all end end class PostsController406您可以使用head:
respond\u to:json
并尝试访问html版本时返回500错误,而不是406错误
下面是一个示例控制器,演示了该问题:
class PostsController < ApplicationController
respond_to :json
def index
@posts = Post.all
end
end
class PostsController
我还有一个用于index
的jbuilder视图,在通过JSON访问时可以使用。如果我尝试在没有JSON扩展的情况下访问路由,它会尝试加载HTML模板(该模板不存在)并返回500错误,而不仅仅是呈现JSON或返回406错误
这可能是什么原因造成的?欢迎提供帮助。当您使用before_筛选器时,如果请求未定义的格式,您将有一个406不可接受 例如:
class SomeController < ApplicationController
respond_to :json
def show
@record = Record.find params[:id]
respond_with @record
end
end
class ApplicationController < ActionController::Base
before_filter :check_format
def check_format
render :nothing => true, :status => 406 unless params[:format] == 'json'
end
end
进一步资料:
为避免加载不存在的HTML模板,请在config/routes.rb中将默认资源类型设置为JSON:
resources :posts, :defaults => { :format => :json }
我相信这里有两个部分:
1) rails中仅json请求 2) rails中仅json的响应 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) 配置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
您可以通过一个before过滤器来设置它,该过滤器将请求显式设置为JSON
request.format=:json
您可以试试这个,因为我也面临这个问题,现在使用这个解决方案就解决了
class PostsController < ApplicationController
respond_to :json
def index
@posts = Post.all
render json: @posts
end
end
class PostsController
当您尝试使用json响应时,因为您只需要我使用的一些属性
@my_model=Model.select(:attributeN, :attributeN......, attributeN)
respond_to do |format|
format.json {
render json: @my_model
}
end
我建议您尝试
gem'active\u model\u serializers'
。它真的很棒而且保持干净
应用程序控制器:
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
def index
render json: Post.all
end
发布控制器:
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
def index
render json: Post.all
end
在Rails 4中,您需要传递lambda以强制路由上的约束 不幸的是,这将不起作用,因为它仍将尝试提供(或尝试提供)html模板,因为格式是可选参数:
resources :posts, constraints: { format: 'json' }
这确实有效(使用lambda):
请参阅中的第二个(最后一个)注释。
约束对POST请求不起作用,然后我尝试了默认值
它对所有人都有效
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
我做这件事有点晚了,但关于您对以下内容的评论:
我希望所有的响应都是JSON
最简单的解决办法是:
respond_to do |format|
format.all { render :json => @posts }
end
可能的重复:我确实看到了,但我想知道为什么它不能仅使用respond\u to:json
设置respond\u to:json
和respond\u with@posts
正确地使用HTTP/1.1406进行响应,这在生产中是我无法接受的。在开发过程中,您会收到一个“HTTP/1.1500内部服务器错误”和一个ActionController::UnknownFormat
很抱歉,我试图回答,但我的帖子被版主删除了,因为我还回答了另一个“可能重复的”问题,尽管这个问题更清楚。所以给你。。。在Rails 4中,您必须在路由中传递lambda以强制执行这样的约束:resources:posts,constraints:lambda{| req | req.format==:json}
您可以在Rails指南的第二个注释中看到更多信息:我的问题是respond_to:json
仍然允许html响应通过。我希望所有响应都是JSON,而不管请求的格式如何。您是否在视图上创建了JSON?params[:format]=“JSON”
是不够的。当使用Accept:application/json
头发出请求时,params[:format]为空,但Rails仍然使用json进行响应。这不提供约束,这是问题所暗示的。如果没有指定.json格式,rails将不会在路由上匹配,并在层次结构上继续。而不是params[:format]==“json”| | request.headers[“Accept”]=~/json/
您可以使用request.format.symbol==“json
。很好的调用。更新为request.format==:json
作为symbol
不是必需的,而不是render:nothing=>true,:status=>406
您可以使用head:not_acceptable
这似乎不适用于范围
,但是默认值:{format:'json'}
。
respond_to do |format|
format.all { render :json => @posts }
end