我知道在使用视图模板(html,rabl)时,我的控制器操作中不需要显式渲染调用,因为默认情况下,Rails会使用与控制器操作名称对应的名称呈现模板。我喜欢这个概念(不关心我的控制器代码中的渲染),因此想知道在使用ActiveModel :: Serializers时这是否可行?
示例,这是来自生成的控制器(Rails 4.1.0)的代码:
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]
#other actions
# GET /products/1
# GET /products/1.json
def show
end
end
这是序列化器:
class ProductSerializer < ActiveModel::Serializer
attributes :id, :name, :description, :url, :quantity, :price
end
点击/products/1.json,我希望会发生两件事:
然而,这不会发生,整个序列化器被忽略。但是,如果我将Show方法修改为以下内容:
# GET /products/1
# GET /products/1.json
def show
@product = Product.find(params[:id])
respond_to do |format|
format.html
format.json { render json: @product }
end
end
现在一切都很好,但我已经失去了before_action过滤器的好处(在我看来,我有一些冗余代码)。
这应该怎么做?
答案 0 :(得分:0)
&#39;冗余代码&#39;我们在第二个看到的只是这一行:
@product = Product.find(params[:id])
我相信这与你之前的行动是一样的逻辑。你不需要这条线,只需删除它。现在删除了重复。
剩下的部分。动作需要知道要渲染的内容。默认情况下,如果操作为空或不存在,则会查找并呈现相应的&#39; action_name&#39; .html.erb(以及respond_to
指定的其他格式)。
这就是Rails 4生成器创建的原因:它创建了呈现的show.html.erb
和show.json.jbuilder
。
使用ActiveModel::Serializer
,您没有模板。如果将操作留空,则不知道要渲染的内容。因此,您需要通过以下任一方式告诉它将@product
呈现为json:
render json: @product
或
respond_with @product
答案 1 :(得分:0)
如果没有明确的render
或respond_with
或respond_to
,Rails会查找匹配的模板。如果该模板不存在,Rails会抛出错误。
但是,您可以创建自己的解析器来绕过它。例如,假设您创建了app\models\serialize_resolver.rb
并将其放入其中:
class SerializeResolver < ActionView::Resolver
protected
def find_templates(name, prefix, partial, details)
if details[:formats].to_a.include?(:json) && prefix !~ /layout/
instance = prefix.to_s.singularize
source = "<%= @#{instance}.active_model_serializer.new(@#{instance}).to_json.html_safe %>"
identifier = "SerializeResolver - #{prefix} - #{name}"
handler = ActionView::Template.registered_template_handler(:erb)
details = {
format: Mime[:json],
updated_at: Date.today,
virtual_path: "/#{normalize_path(name, prefix)}"
}
[ActionView::Template.new(source, identifier, handler, details)]
else
[]
end
end
def normalize_path(name, prefix)
prefix.present? ? "#{prefix}/#{name}" : name
end
end
然后,在您的应用程序控制器(或单个控制器)中:
append_view_path ::SerializeResolver.new
有了这个,你应该能够做你想做的事。如果是json请求,它将创建一个包含正确内容的erb模板并将其返回。
限制:
json
响应。/posts
转换为@post
。)注意: