Uninitialized constant error in Ruby class - ruby-on-rails

I have these two classes in RubyMine:
book.rb:
class Book
def initialize(name,author)
end
end
test.rb:
require 'book'
class teste
harry_potter = Book.new("Harry Potter", "JK")
end
When I run test.rb, I get this error:
C:/Users/DESKTOP/RubymineProjects/learning/test.rb:3:in `<class:Test>': uninitialized constant Test::Book (NameError)
from C:/Users/DESKTOP/RubymineProjects/learning/test.rb:1:in `<top (required)>'
from -e:1:in `load'
from -e:1:in `<main>'

You're getting the error because your require 'book' line is requiring some other book.rb from somewhere else, which doesn't define a Book class.
Ruby does not automatically include the current directory in the list of directories it will search for a require so you should explicitly prepend a ./ if you want to require a file in the current directory, ie.
require './book'

You have defined the initialize method but forgot to assign the values into instance variables and a typo in your code triggered the error, fixed it as:
book.rb
class Book
def initialize(name,author)
#name = name
#author = author
end
end
test.rb
require './book'
class Test
harry_potter = Book.new("Harry Potter", "JK")
end
So, which book or resource are you following? I think you should at least complete a book to get proper knowledge of Ruby and Object Oriented Programming. I would suggest you 'The Book of Ruby' to start with.

In a Rails app this error can also be caused by renaming the class without renaming the file to match, which was my issue when I found this error:
book.rb
class Book
def initialize(name, author)
end
end
book_test.rb
class BookTest
harry_potter = Book.new("Harry Potter", "JK")
end

Related

Ruby - NameError: uninitialized constant. Using class from a different module

I have these 2 files in a large system, both are located in PackA
people.rb
module People
class HobbyValueObject
end
end
job.rb
module People
class Job
end
class CityValueObject
end
end
I am trying to use CityValueObject in a different module like this,
Module is in PackB
work.rb
module Profile
class Work
....
def calculateTaxes
...
a = People::CityValueObject....
end
end
end
But it's giving me an error saying,
NameError: uninitialized constant People::CityValueObject
Did you mean? People::HobbyValueObject
Why is not being able to fine CityValueObject but can find HobbyValueObject just fine?
How do I make it find the object that I am intending to use?
I am not explicitly declaring any requires or includes
I was able to resolve this by adding require at the top while using full path file name.
require './packs/people/app/public/people/job'

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.

undefined method `new' for Test:Module

Hello I have a problem of conflict of the namespace. I have a model: Test and controller TestsController. server displays an error
undefined method `new' for Test:Module
I read this question rails models
added to the model Test in module UserTest
module UserTest
class Test < ActiveRecord::Base
....
end
end
and added to the controller
class TestsController < ApplicationController
def new
#test = UserTest::Test.new
#test.questions.build
#title = "New test"
end
...
end
server shows an error: uninitialized constant TestsController::UserTest
after reading more I realized that probably need to add require or include a controller. Only I do not understand how to do it. please tell me.
Never rename a model to the same name of the project. You will get a message like this:
undefined method `new' for Example:Module
The project module priority precedes on the call.
The convention in Rails is to convert your Class name in file and your module name in directory. So if you put your UserTest::Test class in test.rb file in your app/model directory, the autoload failed to get your class. Because search on app/model/user_test/test.rb file.
So you can "force" the require in your Controller by adding a require in top of your file. The require if you put your class in your test.rb is : require 'test.rb'
To know how define your require is to think the LOAD_PATH of your application add app/model directory. So all inside can be add directly by requiring the directory name and file name.

Problem modifying order model: uninitialized constant Order (NameError) - Spree 0.60.1

This is my first post on the list but before I ask for help I would to thank you all for the wonderful platform that you have created.
On a project I'm working on there is a need for a donation/donate functionality. I've followed the customization guide (http://spreecommerce.com/documentation/customization.html) to add new logic to the Order model.
I've added a new file called 'order_decorator.rb' inside 'app/models' and added:
Order.class_eval do
def my_method
# custom code
end
end
and I'm getting the following error:
order_decorator.rb:1:in `<top (required)>': uninitialized constant Order (NameError)
Anyone can add some light to my problem?
This was cross posted the Spree mailing list https://groups.google.com/d/topic/spree-user/mGcj4EpGuYo/discussion
Thanks Brian (https://groups.google.com/forum/#!topic/spree-user/mGcj4EpGuYo/discussion) for the fix. In spree the require statement needed to add all the files that end with '_decorator' need to go inside the 'self.activate' block:
module SpreeSite
class Engine < Rails::Engine
def self.activate
# Add your custom site logic here
Dir.glob(File.join(File.dirname(__FILE__), "../app/**/*_decorator*.rb")) do |c|
Rails.configuration.cache_classes ? require(c) : load(c)
end
AppConfiguration.class_eval do
#
end
end
def load_tasks
end
config.to_prepare &method(:activate).to_proc
end
end
That is breaking the Rails naming scheme. Either change the file name to order.rb or the code to OrderDecorator.class_eval do ...

Scoping require class loading, etc

I have a file booking.rb in my model directory. It contains the class definition
class Booking < ActiveRecord::Base
def self.setup_connection
wsdlurl = 'http://10.14.47.201:7001xxx/webservice/RetrieveBookingsByCCLV1_01.wsdl'
factory = SOAP::WSDLDriverFactory.new(wsdlurl)
##driver = factory.create_rpc_driver
##driver.return_response_as_xml = true
end
end
I attempt to invoke this method from my application.rb see code below.
module PNR2
class Application < Rails::Application
...
...
Booking.setup_connection
end
end
This fails with the following when I run the app...
C:/Users/sg0209028/RubymineProjects/PNR2/config/application.rb:49:in `<class:Application>': uninitialized constant PNR2::Application::Booking (NameError)
from C:/Users/sg0209028/RubymineProjects/PNR2/config/application.rb:18:in `<module:PNR2>'
from C:/Users/sg0209028/RubymineProjects/PNR2/config/application.rb:17:in `<top (required)>
The reason for the reference to line 49 is that I removed all the comments in this application.rb file to avoid taking space in this note. Line 49 in the original was the Booking.setup_connection line.
I am clearly not understanding how name scoping is working in Rails 3. Maybe I also don't understand when I should be invoking a class method to set up a constant in a Model object. It feels like that should be an application initialization task, but maybe that request should be somewhere else.
Ib case anyone is wondering, I have had this code and invocation of the appropriate web services working in a straingth Ruby (non rails) environment.
Below is the code for that
require 'soap/wsdlDriver'
require 'rexml/document'
require 'soap/rpc/driver'
WSDL_URL = "http://10.14.47.202:7001/xxx/webservice/RetrieveBookingsByCCLV1_01.wsdl"
factory = SOAP::WSDLDriverFactory.new(WSDL_URL)
driver = factory.create_rpc_driver
driver.return_response_as_xml = true
params = {"ccl" => "Booking[BookingName[BookingNameItem[TicketNumber > \"123456789\"]]]", "xmlFormat" => "DefaultBooking"}
response = driver.RetrieveBookingsByCCL(params)
doc = REXML::Document.new response
puts "Number of PNRs = " + REXML::XPath.first(doc, "//count").text
doc.elements.each ("//originCity") {|element| puts "Element = " + element.text}
Can anyone please give this newbie some pointers? Oh and yes I do realize that invoking some SOAP based services instead of back ending with a database is going to have some issues. That I am prepared for once I get the connection to work!
Thanks in advance
Chris
I just realized you were trying to use the Booking class in your application.rb file. I think you are going to have issues because at this point your application is not fully configured, but if you can get around those, to actually use the model, you'll have to require the file at the top of your application.rb file:
require 'rails/all'
require File.join(File.dirname(__FILE__), '../app/models/booking')
Booking is in the root-namespace, and you're calling the function (on your line 49) within the PNR2::Application namespace. You should change it to:
module PNR2
class Application < Rails::Application
...
...
::Booking.setup_connection
end
end

Resources