2017-09-27 6 views
2

Je suis assez nouveau pour Rails et le développement de l'API back-end, alors excusez-moi si j'utilise un concept ou non. En ce moment, j'essaie de refactoriser une grande quantité de code de gestion des erreurs conditionnelles qui est réparti autour de la base de code et d'utiliser une liste explicite d'exceptions sauvées qui est mélangée dans le contrôleur API en l'incluant dans un module. Cela me permettra d'attacher des codes personnalisés, mais arbitraires, à chaque exception interceptée, à condition que nous utilisions les alternatives bang pour les méthodes d'enregistrement actives, et que le code de gestion des erreurs puisse vivre au même endroit. Jusqu'à présent, pour le module de gestion des erreurs, j'ai quelque chose comme ceci:Meilleure façon d'effectuer la gestion des erreurs à l'aide de modules dans Rails?

# app/lib/error/error_handling.rb 
module Error 
    module ErrorHandling 
    def self.included(klass) 
     klass.class_eval do 
     rescue_from ActiveRecord::RecordNotFound do |e| 
      respond(:record_not_found, 404, e.to_s) 
     end 
     rescue_from ActiveRecord::ActiveRecordError do |e| 
      respond(e.error, 422, e.to_s) 
     end 
     rescue_from ActiveController::ParameterMissing do |e| 
      response(:unprocessable_entitry, 422, e.to_s) 
     end 
     rescue_from ActiveModel::ValidationError do |e| 
      response(e.error, 422, e.to_s) 
     end 
     rescue_from CustomApiError do |e| 
      respond(e.error, e.status, e.message.to_s) 
     end 
     rescue_from CanCan::AccessDenied do 
      respond(:forbidden, 401, "current user isn't authorized for that") 
     end 
     rescue_from StandardError do |e| 
      respond(:standard_error, 500, e.to_s) 
     end 
     end 
    end 

    private 

    def respond(_error, _status, _message) 
     render "layouts/api/errors", status: _status 
    end 
    end 
end 

layouts/api/errors est une vue construite en utilisant JBuilder. Dans le ApiController nous avons:

# app/controllers/api/api_controller.rb 
module Api 
    class ApiController < ApplicationController 
    include Error::ErrorHandling 

    attr_reader :active_user 

    layout "api/application" 

    before_action :authenticate_by_token! 
    before_action :set_uuid_header 

    respond_to :json 
    protect_from_forgery with: :null_session 
    skip_before_action :verify_authenticity_token, if: :json_request? 

    private 

    ... 

end 

Malheureusement, cela ne semble pas fonctionner. L'exécution de tests montre que les méthodes privées ne sont pas du tout chargées et sont considérées comme non définies!

Pour être ici plus précis, sont les erreurs émises:

uninitialized constant Error::ErrorHandling::ActiveController 

et

undefined local variable or method `active_user' for Api::FooController 

active_user est un attribut qui est placé à l'intérieur d'une variable d'instance par une méthode appelée set_active_user. Ce qui n'est évidemment pas appelé.

Cependant, le module ErrorHandling est en cours d'évaluation. Comment cela pourrait-il être? Suis-je mal orthographié ou quelque chose?

Merci d'avoir lu.

+0

Pouvez-vous préciser quelles méthodes privées sont indéfinies? Le dans le contrôleur ou le dans le module? Si possible, un stacktrace pourrait aussi aider. – ulferts

+0

J'ai mis à jour le post. Comme mentionné, le module est en train d'être évalué mais j'appuie sur l'erreur '' constantial unitialized'' et la 'variable ou méthode locale indéfinie'' dans le contrôleur api, quand ils sont réellement définis. Peut-être l'erreur dans le module empêche-t-elle d'évaluer le code en dessous de 'include '? – dynsne

+0

Je ne pouvais fournir qu'un pointeur de base concernant le problème de la "méthode non définie". Si vous montrez le code qui déclenche l'erreur, je pourrais vous proposer une aide plus spécifique. – ulferts

Répondre

1

La réponse est divisée en deux parties car je crois qu'il y a deux problèmes distincts.

erreur unitinalized constant

L'erreur

uninitialized constant Error::ErrorHandling::ActiveController 

peut être fixée par la modification de ce

rescue_from ActiveController::ParameterMissing do |e| 
    response(:unprocessable_entitry, 422, e.to_s) 
end 

à ceci:

rescue_from ::ActiveController::ParameterMissing do |e| 
    response(:unprocessable_entitry, 422, e.to_s) 
end 

(ajout de :: devant la constante ActiveController)

La recherche constante dans ruby ​​prend en compte l'imbrication lexicale. Comme vous faites référence à la constante au sein

module Error 
    module ErrorHandling 
    ... 
    end 
end 

rubis va essayer de trouver la constante dans cet espace de noms est si l'avant constante non définie. Le préfixe :: indiquera à ruby ​​d'ignorer l'imbrication lors d'une recherche constante.

méthode locale non définie

L'erreur

undefined local variable or method `active_user' for Api::FooController 

est soulevé parce que certains code appelle la méthode instanceactive_user sur la classeApi::FooController où il n'est pas défini.

+0

Merci, fait des progrès. Je comprends plus sur Ruby maintenant! – dynsne

+0

Heureux d'être utile. Si vous voulez en savoir plus sur la recherche constante, vous pouvez jeter un oeil à cette page (https://cirw.in/blog/constant-lookup.html) – ulferts