简体   繁体   English

Rails response_with在索引和创建方法上的行为不同

[英]Rails respond_with acting different in index and create method

I am building a simple json API in Rails 3.1. 我在Rails 3.1中构建一个简单的json API。 I created a controller that has two functions: 我创建了一个具有两个功能的控制器:

class Api::DogsController < ActionController::Base
  respond_to :json, :xml
  def index
    respond_with({:msg => "success"})
  end

  def create
    respond_with({:msg => "success"})
  end
end

In routes.rb I have 在routes.rb我有

namespace :api do 
  resources :dogs
end

When I make a get request to http://localhost:3000/api/dogs I get the correct json from above. 当我向http:// localhost:3000 / api / dogs发出get请求时,我从上面得到了正确的json。 When I make a post to the same url, I get a rails exception: 当我对同一个网址发帖时,我得到了一个rails例外:

ArgumentError in Api::DogsController#create
Nil location provided. Can't build URI.
actionpack (3.1.0) lib/action_dispatch/routing/polymorphic_routes.rb:183:in `build_named_route_call`
actionpack (3.1.0) lib/action_dispatch/routing/polymorphic_routes.rb:120:in `polymorphic_url'
actionpack (3.1.0) lib/action_dispatch/routing/url_for.rb:145:in `url_for'

But if I change the create code to 但是,如果我将创建代码更改为

def create
  respond_with do |format|
    format.json { render :json => {:msg => "success"}}
  end
end

it returns the json just fine. 它返回json就好了。

Can someone explain what is going on here? 有人能解释一下这里发生了什么吗?

After coming across this issue myself and overcoming it, I believe I can supply an answer. 在我自己遇到这个问题并克服它之后,我相信我能提供答案。

When you simply say: 当你简单地说:

def create
  respond_with({:msg => "success"})
end

What rails tries to do is "guess" a url that the newly created resource is available at, and place it in the HTTP location header . rails试图做的是“猜测”新创建的资源可用的URL,并将其放在HTTP位置头中 That guess fails miserably for a hash object (the location it deduces is nil, which leads to the error message you are seeing). 对于一个哈希对象,这个猜测失败了(它推导出的位置是nil,这会导致你看到的错误信息)。

To overcome this issue, then, you would need to do the following: 要解决此问题,您需要执行以下操作:

def create
  respond_with({:msg => "success"}, :location => SOME_LOCATION)
end

Assuming that you know where the new resource is located. 假设您知道新资源的位置。 You can even specify "nil" as "SOME_LOCATION" and that will work (somewhat absurdly). 您甚至可以将“nil”指定为“SOME_LOCATION”,这将起作用(有点荒谬)。

I had the problem myself. 我自己有问题。

It is, like Aubergine says, something related with the http location header. 就像Aubergine所说的那样,它与http位置标题有关。

Actually, rails seems to build this location using by default the show route . 实际上,rails似乎默认使用show route来构建此位置。

If you don't have a show action , -which is weird in an API, but can happen (i think)`, then you have to set a location by yourself. 如果你没有show action ,这在API中很奇怪,但可能发生(我认为)`,那么你必须自己设置一个位置。 I have no idea what is the standard in this case. 我不知道在这种情况下标准是什么。

If it happens that you need a show route, then code it, and everything should work fine. 如果它发生你需要一个show route,然后编码,一切都应该正常工作。

Cheers. 干杯。

I have found that errors = {:error => @device.errors.full_messages} respond_with( errors, :status => :bad_request, :location => nil) works. 我发现errors = {:error => @ device.errors.full_messages} respond_with(errors,:status =>:bad_request,:location => nil)有效。 The :location is required and setting it to nil helps when using with spec: expect(last_response.status).not_to eql 201 expect(last_response.location).to be_nil :当需要使用时,位置是必需的并且将其设置为nil有助于:expect(last_response.status).not_to eql 201 expect(last_response.location).to be_nil

The problem I was having is that I was not returning the errors hash, just the status. 我遇到的问题是我没有返回错误哈希,只是状态。 Adding the errors hash and setting the location myself solved it. 添加错误哈希并设置位置自己解决了它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM