require 'logger'
require 'digest/md5'

module Verdict
  extend self

  attr_accessor :default_logger, :directory

  def [](handle)
    Verdict.repository[handle.to_s]
  end

  def repository
    if @repository.nil?
      @repository = {}
      discovery
    end

    @repository
  end

  def discovery
    Dir[File.join(Verdict.directory, '**', '*.rb')].each { |f| require f } if @directory
  end

  class Error < StandardError; end
  class SegmentationError < Verdict::Error; end
  class InvalidSubject < Verdict::Error; end
  class EmptySubjectIdentifier < Verdict::Error; end
  class StorageError < Verdict::Error; end

  class ExperimentHandleNotUnique < Verdict::Error
    attr_reader :handle

    def initialize(handle)
      @handle = handle
      super("Another experiment with handle #{handle.inspect} is already defined!")
    end
  end
end

require "verdict/version"
require "verdict/railtie" if defined?(Rails::Railtie)

require "verdict/metadata"
require "verdict/experiment"
require "verdict/group"
require "verdict/assignment"
require "verdict/conversion"
require "verdict/segmenters"
require "verdict/storage"
require "verdict/event_logger"

Verdict.default_logger ||= Logger.new("/dev/null")
Verdict.directory = nil

require 'logger'
require 'digest/md5'

module Verdict
  extend self

  attr_accessor :default_logger, :directory

  def [](handle)
    Verdict.repository[handle.to_s]
  end

  def repository
    if @repository.nil?
      @repository = {}
      discovery
    end

    @repository
  end

  def discovery
    Dir[File.join(Verdict.directory, '**', '*.rb')].each { |f| load f } if @directory
  end

  def clear_respository_cache
    @repository = nil
  end

  class Error < StandardError; end
  class SegmentationError < Verdict::Error; end
  class InvalidSubject < Verdict::Error; end
  class EmptySubjectIdentifier < Verdict::Error; end
  class StorageError < Verdict::Error; end

  class ExperimentHandleNotUnique < Verdict::Error
    attr_reader :handle

    def initialize(handle)
      @handle = handle
      super("Another experiment with handle #{handle.inspect} is already defined!")
    end
  end
end

require "verdict/version"
require "verdict/railtie" if defined?(Rails::Railtie)

require "verdict/metadata"
require "verdict/experiment"
require "verdict/group"
require "verdict/assignment"
require "verdict/conversion"
require "verdict/segmenters"
require "verdict/storage"
require "verdict/event_logger"

Verdict.default_logger ||= Logger.new("/dev/null")
Verdict.directory = nil

Fix issues related to holding references to autoloaded code
Fix issues related to holding references to autoloaded code

Verdict currently holds references to all experiments in
`Verdict.respository`. A common use case for Verdict is to subclass
`Verdict::Experiment` to add your own behaviour. This is problematic
when the subclasses are autoloaded by Rails and can cause Rails to raise
the following exception:

"ArgumentError: A copy of <experiment name> has been removed from the
module tree but is still active!"

The fix for this is to provide a mechanism by which we can trigger
Verdict to reload its experiments via an Active Support `to_prepare`
block in `config/environments/development.rb`. This PR adds the
following:

 - A new method `Verdict.clear_repository_cache` which nils out the
 repository instance variable so the next call to `Verdict[]` will
 trigger reloading all experiments. This can be called in a `to_prepare`
 block in your Rails development config.

 - Changes the load strategy in `Verdict.discovery` from `require` to
 `load` so the experiment files can be loaded again. Note that this has
 the side effect that `Verdict.discovery` cannot be called twice without
 calling `Verdict.clear_repository_cache` in between.
