如何为 ApplicationController 中 after_action 过滤器中的所有操作呈现 json?

Fec*_*ore 3 api controller ruby-on-rails

是否可以在 Rails ApplicationController 中创建一个 after_filter 方法,该方法在每个操作上运行并呈现为 JSON?我正在搭建一个 API,我想将控制器中的每个操作的输出呈现为 JSON。

客户端控制器.rb

def index
  @response = Client.all
end
Run Code Online (Sandbox Code Playgroud)

应用控制器.rb

...
after_action :render_json
def render_json
  render json: @response
end
Run Code Online (Sandbox Code Playgroud)

after_action 永远不会执行,代码中止:

模板丢失。缺少模板客户端/索引,...

如果将render json: @response移动到控制器操作中,则它可以正常工作。

是否有一个过滤器可以让我干燥控制器并将渲染调用移动到基本控制器?

Chr*_*lle 5

你不能渲染 after_action/after_filter。回调 after_action 用于渲染执行操作。所以在 after_action 中渲染为时已晚。
但您的例外只是因为您错过了 JSON 模板。我建议使用RABL(它为您的 JSON 响应提供了很大的灵活性,并且还有一个关于它的Railscast)。那么你的控制器可能看起来像:

class ClientsController < ApplicationController
  def index
    @clients = Client.all
  end
  def show
    @client = Client.find params[:id]
  end
end
Run Code Online (Sandbox Code Playgroud)

并且不要忘记创建您的 rabl 模板。
例如客户/index.rabl:

collection @clients, :object_root => false

attributes :id
node(:fancy_client_name) { |attribute| attribute.client_method_generating_a_fancy_name }
Run Code Online (Sandbox Code Playgroud)

但是,如果您仍然希望更具声明性,您可以利用ActionController::MimeResponds.respond_to像:

class ClientsController < ApplicationController
  respond_to :json, :html
  def index
    @clients = Client.all
    respond_with(@clients)
  end
  def show
    @client = Client.find params[:id]
    respond_with(@client)
  end
end
Run Code Online (Sandbox Code Playgroud)

顺便提一句。请注意,如果您将代码放在 after_action 中,这将延迟整个请求。