5

Ich weiß, es gibt bereits einige Fragen und auch this is a open issue regarding AMS not handling namespaces too efficiently (die von dieser Versionierung Ansatz verwendet wird), aber ich wollte sicher sein, dass ich innerhalb der aktuellen Einschränkungen in der richtigen Spur bin.Richtiger Weg zur Implementierung von API Versioning mit Active_Model_serializers

Im Moment bin ich mit Rails 5 und AMS 0.10.1, so habe ich die folgenden:

# config/initializers/active_model_serializer.rb 
ActiveModelSerializers.config.serializer_lookup_enabled = false 

Standard-Serializer-Lookup zu deaktivieren (die ohnehin nicht funktioniert hat); und

# 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 

außer Kraft zu setzen, wie Serializer standardmäßig zu finden sind; meine Controller und Serializer sind wie folgt aus:

# 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 
    ... 

und

# app/serializers/api/v2/user_serializer.rb 
module Api::V2 
    class UserSerializer < ActiveModel::Serializer 
    ...  

nun Dinge wie ActiveModel::Serializer.serializer_for(object) werden nicht funktionieren, also musste ich auch die API-Version setzen mit example.metadata[:api_version] Affen meiner Anfrage Specs-Patch vor jedem Test und Erhöhung und Fehler, wenn das Beispiel es nicht eingestellt hat.

So:

  1. Gibt es eine bessere Art und Weise dokumentiert?
  2. Ist das annähernd korrekt?
  3. Werde ich bei diesem Ansatz ein Problem haben?
  4. Wie kann es verbessert werden?

Antwort

0

Da ich keinen besseren Weg gefunden, weder dokumentiert noch überall, so scheint es auch richtig zu sein, und ich habe keine Probleme nach einer Weile mit ihm konfrontiert, diese erscheinen ein guter Ansatz für die API-Versionierung sein.

Wie auch immer, ich rate zur Vorsicht mit diesem Ansatz, um das Verhalten älterer unterstützter Versionen für Ihre API nicht zu ändern. Testen Sie sorgfältig und benachrichtigen Sie Ihre Kunden, dass ältere Versionen nicht mehr unterstützt werden.

5

Ich denke, was Sie hier haben, ist in Ordnung. Ich benutze den gleichen Ansatz und es funktioniert gut für meine Anwendung. Ich nahm die ursprüngliche Idee hier von Ryan Bates, wo er tat, erklärt sehr ähnlichen Ansatz

http://railscasts.com/episodes/350-rest-api-versioning

Dies ist, was ich verschiedene Serializer für jede Ressource festlegen,:

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 

In meiner Implementierung Ich bin Verwenden von Serialisierern in API/Controllern/API/V3/Serialisierern. Sie sind also Versionierung Serializer Klassen und Controller-Klassen

Nicht sicher, dass Sie wirklich get_serializer haben müssen, da dies deutlicher ist aber keine große Sache

Wenn Sie eine Menge von api Endpunkten versuchen, sie in Ressourcen zu organisieren . In meiner config/routes.rb habe ich über 700 Ressourcen so ich teilte sie in separate Dateien config/api/v1/routes.rb ...

namespace :api, defaults: {format: 'json'} do 
    namespace :v1 
    resources :assets 
    end 
end 

Auch ist es praktisch, innen inflections.rb initializer zu tun

ActiveSupport::Inflector.inflections(:en) do |inflect| 
    inflect.acronym 'API' 
end 

Für mich würde ich sagen, dass das größte wichtige Problem ist, gute Testabdeckung zu haben. Ich bevorzuge spec und überprüfe auf korrekte Statuscodes 200, 201, ...usw. und ebenso die korrekte Sohnausgabe unter Verwendung von json_schema

Wenn Sie Auth tun müssen, dann würde ich vorschlagen, dass Sie Token basierte Auth und JWT - JSON Web Token verwenden. In meiner Implementierung verwende ich zwei Token. Ein Token zum Lesen und ein anderes Token beim POST und PATCH (nicht sicher, ob es nötig ist). so innerhalb API-Controller so etwas wie diese

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 
+0

Vielen Dank für Ihre Eingabe! Ich habe das getan, um die Dinge etwas zu DRY zu machen. 'get_serializer' wird immer von AMS aufgerufen und ich brauche nur' render json: @object, serializer: Namespaced :: Unconventional :: ObjectSerializer' zu verwenden, wenn es nicht der definierten Konvention folgt. –

Verwandte Themen