@account
最も簡単なのは、インスタンスを別の引数として渡すことです。エラーはどのモデル インスタンスにも発生します。
def create_customer(token,object,model_instance)
Stripe::Customer.create(description: 'Accommodation', email: object.email, card: token)
# return customer <- don't need this. whatever is last evaluated will be returned
rescue Stripe::CardError => e
model_instance.errors.add :base, e.message
false
end
サービス オブジェクトの代わりにコントローラーでエラー処理を行っていた場合rescue_from
、コントローラーや ApplicationController などで、アクション メソッドから発生する例外を処理できるものを利用できます。次のようにします。
rescue_from Stripe::CardError, with: :add_error_message_to_base
def add_error_message_to_base(e)
# this assumes that you set @instance in the controller's action method.
@instance.errors.add :base, e.message
respond_with @instance
end
またはより一般的に:
rescue_from Stripe::CardError, with: :add_error_message_to_base
def add_error_message_to_base(e)
model_class_name = self.class.name.chomp('Controller').split('::').last.singularize
instance_value = instance_variable_get("@#{model_class_name}")
instance_value.errors.add :base, e.message if instance_value
respond_with instance_value
end
rescue_from
または、懸念事項として、上記のいずれかを実行して、含まれているブロックにを入れることができます。
module StripeErrorHandling
extend ::ActiveSupport::Concern
included do
rescue_from Stripe::CardError, with: :add_error_message_to_base
end
def add_error_message_to_base(e)
# see comment above...
@instance.errors.add :base, e.message
respond_with @instance
end
end
José Valim がここでconfig.exceptions_app
説明しているように、ラック レベルでエラーを処理するために使用できます。
メソッドを継承するのではなく、個別のサービス クラスを使用するか、懸念/モジュールを使用することもできます。フックを介して行うこともできます。たとえば、次のようになります。
# not exactly what you were doing but just for example.
# could put in app/controller/concerns among other places.
module ActionsCreateStripeCustomer
extend ::ActiveSupport::Concern
included do
around_action :create_stripe_customer
end
def create_stripe_customer
# this (indirectly) calls the action method, and you will
# set @instance in your action method for this example.
yield
customer = Stripe::Customer.find_or_create_by(description: 'Accommodation', email: object.email, card: token)
# could set customer on @instance here and save if needed, etc.
rescue Stripe::CardError => e
if @instance
@instance.errors.add :base, e.message
respond_with @instance
else
logger.warn("Expected @instance to be set by #{self.class.name}##{params[:action]}")
raise e
end
end
end
次に、コントローラーで:
include ActionsCreateStripeCustomer
before_action
、などもafter_action
あります。また、モジュールをインクルードすることもできます。インスタンス メソッドが呼び出されると、インクルード クラス インスタンスが最初に呼び出され、次に最初にインクルードされたモジュールが呼び出され、次に 2 番目のモジュールがsuper if defined?(super)
呼び出されます。前のメソッドを呼び出す場合は、すべての引数とブロックを自動的に挿入します。
また、インスタンスではなくモデル クラス名を取得することであれば、それも簡単です。呼び出し元のクラスが AccountStripeCommunicator で@model_class
あるとすると、次の後に Account になります。
qualified_class_name = self.class.name.chomp('StripeCommunictor')
@model_class = qualified_class_name.split('::').last.singularize.constantize
あらゆる種類の可能性。