Vitali Melamud
Vitali Melamud

Reputation: 1397

How to initiate a module in Rails only once

I would like to have a configuration module that is loaded only once.

My code is

module Configuration
  extend self

  def settings 
    @settings ||= # some code that loads the settings
  end
end

class SomeClass
  include Configuration

  def evaluate
    settings.get_some_setting
  end
end

I would expect the @settings to be evaluated and set once but when running a Rails server I see that @settings is recreated in different API calls to the server.

I assume that either I'm not using the variable correctly or the module is instantiated on every API call (probably due to different threads).

What would be the right way to have @settings evaluated only once?

Upvotes: 0

Views: 431

Answers (2)

Les Nightingill
Les Nightingill

Reputation: 6156

You can initialize once at boot time by including an initializer in config/initializers, for example:

# config/initializers/settings.rb

settings = # some code that generates the settings
config = Struct.new(:settings)
Configuration = config.new(settings)

then in your app, for example:

special_value = Configuration.settings.special_value

Upvotes: 3

glinda93
glinda93

Reputation: 8479

Your guess is correct:

the module is instantiated on every API call (probably due to different threads)

If the function is expensive, you can use Rails cache to memoize settings value:

def settings
  Rails.cache.fetch('settings') do
    init_settings
  end
end

Notice that expires_in param is omitted not to expire cache value.

Upvotes: 1

Related Questions