I want to extend core Array class with simple method:
class Array
def to_hash
result = Hash.new
self.each { |a| result[a] = '' }
result
end
end
I put array.rb into lib/core_ext and tried to require it in application.rb by
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]
But still get undefined method 'to_hash' for ["var1", "var2", "var3"]:Array if tried to use it in model method. Of course I rebooted the server after code changes.
Once way you can do this is by adding the following to one of the files in config/initializers
require 'core_ext/array`
All your autoload_paths config value does is make the paths available for when the classes/files are requested. In my app I might have some file structure as follows
- lib/
|
|- deefour.rb
|- deefour/
|
|- core_ext.rb
In my deefour.rb I have
require 'deefour/core_ext'
and inside config/initializers I have a deefour.rb file containing simply
require 'deefour'
The only way the autoload config value you set will cause Rails to look auto load lib/deefour/core_ext.rb is if you had some call to a class Deefour::CoreExt that existed in that file. This is why my require 'deefour' line in the initializer knows to autoload the lib/deefour.rb file.
The explicit require 'deefour/core_ext' in lib/deefour.rb serves the same purpose, since it too does not follow the standard class-name-to-directory mapping Ruby/Rails will expect.
Related
I have a rails application where I need to extend the Hash module to add a method -
class Hash
def delete_blank
delete_if{|k, v| v.nil? or (v.instance_of?(Hash) and v.delete_blank.empty?)}
end
end
I have created a filed named, hash_extensions.rb and placed this in my lib folder and of course configured autoloading paths with the following line in config/application.rb
config.autoload_paths += %W(#{config.root}/lib)
When I call the delete blank method on a Hash however, I get the below error -
undefined method `delete_blank' for #<Hash:0x000000081ceed8>\nDid you mean? delete_if
In addition to this, I have also tried placing require "hash_extensions" at the top of the file I am calling the delete_blank method from.
What am I doing wrong here or can I avoid extending Hash to have the same functionality?
You could resolve this issue in a few different ways:
Assuming that hash_extensions.rb resides under your_app/lib/extensions. (It's a good idea to store all extensions in a separate folder), require all extensions in config/application.rb as below:
Dir[File.join(Rails.root, "lib", "extensions", "*.rb")].each {|l| require l }
Move hash_extensions.rb under config/initializers and it should be automoagically loaded.
Create a folder say lib or extensions under your_app/app and move hash_extensions.rb to it and Rails would take care of loading it.
I have many service objects in my service folder. I'm using Rails 4:
->services
a_gen.rb
b_gen.rb
...
a_pro.rb
b_pro.rb
...
I would like my folder structure to be something like
->services
->gen
a_gen.rb
b_gen.rb
...
->pro
a_pro.rb
b_pro.rb
...
I tried just making the folders and putting the objects there, but Rails complains about not able to find it. Do I have to tell rails to look there?
Update:
I am getting this error:
NameError - uninitialized constant ExampleModelName::APro
Even with the path loaded. Once it is in the subfolder.. Rails is looking into the wrong place.
You can do that in two ways.
If you want rails to autoload them without you making any modifications to the config.autoload_paths, define your classes per the folder structure as follows:
module Gen
class ServiceA
end
end
If you don't want to make any changes to your class definition, then you could add those sub folders to the config.autoload_paths as follows in your config/application.rb
module YourApplication
class Application < Rails::Application
config.autoload_paths += [
"#{Rails.root}/app/services/gen",
"#{Rails.root}/app/services/prod"
]
end
end
for a recursive solution
# application.rb
config.autoload_paths += Dir["#{config.root}/app/services/**/"]
Yes, you do. In config/application.rb, you can add the subfolders to the config.autoload_paths collection.
I'd like to add a microapp for errors to be processed (file I placed inside the lib folder).
module MyApp
class Application < Rails::Application
config.autoload_paths += %W( #{config.root}/lib )
config.exceptions_app = FooApp.new(Rails.public_path)
end
end
But Rails raises an unitialized constant (NameError) during it's initialization. Recently I found a similar post and tried every solution from there, but got no result. What actually I've tried:
Name a class and a filename according to convention (even tried to simplify to a single word - class Foo, filename lib/foo.rb).
Use config.eager_load_paths += %W( #{config.root}/lib ) rather than config.autoload_paths, same effect. :(
Create an initializer file and load a class with require: require "#{Rails.root}/lib/foo"
It doesn't work - seems initializers are performed after the initial Rails configuration.
Move the file into app/misc but it doesn't help.
Put a class inside a module with the same name, rename a class while it's still in the module - no effect.
The only working solution I found - is to require a file right inside the Rails configuration block, but... it's a freaky solution. Probably there still exists an idiomatic one?
I'm a fairly new RoR dev and ran into a question about best practices for require ing files from lib in Rails 4.
Background:
As it stands, files in my app's lib don't get autoloaded. I want to require a helper class called rate_limiter that lives in a subdirectory of lib. I've also created a throttle module that handles routes related to rate limiting, and uses this rate_limiter class.
The throttle module is already required at the top of my application controller.
Question: to make sure rate_limiter gets loaded at start of app, what's better:
1) include an initializer rate_limiter.rb that simply says require rate_limiter to load class.
2) add require rate_limiter to the top of a different module throttle, which uses rate_limiter and which already gets required at the top of application controller.
Wondering about best practices for clarity and maintainability going forward.
Thanks for any suggestions!
I believe this would be a more Rails way to include desired files and folders.
# config/application.rb
module YourAppName
class Application < Rails::Application
# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/extras)
config.autoload_paths += Dir[Rails.root.join('lib')]
end
end
You probably could try the following scheme:
# config/application.rb:
# To make sure that your module namespace will be initialized without name collisions with files in your app directories
# require only root file and autoload other relative files in root file using features of ActiveSupport::Autoload
require_relative '../lib/my_module/my_module'
module AppName
class Application < Rails::Application
# Do not include all files in your lib. Require explicitly
# .
# ..
# - lib/my_module/my_module.rb - root file
# - lib/my_module/my_module - directory
config.autoload_paths += Dir[Rails.root.join('lib', 'my_module')]
end
end
Then in you module you can specify explicitly which files required and when
# lib/my_module/my_module.rb
module MyModule
extend ActiveSupport::Autoload
autoload :Configuration
autoload :SomeClass # at lib/my_module/my_module/some_class.rb
autoload :AnotherClass
eager_autoload do
autoload :Errors # at lib/my_module/my_module/errors.rb
autoload :BillError, 'my_module/errors'
end
end
It is worth to read an official guide to understand generic process of Rails constant lookup
To me, since this is going into your application controller which every request gets funneled through, I'd suggest adding this to your autoload paths.
In config/application.rb:
config.autoload_paths += %W(#{config.root}/lib/mymodule)
I am using config.autoload_paths in a way very similar to this related question to load classes from the lib directory in a Rails 3 project.
Specifically, I've added these lines to the config/application.rb file:
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]
However, this method is not working for me for existing classes. When I add a file like lib/extensions/string.rb:
class String
def foo
puts "foo"
end
end
I get an undefined method 'foo' for "":Stringerror. Through various searches I've got the sense that this problem has to do with the lazy loading of these files. I tried using config.eager_load_paths but was not able to get that to work.
I'm doing exactly what you are describing in my application, and the only difference is that I also have an initializer called extensions.rb with the following code:
Dir.glob('lib/extensions/*').each { |f| require f }