I'm trying to build my own Exception for tagged logging:
module Exceptions
class GeneralException < StandardError
LOGGER_NAME = 'Base'
def initialize(message)
#logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
#logger.tagged(get_logger_name) { #logger.error message }
#message = message
end
def get_logger_name
self.class::LOGGER_NAME
end
end
class InvalidDataException < GeneralException; end
class SecurityException < GeneralException
LOGGER_NAME = 'Security'
end
class ElasticSearchException < GeneralException
LOGGER_NAME = 'Elastic'
end
end
I'm expecting to be able to call this new exception with:
raise Exceptions::SecurityException "Something security related happened.
The problem is that when I call this I get:
NoMethodError: undefined method 'SecurityException' for Exceptions:Module
Any idea how to correctly raise this error?
Well, quite easy, you need to raise the instance of the error:
raise Exceptions::SecurityException.new "Something security related happend."
or
raise Exceptions::SecurityException, "Something security related happend."
Related
Im trying to raise some exceptions on my app, and found a bug that its driving me crazy.
Here is my client code:
class PaymentGateway::CreateSubscriptionService < PaymentGateway::Service
def run
begin
Subscription.transaction do
create_client_subscription
self.subscription = create_subscription
self.success = true
end
rescue PaymentGateway::CreateCustomerService,
PaymentGateway::CreatePlanService,
PaymentGateway::ClientError => e
raise PaymentGateway::CreateSubscriptionServiceError.new(
ERROR_MESSAGE,
exception_message: e.message)
end
end
My service error:
#services/payment_gateway/service_error.rb
class PaymentGateway::ServiceError < StandardError
attr_reader :exception_message
def initialize(message, exception_message: )
super(message)
#exception_message = exception_message
end
end
My client its:
class PaymentGateway::Client
attr_accessor :external_client
def initialize(external_client: PaymentGateway::StripeClient.new)
#external_client = external_client
end
def method_missing(*args, &block)
begin
external_client.send(*args, &block)
rescue => e
raise PaymentGateway::ClientError.new(e.message)
end
end
end
class PaymentGateway::CreateCustomerServiceError < PaymentGateway::ServiceError
end
When I run my code, this im getting this error:
ArgumentError in SubscriptionsController#create
missing keyword: exception_message
Extracted source (around line #4):
attr_reader :exception_message
def initialize(message, exception_message: )
What Im doing wrong here?
I am attempting to rescue RuntimeErrors from within my controller using rescue_from, log it as a HealthNotice, and then redirect the user with a flash message, but I'm finding that in certain circumstances, the rescue_from method is being run twice (I end up with 2 duplicate HealthNotices). If the exception is rasied from a function called in a method (such as the test method below), it only creates one, but if I raise the exception directly within the method (such as test2), the rescue function is running twice (although strangely I don't get a double render error -- ??)
class Portal::BluerimController < PortalController
rescue_from RuntimeError, with: :error_handler
def error_handler(e)
hn_long_message = "#{e.class}: #{e.message}\n#{e.backtrace.join("\n")}\n\nPARAMS:\n#{params}"
HealthNotice.create(name: "API Exception Handled", severity: "WARNING", short_message: e.message, long_message: hn_long_message)
flash[:notice] = e.message
redirect_to :action => :index and return
end
def test
Sotal.new.test # a method that raises a RuntimeError -- only 1 HealthNotice
end
def test2
raise "an error" # results in duplicate HealthNotice
end
end
Any suggestions on what I'm doing wrong? Thanks!
Here's the code, but a lot of it is irrelevant:
class BankAccount
def initialize(first_name, last_name)
#first_name = first_name
#last_name = last_name
#balance = 0
end
def public_deposit(amount)
#balance += amount
end
def protected_deposit(amount)
#balance += amount
end
protected :protected_deposit
def private_deposit(amount)
#balance += amount
end
private :private_deposit
def call_private_deposit(amount)
private_deposit(amount)
end
def call_protected_deposit(amount)
protected_deposit(amount)
end
#To show that you can't call a private method with a different instance of the same class.
def private_add_to_different_account(account, amount)
account.private_deposit(amount)
end
#To show that you can call a protected method with a different instance of the same class.
def protected_add_to_different_account(account, amount)
account.protected_deposit(amount)
end
end
I load this code into irb using "load './visibility.rb'" and then create an instance:
an_instance = BankAccount.new("Joe", "Bloggs")
Then, I generate a NoMethodError by typing:
an_instance.protected_deposit(1000)
This returns a NoMethodError. This is intentional. However, what I want to happen is for a custom message to be returned instead of the standard NoMethodError - something like "This is a custom error message."
I've been hacking away at this for hours and I'm at my wits end. I'm a relative beginner, so please bear this in mind.
Thanks.
You can rescue the error:
def call_protected_method
instance = BankAccount.new("Joe", "Bloggs")
instance.protected_deposit(1000)
rescue NoMethodError
puts "You called a protected method"
end
If you want to return a custom message, you can rescue the error and raise your own custom exception. Ruby lets you define your own exception classes. But I can't imagine why you would want to do this. You already have a built in exception to handle this.
I've got a custom Exception class declared like so:
class CustomError < StandardError
def initialize(message = nil)
#message = message
#type = "custom_error"
end
end
That is being handled in my Application controller like so:
rescue_from CustomError do |e|
render json: e.type
end
Now, when I raise the Exception using raise CustomError.new("Oops I did it again") I get a NoMethodError with undefined method `type'
What's going on? Why can't I just access type using e.type?
You can't call e.type because you haven't defined a type method.
You can use
attr_reader :type
To add such an accessor.
Turns out I was missing attr_reader. Here's what the final Exception class looks like:
class CustomError < StandardError
attr_reader :type
def initialize(message = nil)
#message = message
#type = "custom_error"
end
end
Reference: https://stackoverflow.com/a/4371458/2022751
I've created this code to show specific errors messages to user:
application_controller.rb
class ApplicationController < ActionController::Base
rescue_from Exception do |exception|
message = exception.message
message = "default error message" if exception.message.nil?
render :text => message
end
end
room_controller.rb
class RoomController < ApplicationController
def show
#room = Room.find(params[:room_id]) # Can throw 'ActiveRecord::RecordNotFound'
end
def business_method
# something
raise ValidationErros::BusinessException("You cant do this") if something #message "You cant do this" should be shown for user
#...
end
def business_method_2
Room.find(params[:room_id]).do_something
end
end
room.rb
class Room < ActiveRecord::Base
def do_something
#...
raise ValidationErrors::BusinessException("Invalid state for room") if something #message "Invalid state for room" should be shown for user
#...
end
end
app/models/erros/validation_errors.rb
module ValidationErrors
class BusinessException < RuntimeError
attr :message
def initialize(message = nil)
#message = message
end
end
end
example.js
$.ajax({
url: '/room/show/' + roomId,
success: function(data){
//... do something with data
},
error: function(data){
App.notifyError(data) //show dialog with message
}
});
But I can not use the class BusinessException. When BusinessException should be raised,
the message
uninitialized constant Room::ValidationErrors
is shown to user.
if I change this code:
raise ValidationErrors::BusinessException("Invalid state for room") if something
by this:
raise "Invalid state for room" if something
It works.
What change to this code works with BusinessException with messages. I need this
to create specifics rescue_from methods in ApplicationController.
Edit:
Thank you for comments!
My error is it doesn't know ValidationErrors Module. How to import this Module to my class?
I've tested add theses lines to lines:
require 'app/models/errors/validation_errors.rb'
require 'app/models/errors/validation_errors'
But then raise the error:
cannot load such file -- app/models/errors/validation_errors
Solution:
https://stackoverflow.com/a/3356843/740394
config.autoload_paths += %W(#{config.root}/app/models/errors)
raise ::ValidationErrors::BusinessException("Invalid state for room")