Reputation: 1342
I have a rails setup that is something like this.
app/service/TestService.rb
class TestService
def self.doSomething
return 'Hello World!'
end
end
I am using this file in the controller.
require 'TestService'
class IndexController < ApplicationController
def index
@message = TestService.doSomething
end
end
I also added this in application.rb inside the config folder, so that rails autoload classes in service folder.
config.autoload_paths += %W(#{config.root}/app/service)
But the application doesn't seem to pick up updates to TestService class. How can I fix this, so that changes in TestService class show up without restarting the server.
Upvotes: 3
Views: 1631
Reputation: 65435
Do not use require
when attempting to load a file containing a reloadable constant.
Normally, you will not need to do anything special to be able to use that constant. You will just use the constant directly, without having to use require
or anything else.
But if you want to be squeaky clean with your code, ActiveSupport
provides you with a different method that you can use to load these files: require_dependency
.
require_dependency 'test_service'
class IndexController < ApplicationController
...
end
Although it's confusing that you would attempt to be squeaky clean and explicitly load the file containing TestService
but not explicitly load the file containing ApplicationController
....
You do not need to change the autoload_paths
config.
In order to let Rails find and load your constants (classes and modules), you need to do the following:
You must be sure that every reloadable constant in your application is in a file with the right filename. The file must always be in some subdirectory of app
, such as app/models
or app/services
or any other subdirectory. If the constant is named TestService
, the filename must end with test_service.rb
.
The algorithm is: "TestService".underscore + ".rb" #=> "test_service.rb"
.
filename_glob = "app/*/" + the_constant.to_s.underscore + ".rb"
So if the constant is TestService
, then the glob is app/*/test_service.rb
. So sticking the constant in app/services/test_service.rb
will work, as will app/models/test_service.rb
, although the latter is bad form. If the constant were SomeModule::SomeOtherModule::SomeClass
, you would need to put the file in app/*/some_module/some_other_module/some_class.rb
.
Upvotes: 2
Reputation: 62638
You say that your file is in app/server
, but you are autoloading app/service
. Which is correct?
Rename your file to app/service/test_service.rb
and the autoloader should work. Rails looks for snake_cased filenames in your autoload paths. You don't need the manual require
either, once you have the autoloading behavior correct.
Upvotes: 0