`const_missing': uninitialized constant (NameError) - ruby-on-rails

Every time I try to run any class from my rails 2.2 app's lib directory using "script/runner -e production ClassName.run" I get the following error:
/usr/lib/ruby/gems/1.8/gems/rails-2.2.2/lib/commands/runner.rb:47:
/usr/lib/ruby/gems/1.8/gems/activesupport-2.2.2/lib/active_support/dependencies.rb:89:in `const_missing': uninitialized constant ClassName (NameError)"
For some reason I don't get this error when I run it as test instead of production, and everything works fine.
O yeah run is a class method i.e. def self.run .... end
Any suggestions?

That error occurs when ruby can't find a Class or Module. I'd start out by:
Checking gem dependencies (are they same for all environments?)
Search your code for anything that defines ClassName, particularly Modules, Classes and plugins.
disable each of your plugins in dev, does any plugin suddenly cause that error?
if the code is in a lib add the lib require statement to your production.rb to force the lib to be loaded in production.
Hope that helps.
update Just to summarise the comments it was option 4.
Unless you only want to load the lib in production you should think about making sure all environments load the lib by doing one of the following:
Create a rails initializer (a .rb file under config/initializers) with the require in it
Add the path to the lib in config/environment.rb by enabling and modifying the config.load_paths variable.

I had multiple class definition(all STI classes) on the same file. and when I separated the definition into their respective files, It works

Related

Ruby on Rails: Difference between behaviour within the console / in a .rb file

I would like to use information stored within a the credentials.yml.enc file for a Rails 5.2 app. However, I am struggling to get a command which works perfectly within the console to behave in the same way when inserted into a .rb file.
In the Rails console (on my local development computer) Rails.application.credentials.username returns "my_username"
If I insert this line within a very simple db_backup.rb file as shown below, I get the error:
NameError: uninitialized constant #<Class:#<Backup::Config::DSL:0x00007fb0db941d10>>::Rails
db_backup.rb:
Model.new(:db_backup, 'Description for db_backup') do
##
# PostgreSQL [Database]
#
database PostgreSQL do |db|
db.username = Rails.application.credentials.username
end
end
Please could you explain why I get the different behaviour when using exactly the same line of code in the Rails console / within a .rb file?
The context in which the code is executed is not the same. One is the rails console and the other is the backup command
What happens when you load the Rails console
Launching the rails console means you launch all of the rails stack before executing your code against it. The Rack applications like Sinatra, Rails etc. use the config.ru file as a convention for which file should be run to boot. (You can explore the rabbit hole if you want to have a deep understanding of this)
It means that the vast majority of errors you can encounter when will occur during the console boot, preventing you from executing anything in the console (because boot failed). Instead it will print the stack trace errors for you to figure out what went wrong so you can correct and give it another try.
TL; DR Rails.application.credentials.username in console is executed after all of the Rails stack (models, dependencies, initializers) has loaded in a particular order
What happens when you run the backup command
The backup command is defined here in the bin repo of the backup repo
It goes like this
#!/usr/bin/env ruby
# encoding: utf-8
require File.expand_path("../../lib/backup", __FILE__)
Backup::CLI.start
If you open the required file lib/backup.rb and look around in the Gemfile, you won't fine a place where you have a dependency or a define for the Rails constant.
Thus when you run the backup command and execute your db_backup.rb, the constant Rails called here is ... not defined. Ruby being kind will try to find a nested version of this constant in the current scope which is the Model.new do; end block.
It is still not defined which ruby tells you about with NameError: uninitialized constant #<Class:#<Backup::Config::DSL:0x00007fb0db941d10>>::Rails.
#giglemad gives a great explanation of the issue of class resolution in the execution context (rails console vs. running of the backup ruby file).
To fix your error, just let the code know to use the top-level class lookup (::Rails):
Model.new(:db_backup, 'Description for db_backup') do
##
# PostgreSQL [Database]
#
database PostgreSQL do |db|
db.username = ::Rails.application.credentials.username
end
end
If you're still seeing the missing Rails constant, you'll need to put your script in either a rake task, or require your rails environment.
I ended up resolving this by simply adding the line below to the top of my db_backup.rb:
require './config/environment' # added to enable credentials to be read from Rails environment

Rails.root - uninitialized constant

I am writing a script located in /bin of a rails 5 project. Basically I am trying to iterate through various files and paths. Something to help me with this effort is Rails.root so I don't have to worry about relative paths etc
The problem is, when I am attempting to use Rails.root in my script, I am getting an error:
uninitialized constant Rails (NameError)
My script looks something like this
bin/my_class.rb
class MyClass
def initialize
...
end
def my_function
...
Rails.root.to_s
end
end
MyClass.new.my_function
Then i call my script like
ruby bin/template_check.rb foo=bar
And it's breaking on the line where I am calling Rails.root with the error message:
uninitialized constant Rails (NameError)
I have tried
moving Rails.root to a constant above the class (thought maybe it was a name conflict or something?). didn't work
changing the name to ::Rails.root.to_s. did not work either
Does anyone know why I cannot access Rails.root inside of my script?
edit
I was able to get this resolved by adding
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment'))
to the top of my script. This loads rails. as a default, the script is slower, and I'm not a huge fan of loading all of rails just to use Rails.root, but for now it works.
Other solutions like the answers below are to either use rails runner to run the script, or to wrap everything in a rake task.
You can try with
rails r bin/my_class.rb if your file is under bin
other wise you can use
rails r #{file_name}.rb specify the file name
Run with $ rails runner bin/my_class.rb. You can find out more about rails runner here

LoadError for custom Ruby module

I am new to Ruby. I am dealing with a codebase of the following nature.
I have a main/ directory containing my entire codebase, and inside it I have files like:
main/lib/foo/test1.rb and
main/app/bar/test2.rb
Inside main/app/bar/test2.rb there is the line: require 'test1'
However, if I am in the main/ directory and I run ruby main/app/bar/test2.rb I get the following error: require': cannot load such file -- access_control (LoadError)
Now, upon Googling, I think this has something to do with /config/application.rb and adding the line: config.autoload_paths += Dir["#{config.root}/lib", "#{config.root}/lib/**/". I do this, but it doesn't seem to make any difference.
Presumably my production environment knows where to look in the require 'test1.rb' statement, while my environment does not. How can I fix this?
Thanks!
It sounds like you have a Ruby on Rails application.
Given that, you probably don't want to run any contained script directly with ruby. If it's designed to be executed directly, try running it with rails runner path/to/file.rb (from inside the directory that contains app/, lib/, config/, etc).
If it's inside app/ or lib/, though, it's more likely intended to be loaded as a library from some other script elsewhere in the application... those would both be unusual places to keep a stand-alone executable.

ActiveSupport Autoloading not working outside of Rails

Given a file structure of
lib
app/
feature.rb
app.rb
And given the file app.rb that consists of:
require 'active_support'
require 'active_support/dependencies'
module App
extend ActiveSupport::Autoload
autoload :Feature, 'app/feature.rb'
def self.start
p Feature.new
end
end
It complains that LoadError: cannot load such file -- app/feature.rb
I've tried passing the absolute system path, no path, relative path to feature.rb from the module and the relative path from the execution point (one dir above lib).
This appears to be exactly the same thing that Rails is doing in the source.
Seems like this should be pretty intuitive, no?
The solution is the add the files to the Ruby interpreter load path like this: $LOAD_PATH.unshift(File.dirname(__FILE__)).
What that does is basically, allow Ruby to lookup those files. In Rails that is configured already when a new app is generated. When building a gem, in the spec you can add files or dirs to the load path. Outside of those, say a script in this instance, you must manually do that. autoload does not do that by default so you must specify (somewhat confusingly to me) the paths that Ruby can access.
I'm sure someone can clean up this explanation but that is how I understand it.
I don't believe Rails has lib on its autoload paths by default. We've got the following in config/application.rb:
config.eager_load_paths << Rails.root.join('lib')

Rails Jruby LoadError: no such file to load , when using Java Class in config.after_initialize

I am using jruby and I need to launch some java code after I initialized something. Below is the code that I need to launch in application.rb. I have the proper classes and libraries imported.
config.after_initialize do
ihp = IPHistoryProcessor.new("/home/ubuntu/jruby/logs/inputFiles/")
end
However I get the following error
LoadError: no such file to load -- /home/ubuntu/jruby/jruby_try_4/config/environment
require at org/jruby/RubyKernel.java:940
block in require at /home/ubuntu/.rvm/gems/jruby-9.0.0.0/gems/activesupport-4.1.12/lib/active_support/dependencies.rb:247
........
I can call the other built in ruby classes but not this java class that I made. I have no idea where the problem could begin. Most indications from other posts I see suggest it is a Passenger problem but I am using Puma for the server. Any help to fix this would be greatly appreciated. Thank you!
you need to tell JRuby where to look for your Java .class ... otherwise it does not know anything about Rails (there's no convention for auto-loading .class files from a location such as lib) ... try :
$CLASSPATH << 'lib/java' # set this early e.g. in boot.rb
or whereverer IPHistoryProcessor.class is (including the pkg dir structure)

Resources