Unable To access custom exceptions defined in a module - ruby-on-rails

In My lib folder, I have a file image_helper_exception.rb. The path is lib/dibs_exception/image_exception/image_helper_exception.rb
In this file I have all my Image Exceptions defined
module DibsException
module ImageException
class ImageHelperException < Exception; end
class InvalidEntityException < Exception; end
class InvalidImageTypeException < Exception; end
class InvalidImageVersionException < Exception; end
class InvalidImageUrlException < Exception; end
class ImageNotFoundException < Exception; end
end
end
I raise applications elsewhere in my application when certain things are missing. The path to the file image_resize.rb where it is being used is helpers/image_resize.rb
The image_resize.rb looks something like this.
module Helpers
class ImageResize
require 'RMagick'
require 'aws/s3'
require 'rvg/rvg'
require 'mechanize'
include Magick
def initialize(abc)
if abc
raise DibsException::ImageException::InvalidEntityException.new("Entity is invalid.")
#The above line raises a error
#NameError: uninitialized constant DibsException::ImageException::InvalidEntityException
else
raise DibsException::ImageException::ImageHelperException.new("ImageHelperException.")
#The above line does not raise a error
end
end
end
I would like to add lib gets loaded in application.rb.
I am not able to understand why(Helpers::ImageResize.new(true)) is raising this error : NameError: uninitialized constant DibsException::ImageException::InvalidEntityException
But this works fine as expected : Helpers::ImageResize.new(false)
Why is only the first class loaded. Can some one help ? require does not work.

Ruby does not support function overloading.
second initialize overwrite the first one while parsing.
soo only the second function exists.
This should do the magic.
def initialize(xyz=nil)
raise DibsException::ImageException::InvalidEntityException.new("Entity is invalid.") if(xyz.blank?)
raise DibsException::ImageException::ImageHelperException.new("ImageHelperException.")
#This line DOES NOT raise error like above. It works fine.
end

Related

uninitialised constant after upgrade of Gemfile

I've just updated my Gemfile.
At the beginning I thought problem came from Zeitwerk (from 2.4.2 to 2.5.4) but I've downgraded it and I still have an issue on my spec. I've isolated that the problem does not come from RSpec and dependencies.
Actually, RSpec does not found a class which is defined within another file and does not match the file name/class name.
Important point: Filter::MyStandardError is found.
# app/services/filter/my_standard_error.rb
module Filter
class MyStandardError < StandardError; end
class MySpecificError < MyStandardError; end
# ...
end
# app/services/filter/my_tested_service.rb
module Filter
class MyTestedService
def initialize
raise ::Filter::MySpecificError
end
end
end
RSpec.describe Filter::MyTestedService do
subject { described_class.new }
it 'raises an error'
expect{subject}.to raise_error(::Filter::MySpecificError)
end
end
And I got the error:
NameError:
uninitialized constant Filter::MySpecificError
I got the Changelog but breaking changes are not used on my configuration.
Does anybody have an idea for this one?
You do not need to add app/services to the autoload paths, that is done automatically by Rails. I'd suggest to remove that configuration to keep things simple/idiomatic.
The implementation of app/services/filter.rb should not be needed. Your application is doing something that is not right, we just need to find it.
Could you please delete app/services/filter.rb, throw Rails.autoloaders.log! in config/application.rb, trigger the error, and share the traces?
After reading one-file-one-constant-at-the-same-top-level
I found this to fix my issue
# app/services/filter.rb
class Filter
class MyStandardError < StandardError; end
class MySpecificError < MyStandardError; end
end
# app/services/filter/my_tested_service.rb
class Filter
class MyTestedService
def initialize
raise ::Filter::MySpecificError
end
end
end
I still don't know why it was working before..
You cannot define two constants at the same level in the same file. It is one constant, one file. This has not changed in Zeitwerk upgrades. You need one file for the standard error, and another file for the specific error.

Cannot raise custom exception in Rails 5.2

I am developing a RoR application. I need to use a custom exception I implemented. It looks like this:
# app/exceptions/JobError.rb
module Exceptions
class JobError < StandardError
# ...
end
end
However, I got a uninitialized constant JobError when I raise the exception. I tried different namespaces but none of them work:
raise JobError.new()
raise Exceptions::JobError.new()
raise ::Exceptions::JobError.new()
Any idea?
My bad, I wrote the file name in CamelCase, not in snake_case...

Ruby - Check if controller defined

I am using Solidus with Ruby on Rails to create a webshop and I have multiple modules for that webshop.
So, I defined a me controller into an module called 'solidus_jwt_auth' with the followin code:
module Spree
module Api
class MeController < Spree::Api::BaseController
def index
...
end
def orders
...
end
def addresses
...
end
end
end
end
I want to extend this in another module called 'solidus_prescriptions' so I created a decorator for this with the following code me_decorator:
if defined? Spree::Api::MeController.class
Spree::Api::MeController.class_eval do
def prescriptions
...
end
def create_prescription
...
end
private
def prescription_params
params.require(:prescription).permit(
*Spree::CustomerPrescription.permitted_attributes
)
end
end
end
And for this I wrote unit tests in solidus_prescription module and integration tests in webshop. The unit tests are working fine, but the integration tests are giving the following error:
Error:
MeEndpointsTest#test_me/prescriptions_post_endpoint_throws_an_error_when_wrong_params:
AbstractController::ActionNotFound: The action 'create_prescription' could not be found for Spree::Api::MeController
test/integration/me_endpoints_test.rb:68:in `block in '
Which means that he can not find the MeController defined in another module. How can I make the check if the MeController is defined since the code bellow does not help me with anything:
if defined? Spree::Api::MeController.class
end
This worked in the end:
def class_defined?(klass)
Object.const_get(klass)
rescue
false
end
if class_defined? 'Spree::Api::MeController'
....
end
if defined? should do exactly what you want it to do in theory. The problem is you're checking if defined? Spree::Api::MeController.class. The #class of your class is Class. So what you're really getting is if defined? Class which will always be true!
This issue is most likely not that the conditional is failing but that it's never getting read. Rails lazy loads most of the code you write, meaning the file is not read until it's called somewhere in execution.
The decorator module should just contain the methods you want to add, without the conditionals or the use of class_eval. Then in the original class you can include it.
module Spree
module Api
class MeController < Spree::Api::BaseController
include MeDecorator
end
end
end
If for any reason you're not certain MeDecorator will be defined, don't use defined?, because defined? MeDecorator will not actually go looking for it if it's not defined and load the necessary file. It will return nil if the constant has no value. Just rescue a NameError
module Spree
module Api
class MeController < Spree::Api::BaseController
begin
include MeDecorator
rescue NameError => e
logger.error e
end
end
end
end

Rails - including module containing a class gives Uninitialized Constant error

My application has lib/project/errors which contains a bunch of Exception classes, one of which is ServiceException
module Project
module Errors
class ServiceException < Exception
def initialize(message = nil)
super message
end
end
end
end
I am trying to use this in my GameService:
module GameMan
class GameService
Blah blah
def validate(score)
raise Project::Errors::ServiceException.new('blah')
end
end
end
This works,
however I hate writing the full module path everywhere. Is there a way to avoid this?
I have tried
module GameMan
class GameService
include Project::Errors
Blah blah
def validate(score)
raise ServiceException.new('blah')
end
end
end
This gives
uninitialized constant ServiceException error.
I have
config.autoload_paths +=
%W(#{config.root}/lib #{config.root}/app/services)
already set inapplication.rb``
What am I doing wrong?
It is all about constants lookup.
ServiceException is defined in the scope of Project::Errors. When you reference ServiceException without prefixing Project::Errors it looks for the class defined in the outer scope, and failing, because there is none.
You should be using the full path.
include Project::Errors
Replace above line to following line
include Project::Errors::ServiceException

Uninitialized constant while trying to include helper module

The module that I am trying to include is located here:
test/unit/helpers/test_helpers.rb
Looks like:
module TestHelpers
end
I am trying to include it in:
test/unit/app/models/abc.rb
class Abc < ActiveSupport::TestCase
include TestHelpers
end
gives the following error:
Error executing test/unit/app/models/abc.rb uninitialized constant
Abc::TestHelpers
Any ideas why this might be happening?
To include a module into your class, you need to require that file.
require 'test_helpers'
Add this line at the top of your model class.

Resources