我已经有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表示将是相同的!
这种方法有一些优点:
>因为你的序列化程序是一个普通的Ruby类,所以很容易编写和编写.测试
>在控制器之间共享JSON逻辑很容易
>它非常易于扩展:当您需要JSON用于其他目的时,只需添加一个新的序列化程序并使用它.
有些人为此使用ActiveModel Serializers,但我没有.我一年前尝试过AMS而且我不喜欢它,因为它会覆盖你应用中所有对象的as_json,这会导致我的情况发生重大变化!