I need to create a method that can be used in any situation (MVC, testing etc). Instead of stuffing it in environments.rb
id like to create a module and include it as a gem. What class do I need to extend in my gem in order to get Rails to recognize the methods in this module?
Update:
I'm looking for a solution that allows me to call my method without a module prefixed.
You need to "extend" the Kernel
module by including your methods into it with include
.
Generally a "global" method in Ruby means creating a method in Kernel
or Object
. The method is then available to all (most) classes because they inherit from Object
(which includes Kernel
). Your method can be called without a prefix from most places because the implicit self
in any given context will be an object that inherits from Object
and therefore contains the method you defined.
One way to define such a method is just to place its definition in a file outside of any class or module:
def my_method
# do fancy stuff
end
Of course, you have to make sure that file gets loaded (i.e. required) somewhere.
If you want your method to be organized within a module (which is a good idea), you need to include that module into Kernel
like this:
module MySpecialMethods
def my_method
# do fancy stuff
end
end
module Kernel
private
include MySpecialMethods # This is where the method gets added to Kernel
end
In Rails, I would put the MySpecialMethods
module in lib/
, add put the Kernel
part inside an initializer file like config/initializers/extend_kernel.rb
. You also need to help Rails "find" your module in lib/
by adding config.autoload_paths += %W(#{config.root}/lib)
to application.rb
It's worth nothing that there are very few situations where it's a good idea to extend Kernel
in this way. It's possible (likely?) that for your situation it is better to put your methods in a module and explicitly call them with the module name like MyModule.my_method
.
module MyModule
def self.my_method
# do fancy stuff here
end
end
There are many places you could place this code. In Rails, I'd recommend putting it in the lib/
folder as above and then making sure Rails can find it by adding config.autoload_paths += %W(#{config.root}/lib)
to application.rb
Creating a gem is beyond the scope of this question, but supposing you created a gem, typically the modules within that gem are available in your Rails app as long as you specify the gem in your Gemfile. This is because Rails apps by default call Bundler.require
. As long as the gem follows proper naming conventions, the main gem file is required automatically, and the main gem file requires any other necessary files.
If you want to extend Kernel
from a gem, just put the Kernel
extension code (from above) inside a file that is required (directly or indirectly) when your gem is required.
Rails initializers only run once when you boot the Rails server, so changes to them are not autoloaded like many other pieces of Rails in development.
If you're tweaking Rails' autoload_paths
, you might also want to tweak eager_load_paths
(see this blog post)
There are some objects in Ruby that do not inherit from Object
(e.g. BasicObject), so technically these "global" methods will not be available everywhere. That's not likely to cause problems for you.
Using Bundler.require
in a Rails app is perhaps controversial (see this blog post for more information on that)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With