使用active_model_serializers实现API版本控制的正确方法
我知道已经存在一些问题,而且这是一个关于AMS不能有效处理命名空间 (这种版本控制方法使用) 的开放性问题,但我想确保我在当前约束内处于正确的轨道。
现在我正在使用Rails 5和AMS 0.10.1,所以我做了以下事情:
# config/initializers/active_model_serializer.rb ActiveModelSerializers.config.serializer_lookup_enabled = false
禁用默认的序列化程序查找(无论如何都不起作用); 和
# app/controllers/application_controller.rb class ApplicationController < ActionController::API def get_serializer(resource, options = {}) unless options[:each_serializer] || options[:serializer] then serializer = (self.class.name.gsub("Controller","").singularize + "Serializer").constantize resource.respond_to?(:to_ary) ? options[:each_serializer] = serializer : options[:serializer] = serializer end super(resource, options) end end
覆盖默认情况下如何找到序列化程序; 我的控制器和序列化器是这样的:
# app/controllers/api/v2/api_controller.rb module Api::V2 class ApiController < ApplicationController ... # app/controllers/api/v2/users_controller.rb module Api::V2 class UsersController < ApiController ...
和
# app/serializers/api/v2/user_serializer.rb module Api::V2 class UserSerializer < ActiveModel::Serializer ...
现在,像ActiveModel::Serializer.serializer_for(object)
这样的东西将不起作用,所以我不得不使用example.metadata[:api_version]
来example.metadata[:api_version]
我的请求规范,以便在每次测试之前设置API版本并且如果例子没有设置它。
所以:
- 记录有更好的方法吗?
- 这是否接近正确?
- 用这种方法我是否会进一步面临问题?
- 怎么改进?
我想你在这里有什么好的。 我使用相同的方法,它适用于我的应用程序。 我从Ryan Bates那里挑选了最初的想法,他在那里解释了非常类似的方法
http://railscasts.com/episodes/350-rest-api-versioning
这是我用来为每个资源指定不同的序列化器:
module API module V3 class AssetController < API::V3::ApiController def index render json: assets, status: :ok, each_serializer: API::V3::Serializers::AssetSerializer end end end
在我的实现中,我在api / controllers / api / v3 / serializers中使用序列化器。 所以你是版本化序列化程序类和控制器类
不确定你真的需要get_serializer,因为这更明确但不是什么大不了的事
如果你有很多api端点尝试在资源中组织它们。 在我的config / routes.rb中,我有大约700个资源,所以我将它们分成单独的文件config / api / v1 / routes.rb ...
namespace :api, defaults: {format: 'json'} do namespace :v1 resources :assets end end
在inflections.rb初始化器内部也很方便
ActiveSupport::Inflector.inflections(:en) do |inflect| inflect.acronym 'API' end
对我来说,我认为最重要的问题是要有良好的测试覆盖率。 我更喜欢spec并检查正确的状态代码200,201,...等以及使用json_schema的正确子输出
如果您需要进行身份validation,那么我建议您使用基于令牌的身份validation和JWT - JSON Web令牌。 在我的实现中,我使用两个令牌。 在执行POST和PATCH时读取一个令牌和不同的令牌(不确定是否需要它)。 所以在API控制器里面是这样的
class ApiController < ActionController::Base skip_before_action :verify_authenticity_token, if: :json_request? before_action :authenticate protected def json_request? request.format.json? end if request.headers['X-Authorization'] token = request.headers['X-Authorization'] payload = JWT.decode(token, 'my_custom_key_to_check_if_key_has_been_tempered d_on_client_side')[0] end end
由于我没有找到更好的方法,既没有记录也没有任何地方,它似乎也是正确的,并且我在使用它一段时间后没有遇到问题,这似乎是API版本化的好方法。
无论如何,我建议谨慎使用此方法不要更改API支持的旧版本的行为。 仔细测试并通知您的客户旧版本的弃用和支持删除。
- Rails 3.2,保存序列化哈希不会保存number_with_delimiter()
- Rails ActiveModelSerializer将两个相同类型模型的列表组合成一个序列化响应,具有不同的名称
- 如何为活动模型序列化器关系选择所需的属性
- 使用active_model_serializers序列化权限(例如CanCan)
- 使用active_model_serializers序列化模型数组
- 活动模型序列化程序belongs_to
- 使用active-model-serializers错误地为act-as-taggable标签加载JSON
- 在Rails中使用ActiveModel :: Serializer – JSON数据在json和index响应之间有所不同
- 更改活动模型序列化器默认适配器