In my rails app I've decided to use singleton to create some sort of factory to get objects properly.
config/initializers/registry.rb:
registry = Registry.instance
registry.define_lazy :period_predictor do
  PeriodPredictor.new(NotificationBuilder.new, 28, 4, 3)
end
registry.define_lazy :notification_sender do
  NotificationSender.new
end
lib/registry.rb:
# Registry class which is singleton and stores values.
class Registry
  include Singleton
  # Define simple value. Like a constant.
  #
  # @param key [Symbol]
  # @param value
  def define(key, value)
    container[key] = value
  end
  # Define value (block required) which will be calculated when it will be need.
  # It will calculate it every time when it will be needed.
  #
  # @param key [Symbol]
  # @param block [Proc]
  def define_lazy(key, &block)
    container[key] = LazyValue.new(&block)
  end
  # Get value.
  #
  # @param key [Symbol]
  #
  # @return
  def get(key)
    value = container[key]
    if value.is_a?(LazyValue)
      value = value.call
    end
    value
  end
  # Get value (hash access).
  #
  # @param key [Symbol]
  #
  # @return
  def [](key)
    get(key)
  end
  # Export all the values.
  # Replacing values of returned hash won't change registry.
  #
  # @return [Hash]
  def export
    container.clone
  end
  # Import hash data to registry
  #
  # @param data [Hash]
  def import(data)
    data.each do |key, value|
      @container[key] = value
    end
  end
  private
  # Get container.
  #
  # @return [Hash]
  def container
    @container ||= {}
  end
  # Class to store lazy value.
  class LazyValue
    def initialize(&block)
      @block = block
    end
    def call
      @block.call
    end
  end
end
Everything works fine in production. But when I change something (even add space somewhere), I can't get data from singleton anymore in controllers.
Registry.instance became just fresh instance of registry and Registry.instance[:period_predictor] became nil
Same thing happens when I just go away with singleton and make class methods.
It does not do this thing only if I turn off singleton and create a constant:
registry = Registry.new
registry.define_lazy :period_predictor do
  PeriodPredictor.new(NotificationBuilder.new, 28, 4, 3)
end
registry.define_lazy :notification_sender do
  NotificationSender.new
end
REGISTRY = registry
Rails version 4.2.5.1
Do someone have any ideas why this is happening?
I've figured out, that it happenes because Rails refreshes autoloaded constants. http://guides.rubyonrails.org/autoloading_and_reloading_constants.html#constant-reloading
I've added line require "#{Rails.root}/lib/registry" at the beggining of initializer and everything is OK.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With