3coins
3coins

Reputation: 1342

Rails Load Class Changes without restarting the server

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

Answers (2)

yfeldblum
yfeldblum

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.


Update 1

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

Chris Heald
Chris Heald

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

Related Questions