LoadError for custom Ruby module - ruby-on-rails

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.

Related

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')

What is the difference in running a rails unit test with -Ilib and -Itest?

I use both the following commands to run tests in my application:
ruby -Ilib test/unit/account_test.rb
ruby -Itest test/unit/account_test.rb
Both works fine. But, what is the difference. What actually the flag -I means?
From the Ruby manual page (man ruby):
-I directory Used to tell Ruby where to load the library scripts. Direcā€
tory path will be added to the load-path variable ($:).
The variable $: (aliased as $LOAD_PATH) is the array of directories where Ruby looks for files to load when you call require. In your case both commands works well because, I guess, you don't require anything inside lib or test directories from your test code.

Why does require load differently in production (Heroku) and development environments for Rails?

I am trying to require a file located in lib (in my Rails app).
In development, this line works without any problems.
require "km"
However, in Heroku, I get a "no such file to load" error.
Via the Heroku console, I've tried a number of variants in terms of specifying paths to the file. For example:
require "lib/km"
require "./lib/km.rb"
And so forth. This is based on answers from these questions, which suggest that the issue is specifying the path to the file.
Rails, Heroku does not load my lib
Heroku console not loading file in /lib?
I've also tried adding this autoload line suggested here, which doesn't seem to solve it.
config.autoload_paths += Dir["#{config.root}/lib/**/"]
http://www.williambharding.com/blog/technology/rails-3-autoload-modules-and-classes-in-production/
How do I tell Rails to find the lib file? And why is there a difference in behaviour for require in development vs production?
UPDATE:
The issue turns out to be related to git. The original filename was "KM.rb", which was later changed to "km.rb". However, git didn't pick up the case change, so the change never got pushed onto the Heroku environment.
A key step was using the Ruby Dir commands in Heroku console to investigate the file structure and confirm the filename within the environment on Heroku.
I was getting the "no such file to load" error and found that I had the wrong case on a require statement
require_relative './place/Places.rb'
when the actual filename was places.rb
Worked fine on Windows since it's case insensitive

Where to put Ruby scripts for script/runner on a Rails project?

I have seen examples where it is put in the lib folder, and another example in the app folder. Is there standard place where it should be put for Rails 2.3.8 and Rails 3 convention?
Scripts have to go into the /scripts folder. Of course there's almost always the confusion as to how to differentiate a script from a regular ruby file that is 'required' by a controller/model. If your script is required to start/sustain your application, then yes its a script. Or else if its a ruby file that is need at times or just for some cases wherein it complements the model/controller, you're better off putting it in the /lib folder.
I usually don't have runner scripts, but instead directly call some method that exists either on a model or in something in lib. For example, my Rails cronjobs typically look like this:
/path_to_app/scripts/runner -e production "SomeModule.perform_task"
I think this is cleaner.
I wrote a script on one one occasion, though, and in that case, I just put it in the lib directory:
/path_to_app/scripts/runner -e production /path_to_app/lib/perform_task.rb"

`const_missing': uninitialized constant (NameError)

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

Resources