如何从Rails视图调用内部API(用于ReactJS预渲染目的)?
我已经有Rails API控制器返回JSON响应。 它被前端Javascript(以及移动应用程序)用来呈现值。
现在,我希望使用ReactJS预渲染这些值:
#app/controllers/api/v1/products_controller.rb
module API
module V1
class ProductsController < ApplicationController
def index
@products = Product.all #this could be acomplex multi-line statements.
#rendered in api/v1/products/index.json.jbuilder
end
end
end
end
#app/controllers/products_controller.rb
class ProductsController < ApplicationController
def index
#How to do this efficiently?
@products_json = #Call to internal /api/v1/products/index for prerender purpose.
@user_json = #Call to internal /api/v1/user/show for prerender purpose.
end
end
#app/views/products/index.html.erb
<%= react_component('ProductsList', @products_json, {prerender: true}) %>
<%= react_component('UserProfile', @user_json, {prerender: true}) %>
如何有效地调用internal /api/v1/products
和/api/v1/user
URL(例如,不向我自己的服务器发送HTTP GET请求)?
我同意您希望重新使用您的API代码来实现您的观点。 这将使应用程序更易于维护。
如果你稍微改变一下范围会怎么样? 不要调用控制器方法,而要将逻辑移到新的Ruby类中。
这个类的工作是将一个对象转换成一个JSON字符串,所以它被称为“序列化器”。 在我的应用程序中,我们有app/serializers/{model_name}/
用于存储不同的序列化程序类。
以下是一个示例序列化程序:
# app/serializers/product/api_serializer.rb
class Product::APISerializer
attr_reader :product, :current_user
def initialize(product, current_user)
@product = product
@current_user = current_user
end
# Return a hash representation for your object
def as_json(options={}) # Rails uses this API
{
name: product.name,
description: product.description,
price: localized_price,
categories: product.categories.map { |c| serialize_category(c) },
# ... all your JSON values
}
end
private
# For example, you can put logic in private methods of this class.
def localized_price
current_currency = current_user.currency
product.price.convert_to(current_currency)
end
def serialize_category(category)
{ name: category.name }
end
end
然后,使用这个序列化器来构建你的API响应:
class API::V1::ProductsController < ApplicationController
def index
products = Product.all
products_json = products.map do |product|
serializer = Product::APISerializer.new(product, current_user)
serializer.as_json
end
render json: products_json
end
end
然后,您可以在UI控制器中再次使用串行器:
class ProductsController < ApplicationController
def index
products = Product.all
@products_json = products.map do |product|
serializer = Product::APISerializer.new(product, current_user)
serializer.as_json
end
# render view ...
end
end
因为在这两种情况下您都使用了相同的序列化器,所以产品的JSON表示形式将是相同的!
这种方法有几个优点:
有些人为此使用ActiveModel串行器,但我没有。 一年前我尝试过AMS,但我不喜欢它,因为它覆盖了你应用程序中所有对象的as_json
,这导致了我的情况发生了重大变化!
尝试这个:
def index
@products = Product.all
@products_json render_to_string('/api/v1/products/index', formats: [:json])
# etc...
end
链接地址: http://www.djcxy.com/p/88137.html
上一篇: How to call internal API from Rails view (for ReactJS prerender purpose)?