Rails /Lib Modules And

Rails /lib modules and

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 required. If a file is required, Ruby looks through the entire list of paths in your load paths, and find the first case where the file you required 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).

How to properly load lib modules and classes in Rails 5 app

No, you shouldn't resort to using require (if you want to follow Rails conventions). Rails autoloading is based on paths and namespacing, as those two things have to match up. Besides the initial problem with namespacing that was fixed, the way you modify the autoload paths is incorrect. It should be done this way:

config.autoload_paths << "#{Rails.root}/lib"

This is if you want to leave lib/ at the root of your project. As mentioned in the comments, you could move it into your app/ directory.

Accessing modules in Rails lib folder

The simplest way to solve this is by placing your files in app/lib/account_management/email_token.rb. Rails already autoloads any subdirectory of the app folder*.

/lib has not been on the autoload paths since Rails 3. If you want to add it to the autoload paths you need to add /lib not /lib/account_management to the autoload/eager loading paths. In Zeitwerk terms this adds a root where Zeitwerk will index and resolve constants from.

config.autoload_paths += config.root.join('lib')
config.eager_load_paths += config.root.join('lib')

Note that eager_load_paths is only used when eager loading is turned on. Its turned off by default in development to enable code reloading.

/lib is added to $LOAD_PATHso you can also manually require the file with:

require 'account_management/email_token'

See:

  • Autoloading and Reloading Constants (Zeitwerk Mode)
  • Rails #37835

can't include modules loaded from lib in Rails 5

What you have is a simple misunderstanding of how rails resolves module names. Adding a directory to the autoload path does not cause rails to look recursively through its subdirectories.

In order for rails to properly load the module it would have to be declared as:

# lib/surveyable/surveyable.rb
module Surveyable::Surveyable
extend ActiveSupport::Concern
end

This is because the autoloader deduces the file path based on module nesting.

Or you can move the file to lib/surveyable.rb.

But since what you are writing seems to be a model concern I would place it in app/models/concerns which is already added to the load path.

Why do Rails /lib modules prevent gem modules from loading?

If you open up a console (with script/console) and examine the $LOAD_PATH variable, you should see something resembling this:

>> $LOAD_PATH
[
# some entries...
[12] "/your/rails/root/app",
[13] "/your/rails/root/app/controllers",
[14] "/your/rails/root/app/models",
[15] "/your/rails/root/app/helpers",
[16] "/your/rails/root/lib",
# more entries...
[27] "/your/ruby/path/lib/ruby/1.8/gems/foo_blaster-0.0.1/lib"
# rest of entries
]

When you require 'foo_blaster' (which may be done implicitly by Rails, Bundler, or perhaps some other means), Ruby searches the locations in $LOAD_PATH sequentially until it finds the file foo_blaster.rb, loads that file, and stops. In your case, it finds the file in your application's /lib directory. The file from your gem will never be loaded.

If you want to load both files, all you have to do is give them different names and make sure to require them both. For instance, you might rename the file in your application to foo_blaster_extensions.rb, then add an initializer to load it:

# config/initializers/extend_foo_blaster.rb
require 'foo_blaster_extensions'

Accessing module in lib directory (Ruby on rails)

In your console/controller:

include Search
zip_code_perimeter_search(zip, radius)

In case it doesn't auto-load in Rails 3, in your config/application.rb file, you can do this:

# Custom directories with classes and modules you want to be autoloadable.
config.autoload_paths += Dir["#{config.root}/lib/**/"]

How to use module in lib from controller with Rails?

I know the reason. It is necessary to add require in the first line of the controller:

require 'a/b/c'

Rails: Loading custom class from lib folder in controller

Ruby on Rails expects certain naming conventions to support autoloading.

Rails can autoload a file located at lib/services/my_service.rb if the model/class structure was Services::MyService.

Change your lib/services/my_service.rb to:

module Services
class MyService
# ...
end
end

And use that class like this in your controller:

service = Services::MyService.new

Please note that depending on your Ruby on Rails version you might need to add the lib folder to the list of folders which are queried when looking for a file to autoload:

# add this line to your config/application.rb:
config.autoload_paths << "#{Rails.root}/lib"

Read more about autoloading in the Rails Guides.

Rails lib/module with 'class Class' and custom attr_accessor

Try to define your method attr_accessor_with_onchange_callback directly in ModelHelpers, without class Class. And use extend keyword instead include inside class defenition. Like this:

module ModelHelpers
def attr_accessor_with_onchange_callback(*args, &block)
...

require 'model_helpers'
class MyCLass < ActiveRecord::Base
extend ModelHelpers

Here is my example:

module ModelHelpers
def my_method
puts 'ModelHelpers::my_method called.'
puts "self is #{self}"
end
end

class MyCLass
extend ModelHelpers
my_method
end

And output is:

> ruby custom_method_inside_class.rb
ModelHelpers::my_method called.
self is MyCLass


Related Topics



Leave a reply



Submit