我的config / routes.rb文件…
Rails.application.routes.draw do namespace :api, defaults: {format: 'json'} do namespace :v1 do resources :hotels do resources :rooms end end end
我的app / controllers / api / v1 / hotels_controller.rb
module Api module V1 class HotelsController < ApplicationController respond_to :json skip_before_filter :verify_authenticity_token def index @hotels = Hotel.all respond_with ({hotels: @hotels}.as_json) #respond_with(@hotels) end def show @hotel = Hotel.find(params[:id]) respond_with (@hotel) end def create @hotel = Hotel.new(user_params) if @hotel.save respond_with (@hotel) #LINE 21 end end private def user_params params.require(:hotel).permit(:name, :rating) end end end end
当我通过Postman进行POST时,我的数据保存得很好,但是却出现了NoMethodError。为什么是这样?问题似乎发生在第21行,这是response_with(@hotel)行。是否应该通过show方法不只是用json ouput响应新创建的酒店?
(1.1ms) COMMIT Completed 500 Internal Server Error in 76ms NoMethodError (undefined method `hotel_url' for #<Api::V1::HotelsController:0x0000010332df58>): app/controllers/api/v1/hotels_controller.rb:21:in `create' Rendered /Users/.rvm/gems/ruby-2.0.0-p451@railstutorial_rails_4_0/gems/actionpack-4.1.0/lib/action_dispatch/middleware/templates/rescues/_source.erb (1.0ms) Rendered /Users/.rvm/gems/ruby-2.0.0-p451@railstutorial_rails_4_0/gems/actionpack-4.1.0/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (1.7ms) Rendered /Users/.rvm/gems/ruby-2.0.0-p451@railstutorial_rails_4_0/gems/actionpack-4.1.0/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (1.4ms) Rendered /Users/.rvm/gems/ruby-2.0.0-p451@railstutorial_rails_4_0/gems/actionpack-4.1.0/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (31.5ms)
由于您的路由位于API + v1命名空间中,因此您实际上需要api_v1_hotel_url(@hotel)在成功创建资源后重定向到。当然,这是一个API,并且没有真正的重定向,但是默认的Rails响应器不知道这一点。它还不知道您的路由名称空间。
api_v1_hotel_url(@hotel)
仅使用默认响应者,您将不得不做
respond_with :api, :v1, @hotel
这样,Rails将构建一个存在的URL。或者,您可以创建一个删除该:location选项的自定义响应器。这是默认的响应者:http : //api.rubyonrails.org/files/actionpack/lib/action_controller/metal/responder_rb.html
:location
通读该类的源代码对理解非常有帮助respond_with。例如,if record.save在使用respond_with此“响应程序” 之前,不需要使用。Rails将检查记录是否为您成功保存,如果保存失败,则呈现422错误。
respond_with
if record.save
无论如何,您可以看到响应者在其初始化程序中设置了很多变量:
def initialize(controller, resources, options={}) @controller = controller @request = @controller.request @format = @controller.formats.first @resource = resources.last @resources = resources @options = options @action = options.delete(:action) @default_response = options.delete(:default_response) end
如果您将此响应程序子类化,则可以进行如下操作:
class CustomResponder < ActionController::Responder def initialize(*) super @options[:location] = nil end end
您可以使用来设置控制器的响应者responder=:
responder=
class AnyController < ActionController::Base self.responder = CustomResponder # ... end
为了清楚起见,让我回顾一下:
show
hotel_url
api_v1_hotel_url
nil