Help me geavanceerde foutafhandeling in mijn Ruby-toepassing te implementeren
description
Door geavanceerde foutafhandeling te implementeren, verbetert u de robuustheid en onderhoudbaarheid van uw toepassing. Dit leidt tot een betere gebruikerservaring en eenvoudiger debuggen.
prompt
try_prompt
Ik wil mijn Ruby-toepassing verbeteren door geavanceerde foutafhandelingsstrategieën te implementeren. Geef alstublieft begeleiding over hoe je aangepaste foutklassen maakt, uitzonderingshiërarchieën beheert en foutlogboeken implemen ... more
generate_helper
...
ai_answers
provider: openai
model: gpt-4.1-nano
Natuurlijk! Hier is een uitgebreide gids om je Ruby-toepassing voor een E-commerce platform te verbeteren met geavanceerde foutafhandelingsstrategieën:
1. Aangepaste Foutklassen Maken
---------------------------------
Gebruik aangepaste foutklassen om specifieke fouten te identificeren en te beheren. Dit helpt bij het onderscheiden van verschillende foutsoorten en het bieden van gerichte afhandeling.
```ruby
class ECommerceError < StandardError; end
class PaymentError < ECommerceError; end
class InventoryError < ECommerceError; end
class UserAuthenticationError < ECommerceError; end
```
2. Uitzonderingshiërarchie Beheren
-----------------------------------
Zorg voor een duidelijke hiërarchie zodat je generieke en specifieke fouten gemakkelijk kunt onderscheiden en afhandelen.
```ruby
begin
# code die kan falen
rescue PaymentError => e
# afhandeling voor betalingsfouten
rescue InventoryError => e
# afhandeling voor voorraadproblemen
rescue UserAuthenticationError => e
# afhandeling voor authenticatiefouten
rescue ECommerceError => e
# algemene afhandeling voor andere e-commerce fouten
rescue StandardError => e
# voor onvoorziene fouten
end
```
3. Foutlogboeken Implementeren
-----------------------------
Gebruik logging om fouten vast te leggen voor latere analyse. Ruby's standaard `Logger` klasse is hiervoor geschikt.
```ruby
require 'logger'
logger = Logger.new('fouten.log')
begin
# code die kan falen
rescue ECommerceError => e
logger.error("#{e.class}: #{e.message}\n#{e.backtrace.join("\n")}")
# eventueel doorgeven of gebruikersvriendelijk bericht tonen
end
```
4. Best Practices voor Gebruiksvriendelijke Foutmeldingen
----------------------------------------------------------
- Toon duidelijke en beknopte berichten aan de gebruiker.
- Vermijd technische details in de gebruikersinterface.
- Geef indien mogelijk hersteladviezen.
Voorbeeld:
```ruby
def handle_error(e)
case e
when PaymentError
puts "Er was een probleem met uw betaling. Controleer uw betaalgegevens en probeer het opnieuw."
when InventoryError
puts "Het artikel is niet op voorraad. U kunt een andere maat of kleur proberen of wachten op voorraad."
when UserAuthenticationError
puts "Authenticatie mislukt. Controleer uw inloggegevens of reset uw wachtwoord."
else
puts "Er is een onverwachte fout opgetreden. Neem contact op met de klantenservice."
end
end
```
5. Herstelprocedures en Foutafhandeling
---------------------------------------
- Probeer fouten te voorkomen door validatie en controle vooraf.
- Gebruik herhaalbare transacties waar mogelijk.
- Bied gebruikers de mogelijkheid om acties te annuleren of opnieuw te proberen.
- Log fouten systematisch voor analyse en verbetering.
6. Extra Tips voor Robuuste en Onderhoudbare Foutafhandeling
------------------------------------------------------------
- **Consistente structuur:** Gebruik consistente patronen voor foutafhandeling en logging.
- **Herbruikbare methoden:** Maak generieke foutafhandelingsmethoden.
- **Testen:** Schrijf unittests voor foutscenario's.
- **Monitoring:** Overweeg tools voor real-time foutbewaking, zoals Sentry.
- **Documentatie:** Documenteer de foutklassen en afhandelingsstrategie.
Door deze aanpak te volgen, wordt je Ruby-toepassing niet alleen robuuster, maar ook makkelijker te onderhouden en gebruiksvriendelijker voor je klanten.
provider: deepseek
model: deepseek-chat
Zeker, hier een uitgebreide handleiding voor geavanceerde foutafhandeling in je Ruby E-commerce platform:
## 1. Aangepaste Foutklassen Maken
```ruby
# Definieer een basis foutklasse voor je applicatie
module Ecommerce
class ApplicationError < StandardError
attr_reader :code, :details
def initialize(message = "Er is een fout opgetreden", code: :generic_error, details: {})
@code = code
@details = details
super(message)
end
def to_h
{
error: self.class.name.demodulize.underscore,
message: message,
code: code,
details: details,
timestamp: Time.current.iso8601
}
end
end
# Domeinspecifieke foutklassen
class PaymentError < ApplicationError; end
class InventoryError < ApplicationError; end
class UserError < ApplicationError; end
class ExternalServiceError < ApplicationError; end
# Gedetailleerde subklassen
class PaymentProcessingError < PaymentError
def initialize(payment_id, gateway_response)
super(
"Betaling verwerken mislukt voor payment #{payment_id}",
code: :payment_processing_failed,
details: { payment_id: payment_id, gateway_response: gateway_response }
)
end
end
class InsufficientStockError < InventoryError
def initialize(product_id, requested, available)
super(
"Onvoldoende voorraad voor product #{product_id}",
code: :insufficient_stock,
details: {
product_id: product_id,
requested: requested,
available: available
}
)
end
end
end
```
## 2. Uitzonderingshiërarchie Beheren
```ruby
# config/initializers/error_handling.rb
module ErrorHandling
extend ActiveSupport::Concern
included do
rescue_from Ecommerce::ApplicationError, with: :handle_application_error
rescue_from ActiveRecord::RecordNotFound, with: :handle_record_not_found
rescue_from ActiveRecord::RecordInvalid, with: :handle_record_invalid
rescue_from ActionController::ParameterMissing, with: :handle_parameter_missing
rescue_from Ecommerce::ExternalServiceError, with: :handle_external_service_error
# Veiligheid voor onverwachte fouten
rescue_from StandardError, with: :handle_unexpected_error
end
private
def handle_application_error(error)
log_error(error, level: :warn)
render_error(error.to_h, status: :unprocessable_entity)
end
def handle_record_not_found(error)
log_error(error, level: :warn)
render_error(
error: "record_not_found",
message: "De gevraagde resource kon niet worden gevonden",
code: :resource_not_found,
details: { model: error.model }
), status: :not_found
end
def handle_external_service_error(error)
log_error(error, level: :error)
render_error(
error: "external_service_unavailable",
message: "Een externe service is tijdelijk niet beschikbaar",
code: :service_unavailable,
details: { retry_after: "5 minutes" }
), status: :service_unavailable
end
def handle_unexpected_error(error)
log_error(error, level: :error)
# Stuur notificatie naar ontwikkelaars
ErrorNotifier.critical_error(error, context: error_context)
render_error(
error: "internal_server_error",
message: "Er is een onverwachte fout opgetreden",
code: :internal_error
), status: :internal_server_error
end
def render_error(error_payload, status:)
respond_to do |format|
format.json { render json: error_payload, status: status }
format.html { render "errors/#{status}", status: status, locals: { error: error_payload } }
end
end
end
```
## 3. Geavanceerd Foutlogboek Implementeren
```ruby
# app/services/error_logger.rb
class ErrorLogger
def self.log(error, context = {}, level = :error)
log_data = build_log_data(error, context, level)
# Schrijf naar verschillende outputs
Rails.logger.public_send(level, log_data.to_json)
# Structured logging voor monitoring systemen
log_to_structured_store(log_data)
# Metrics voor monitoring
increment_error_metrics(error, context)
end
private
def self.build_log_data(error, context, level)
{
timestamp: Time.current.iso8601,
level: level,
error_class: error.class.name,
message: error.message,
backtrace: sanitize_backtrace(error.backtrace),
context: context,
request_id: Current.request_id,
user_id: Current.user&.id,
environment: Rails.env
}
end
def self.sanitize_backtrace(backtrace)
backtrace&.first(10)&.map do |line|
# Verwijder gevoelige pad informatie
line.gsub(Rails.root.to_s, "[APP_ROOT]")
end
end
def self.log_to_structured_store(log_data)
# Integratie met ELK Stack, Splunk, etc.
StructuredLogger.info(log_data)
end
def self.increment_error_metrics(error, context)
tags = [
"error_class:#{error.class.name}",
"controller:#{context[:controller]}",
"action:#{context[:action]}"
]
StatsD.increment("application.errors", tags: tags)
end
end
# Gebruik in controllers
class ApplicationController < ActionController::Base
include ErrorHandling
private
def log_error(error, level: :error)
ErrorLogger.log(error, error_context, level)
end
def error_context
{
controller: controller_name,
action: action_name,
params: params.permit!.to_h.except('password', 'token'),
user_agent: request.user_agent,
ip: request.remote_ip
}
end
end
```
## 4. Gebruik in Domeinlogica
```ruby
# app/services/payment_processor.rb
class PaymentProcessor
def process(order, payment_method)
validate_order(order)
validate_payment_method(payment_method)
begin
gateway_response = PaymentGateway.charge(
amount: order.total_amount,
payment_method: payment_method
)
create_payment_record(order, gateway_response)
rescue PaymentGateway::ConnectionError => e
raise Ecommerce::ExternalServiceError.new(
"Betaling gateway is niet bereikbaar",
code: :payment_gateway_unavailable,
details: { original_error: e.message }
)
rescue PaymentGateway::DeclinedError => e
raise Ecommerce::PaymentProcessingError.new(
order.payment.id,
e.response
)
end
end
private
def validate_order(order)
if order.items.empty?
raise Ecommerce::UserError.new(
"Bestelling bevat geen producten",
code: :empty_order
)
end
end
end
# app/services/inventory_manager.rb
class InventoryManager
def reserve_stock(order)
order.items.each do |item|
available = item.product.available_quantity
if item.quantity > available
raise Ecommerce::InsufficientStockError.new(
item.product.id,
item.quantity,
available
)
end
end
# Reserveer voorraad
order.items.each(&:reserve_quantity!)
end
end
```
## 5. Best Practices en Gebruikersvriendelijke Meldingen
```ruby
# app/helpers/error_message_helper.rb
module ErrorMessageHelper
def user_friendly_error(error)
case error
when Ecommerce::InsufficientStockError
"Helaas, sommige producten zijn niet meer op voorraad. " \
"Pas uw winkelwagen aan en probeer het opnieuw."
when Ecommerce::PaymentProcessingError
"Uw betaling kon niet worden verwerkt. " \
"Controleer uw betalingsgegevens of probeer een andere methode."
when Ecommerce::ExternalServiceError
"De service is tijdelijk niet beschikbaar. " \
"Probeer het over enkele minuten opnieuw."
when ActiveRecord::RecordNotFound
"De pagina die u zoekt bestaat niet."
else
"Er is een onverwachte fout opgetreden. " \
"Onze technische staf is op de hoogte gesteld."
end
end
def error_suggestion(error)
case error.code
when :insufficient_stock
{
title: "Voorraad probleem",
actions: [
"Bekijk vergelijkbare producten",
"Pas hoeveelheid aan in winkelwagen"
],
retry: false
}
when :payment_processing_failed
{
title: "Betalingsprobleem",
actions: [
"Controleer creditcard gegevens",
"Probeer een andere betaalmethode",
"Neem contact op met uw bank"
],
retry: true
}
end
end
end
```
## 6. Monitoring en Herstelprocedures
```ruby
# config/initializers/monitoring.rb
class ErrorMonitor
def self.setup_alerts
# Configureer alerts voor kritieke fouten
ErrorAlert.new(
condition: ->(error) { error.is_a?(Ecommerce::ExternalServiceError) },
channel: :slack_critical,
message: "Externe service storing gedetecteerd"
)
ErrorAlert.new(
condition: ->(error) { error.is_a?(Ecommerce::PaymentError) },
channel: :slack_payments,
message: "Betaling fout opgetreden"
)
end
def self.track_recovery_actions(error, user_action)
RecoveryTracker.record(
error_id: error.id,
user_action: user_action,
success: true,
timestamp: Time.current
)
end
end
# Herstelstrategieën
class RetryStrategy
def self.with_retry(max_attempts: 3, base_delay: 1.0)
attempts = 0
begin
yield
rescue Ecommerce::ExternalServiceError => e
attempts += 1
if attempts < max_attempts
sleep(base_delay * (2 ** (attempts - 1))) # Exponential backoff
retry
else
raise e
end
end
end
end
```
## 7. Teststrategie
```ruby
# spec/services/error_handling_spec.rb
describe ErrorHandling do
let(:controller) { TestController.new }
describe "payment errors" do
it "handles insufficient stock gracefully" do
error = Ecommerce::InsufficientStockError.new(123, 5, 2)
expect {
controller.handle_application_error(error)
}.to log_message(/Onvoldoende voorraad/)
end
it "sends alert for critical external service errors" do
error = Ecommerce::ExternalServiceError.new("API timeout")
expect(ErrorNotifier).to receive(:critical_error)
controller.handle_external_service_error(error)
end
end
end
```
## Belangrijkste Best Practices:
1. **Gebruik domeinspecifieke foutklassen** voor betere organisatie
2. **Log structured data** voor eenvoudige analyse
3. **Scheid technische en gebruikersmeldingen**
4. **Implementeer retry mechanismen** voor tijdelijke fouten
5. **Monitor error rates** met metrics
6. **Bied bruikbare herstelsuggesties** aan gebruikers
7. **Test je error handling** grondig
Deze aanpak zorgt voor robuuste foutafhandeling die zowel ontwikkelaars als eindgebruikers ten goede komt in je E-commerce platform.

