Ruby on rails Rails 4-只响应JSON而不响应HTML

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:

我试图在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 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