In my Rails 7 app I'm using several 3rd parties API to provide fetch data. Each time I'm receiving an error I've to rescue
with nil
to still be able to display redirect user to desired page, e.g.:
# lib/custom_api.rb
module CustomApi
extend self
def fetch_transactions(user_id)
client.transactions.list(user_id:)
# rescue from custom error
rescue Errors::NotFoundError
nil
end
end
# transactions_controller.rb
class TransactionsController < ApplicationController
def index
transaction_list = CustomApi.fetch_transactions(current_user.id)
if transaction_list
@transactions = transaction_list
else
@transactions = transaction_list
flash[:alert] = 'No transactions'
end
end
end
# views/transactions/index.html.erb
<%= turbo_frame_tag 'transactions' do %>
<%= render partial: 'table_headers' %>
<%= render Transactions::TableComponent.new(records: @transactions) if @transactions %>
<% end %>
Everything works well but I've got 50 endpoints where I need to include rescue Errors::NotFoundError
and I don't think it's super sufficient to to repeat this line 50 times. Is there a way to avoid that?
CodePudding user response:
In general, using Rescuable
is the Rails' way for rescuing from exception in a centralized manner.
Add this to your ApplicationController
:
rescue_from Errors::NotFoundError, with: :handle_not_found_error_from_external_api
private
def handle_not_found_error_from_external_api
# handle the error in a generalized way, for example, by returning a response
# that renders a modal or a toast.
end
And remove these lines from your CustomApi
:
# rescue from custom error
rescue Errors::NotFoundError
nil
CodePudding user response:
You can use class inheritance to accomplish what you need:
class CustomApi
def self.fetch(args)
self.new.do_fetch(args)
# rescue from custom error
rescue Errors::NotFoundError
nil
end
end
and then for the transaction API:
class CustomTransactionApi < CustomApi
def do_fetch(args)
client.transactions.list(args[:user_id])
end
end
For instance, if you have another API for messages:
class CustomMessageApi < CustomApi
def do_fetch(args)
client.messages.list(args[:user_id])
end
end
And then your controller will be:
class TransactionsController < ApplicationController
def index
@transaction_list = CustomTransactionApi.fetch({user_id: current_user.id})
flash[:alert] = 'No transactions' if @transaction_list.blank?
end
end