Rails /lib modules and
Solution 1
There are two ways that files get loaded in Rails:
- It is registered in the autoload process, and you reference a constant that corresponds to the file name. For instance, if you have
app/controllers/pages_controller.rb
and reference PagesController,app/controllers/pages_controller.rb
will automatically be loaded. This happens for a preset list of directories in the load path. This is a feature of Rails, and is not part of the normal Ruby load process. - Files are explicitly
require
d. If a file isrequire
d, Ruby looks through the entire list of paths in your load paths, and find the first case where the file yourequire
d is in the load path. You can see the entire load path by inspecting $LOAD_PATH (an alias for $:).
Since lib
is in your load path, you have two options: either name your files with the same names as the constants, so Rails will automatically pick them up when you reference the constant in question, or explicitly require the module.
I also notice that you might be confused about another thing. ApplicationController is not the root object in the system. Observe:
module MyModule
def im_awesome
puts "#{self} is so awesome"
end
end
class ApplicationController < ActionController::Base
include MyModule
end
class AnotherClass
end
AnotherClass.new.im_awesome
# NoMethodError: undefined method `im_awesome' for #<AnotherClass:0x101208ad0>
You will need to include the module into whatever class you want to use it in.
class AnotherClass
include MyModule
end
AnotherClass.new.im_awesome
# AnotherClass is so awesome
Of course, in order to be able to include the module in the first place, you'll need to have it available (using either of the techniques above).
Solution 2
In Rails 3 /lib modules are not loaded automatically.
This is because the line:
# config.autoload_paths += %W(#{config.root}/extras)
inside config/application.rb is commented.
You can try to uncomment this line or, (it worked even better for me), leave this commented (for future reference) and add this two lines:
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]
Solution 3
What worked for me, besides uncommenting config.autoload_paths (I’m on Rails 3.1.3), was to create a initializer like this:
#config/initializers/myapp_init.rb
require 'my_module'
include MyModule
This way I can call mymodule methods from anywhere and as class methods Model.mymodule_method
or as instance methods mymodel.mymodule_method
Maybe some expert may explain the implications of this. By now, use it at your own risk.
Edit: Afterwards, I think a better approuch would be:
create a initializer like this:
#config/initializers/myapp_init.rb
require ‘my_module’
Include the module where needed, like this:
1) if you want to use it as "Class Methods" use "extend":
class Myclass < ActiveRecord::Base
extend MyModule
def self.method1
Myclass.my_module_method
end
end
2) if you want to use it as "Instance Methods" include it inside Class definition:
class Myclass < ActiveRecord::Base
include MyModule
def method1
self.my_module_method
end
end
3) remember that include MyModule
refers to a file my_module.rb
in your load path that must be required first
Solution 4
To use the module lib/my_module.rb
in your models and controllers:
In config/application.rb
:
config.watchable_dirs['lib'] = [:rb]
In your model (similar idea for your controller):
require_dependency 'my_module'
class MyModel < ActiveRecord::Base
include MyModule
MyModule.some_method
end
This method is described in more detail at http://hakunin.com/rails3-load-paths
Related videos on Youtube
Mantas
iOS native apps and Ruby on Rails freelancer available for hiring!
Updated on December 13, 2020Comments
-
Mantas over 3 years
I am writing a custom wrapper for
open_flash_chart
plugin. It's placed in/lib
and load it as a module inApplicationController
.However, I have some Class hierarchy or smth problem.
From any controller I can access
open_flash_chart
functions asOpenFlashChart
,Line
etcHowever, in a class in a
/lib
module, it doesnt work!Any ideas?
-
Mike over 13 yearsJust wanted to add : If one of your module in /lib (or in one of the autoload directories) is already define ; exemple you overload ActiveRecord or String, you'll have to explicitly require it or it won't be loaded
-
mkirk about 13 yearsstrangely, I'm getting: uninitialized constant GaClient (NameError), unless I require 'ga_client' beforehand (the class is defined in lib/ga_client.rb). Is there documentation for the autoload naming scheme?
-
jibiel over 12 yearsThis will duplicate
../lib
path inApplicationName::Application.config.autoload_paths
array. -
ylluminate about 12 years@jibiel so what's the resolution here?
-
Mindaugas MG almost 12 yearswhy did the latter option work better for you? Also, why was the default changed...there must be a reason despite lots of people finding work arounds.
-
S.M.Mousavi over 11 yearsI have created my module on
lib
folder, therefore i have addedconfig.autoload_paths += %W(#{config.root}/lib)
onconfig/application.rb
file. After that i followed your suggestion to addingconfig/initializers/myapp_init.rb
file and it's contents. Everything is good. Thanks a lot :)