Module: AppConfigFor

Defined in:
lib/app_config_for.rb,
lib/app_config_for/errors.rb,
lib/app_config_for/version.rb,
lib/app_config_for/gem_version.rb

Overview

Gem Version

Ruby gem providing Rails::Application#config_for style capabilities for non-rails applications, gems, and rails engines.

It respects RAILS_ENV and RACK_ENV while providing additional capabilities beyond Rails::Application#config_for.

Usage

Typical usage will be done by extension but inclusion is also supported.

Presume a typical rails database config at ./config/database.yml

One environment variable ('MY_APP_ENV', 'RAILS_ENV', or 'RACK_ENV') is set to 'development' or all are non existent.

./config/sample_app.yml

default: &default
  site: <%= ENV.fetch("MY_APP_SITE", 'www.slackware.com') %>
  password: Slackware#1!

development:
<<: *default
username: Linux

test:
<<: *default
username: TestingWith

production:
<<: *default
username: DefinitelyUsing

shared:
color: 'Blue'

sample_application.rb

require 'app_config_for'

module Sample
  class App
    extend AppConfigFor
    def info
      puts "Current environment is #{App.env}"

      # Access the configuration in various ways depending on need/preference.
      puts "Remote Host: #{App.site}"
      puts "Username:    #{App.configured.username}"
      puts "Password:    #{App.config_for(App).password}"
      puts "Domain:      #{self.class.config_for(:app)[:domain]}"

      # Access a different config
      if App.config_file?(:database)
        adapter_name = App.config_for(:database).adapter
        puts "Rails is using the #{adapter_name} adapter."
      end
    end
  end
end

Defined Under Namespace

Modules: VERSION Classes: ConfigNotFound, Error, InvalidEnvInheritanceStyle, LoadError

Constant Summary collapse

EnvInheritanceStyles =

Types of hierarchical traversal used to determine the runtime environment.

  • :none - No inheritance active

  • :namespace - Inheritance by lexical namespace

  • :class - Inheritance by class hierarchy

  • :namespace_class - Namespace inheritance combined with class inheritance

  • :class_namespace - Class inheritance combined with namespace inheritance

[:none, :namespace, :class, :namespace_class, :class_namespace]

Class Method Summary collapse

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object

Note:

Values can be written or read prior to the loading of the configuration presuming the configuration can load without error.

Allow access to configuration getters and setters directly from the extending class/module.

Examples:

class Sample
  extend AppConfigFor
end

# Presuming config/sample.yml contains a configuration for 'log_level' and 'status' but no other keys.
Sample.log_level          # => :production
Sample.log_level = :debug 
Sample.log_level          # => :debug

# You are allowed to set the value prior reading it should the need should arise.
Sample.status = 'active'  
Sample.status             # => 'active'

# However, you cannot invent new keys with these methods.
Sample.something_else     # => NoMethodError(undefined method `something_else' for Sample)
Sample.something_else = 1 # => NoMethodError(undefined method `something_else=' for Sample)


495
496
497
498
499
500
501
502
503
504
505
506
507
508
# File 'lib/app_config_for.rb', line 495

def method_missing(name, *args, &block)
  if configured?(name.to_s.split('=').first.to_sym)
    configured.send(name, *args, &block)
  else
    begin
      super
    rescue Exception => e
      # Remove the call to super from the backtrace to make it more apparent where the failure occurred,
      super_line = Regexp.new("#{__FILE__}:#{__LINE__ - 3}") 
      e.set_backtrace(ActiveSupport::BacktraceCleaner.new.tap { |bc| bc.add_silencer { |line| line =~ super_line } }.clean(e.backtrace))
      raise e
    end
  end
end

Class Method Details

.add_env_prefix(prefix, at_beginning = true) ⇒ Array<Symbol>

Note:

Prefixes added here will affect all consumers of AppConfigFor. For targeted changes see: #add_env_prefix

Add an additional environmental prefix to be used when determining current environment.

Parameters:

  • prefix (Symbol, Object)

    Prefix to add.

    Non symbols are converted via prefix_from.

  • at_beginning (Boolean) (defaults to: true)

    where to insert the new prefix with respect to existing prefixes.

    • true - Add to the beginning of the list.

    • false - Add to the end of the list.

Returns:

  • (Array<Symbol>)

    Current prefixes (without inheritance)

See Also:



545
546
547
548
# File 'lib/app_config_for.rb', line 545

def add_env_prefix(prefix, at_beginning = true)
  env_prefixes(false, false).send(at_beginning ? :unshift : :push, prefix_from(prefix)).uniq!
  env_prefixes(false)
end

.env_name(prefixes = env_prefixes) ⇒ String

The name of the current runtime environment. This is value of the first non blank environment variable. If no value can be found, the default is 'development'. Prefixes like :some_app, :rails, and :rack convert to 'SOME_APP_ENV', 'RAILS_ENV', and 'RACK_ENV' respectively.

Parameters:

  • prefixes (Array<#to_s>) (defaults to: env_prefixes)

    List of prefixes of environment variables to check.

Returns:

  • (String)

    current runtime environment.

See Also:



556
557
558
# File 'lib/app_config_for.rb', line 556

def env_name(prefixes = env_prefixes)
  Array(prefixes).inject(nil) { |current_env, name| current_env || ENV["#{name.to_s.upcase}_ENV"].presence } || 'development'
end

.env_prefixes(_ = true, dup = true) ⇒ Array<Symbol>

Prefixes used to determine the environment name.

A prefix of :some_app will will cause AppConfigFor to react to the environment variable 'SOME_APP_ENV' The order of the prefixes will be the order in which AppConfigFor searches the environment variables.

Parameters:

  • _ (defaults to: true)

    Ignored. Unlike #env_prefixes, the first parameter is ignored as there is no inheritance at this point.

  • dup (Boolean) (defaults to: true)

    Return a duplicate of the internal array to prevent accidental modification.

Returns:

  • (Array<Symbol>)

    Defaults to [:rails, :rack]

See Also:



569
570
571
572
# File 'lib/app_config_for.rb', line 569

def env_prefixes(_ = true, dup = true)
  @env_prefixes ||= [:rails, :rack]
  dup ? @env_prefixes.dup : @env_prefixes
end

.gem_versionGem::Version

Current version of this gem with comparable values.

Returns:

  • (Gem::Version)


5
6
7
# File 'lib/app_config_for/gem_version.rb', line 5

def self.gem_version
  Gem::Version.new(VERSION::STRING)
end

.namespace_of(object) ⇒ Module, ...

Lexical namespace of an object. Strings are considered to hold the #name of a Class or Module. Anything not a String, Class, or Module will return the namespace of the class of the object.

Examples:

module Some
  class App
  end
end

namespace_of(Some::App)      # => Some
namespace_of('Some::App')    # => Some
namespace_of(Some::App.new)  # => Some
namespace_of(Some)           # => nil

Parameters:

  • object (Module, Class, String, Object)

Returns:

  • (Module, Class, nil)

    nil is returned if there is no surrounding namespace.



589
590
591
# File 'lib/app_config_for.rb', line 589

def namespace_of(object)
  (String === object ? object : nearest_named_class(object).name).deconstantize.safe_constantize
end

.namespaces_of(object) ⇒ Array<Module, Class>

Array of all hierarchical lexical namespaces of an object. Uses namespace_of

Examples:

module Some
  class App
    class Connection
    end
  end
end

namespaces_of(Some::App::Connection) # => [Some::App, Some]
namespaces_of(Some) # => []

Parameters:

  • object (Module, Class, String, Object)

Returns:

  • (Array<Module, Class>)


606
607
608
# File 'lib/app_config_for.rb', line 606

def namespaces_of(object)
  (object = [namespace_of(object)]).each { |x| x && object << namespace_of(x) }[0..-2]
end

.nearest_named_class(object) ⇒ Class

Locate the nearest class that is not anonymous.

Parameters:

  • object (Object)

Returns:

  • (Class)

    The first non-anonymous class that is in the class hierarchy.



613
614
615
616
617
618
619
620
621
# File 'lib/app_config_for.rb', line 613

def nearest_named_class(object)
  # Switch from an instance to a class
  object = object.class unless object.is_a?(Module)
  # Switch from anonymous module to a class unless it provides a name
  object = object.class unless object.try(:name) || object.respond_to?(:superclass)
  # Continue up the hierarchy while we are in an anonymous class
  object = object.superclass while object.name.nil?
  object
end

.parent_of(object) ⇒ Class?

Parent of an object. Parent of an object. While similar to inheritance it provides a meaningful value for strings and other objects. Classes return super classes. Strings are treated as a name of a class and an attempt is made to locate that class (not the superclass of the named class). All other objects return the class of the object.

Examples:

module Some
  class Base
  end
  class App < Base
  end
end

parent_of(Some::App)     # => Some::Base
parent_of(Some::App.new) # => Some::App
parent_of('Some::App')   # => Some::App
parent_of('wtf')         # => nil

Parameters:

  • object (Class, String, Object)

Returns:

  • (Class, nil)

    nil is returned if a string is given that is not the name of a class.



643
644
645
646
647
648
649
650
651
652
# File 'lib/app_config_for.rb', line 643

def parent_of(object)
  case object
  when String
    object.safe_constantize
  when Class
    object.superclass
  else
    object.class
  end
end

.parents_of(object) ⇒ Array<Class>

List of all hierarchical parents of an object. Uses parents_of

Examples:

module Some
  class Base
  end
  class App < Base
  end
end

parents_of(Some::App)     # => [Some::Base, Object, BasicObject]
parents_of(Some::App.new) # => [Some::App, Some::Base, Object, BasicObject]
parents_of('Some::App')   # => [Some::App, Some::Base, Object, BasicObject]
parents_of('wtf')         # => []

Parameters:

  • object (Class, String, Object)

Returns:

  • (Array<Class>)


670
671
672
# File 'lib/app_config_for.rb', line 670

def parents_of(object)
  (object = [parent_of(object)]).each { |x| x && object << parent_of(x) }[0..-2]
end

.prefix_from(object) ⇒ Symbol

Converts an object to a prefix symbol. Non symbols are converted to underscored symbols with '/' characters changed to underscores. Conversion by object type is as follows:

  • Symbol -> symbol

  • Module -> module.name

  • Class -> class.name

  • String -> string

  • Pathname -> pathname.basename (Without an extension)

  • other -> other.class.name

Examples:

module Some
  class App
  end
end

# All of the following return :some_app
prefix_from(Some::App)
prefix_from('Some::App')
prefix_from(Some::App.new)
prefix_from(:some_app)
prefix_from(Pathname.new('/foo/bar/some_app.yml'))

Parameters:

  • object (Symbol, Module, Class, String, Pathname, Object)

    object to convert to a prefix

Returns:

  • (Symbol)


697
698
699
700
701
702
703
704
705
706
707
708
709
710
# File 'lib/app_config_for.rb', line 697

def prefix_from(object)
  if object.is_a?(Symbol)
    object
  else
    case object
    when String
      object
    when Pathname
      object.basename('.*').to_s
    else
      nearest_named_class(object).name
    end.underscore.gsub('/','_').to_sym
 end
end

.progenitor_of(object, style = nil) ⇒ Object?

The first env_prefix aware namespace/parent of an object. Search is dependant on the inheritance style given.

Parameters:

  • object (Object)

    Object to retrieve the progenitor of.

  • style (#to_s) (defaults to: nil)

    Type of hierarchical traversal.

Returns:

  • (Object, nil)

    nil is returned if there is no progenitor.

Raises:

See Also:



719
720
721
722
723
# File 'lib/app_config_for.rb', line 719

def progenitor_of(object, style = nil)
  style = verified_style!(style, object)
  command = {namespace: :namespace_of, class: :parent_of}[style.to_s.split('_').first.to_sym]
  object && command && send(command, object).yield_self { |n| n && (n.respond_to?(:env_prefixes) ? n : progenitor_of(n)) }
end

.progenitor_prefixes_of(object, style = nil, all = true) ⇒ Array<Symbol>

Extract the env_prefixes from the progenitor of the given object.

Parameters:

  • object (Object)

    Object to retrieve the progenitor_of and subsequently the #env_prefixes.

  • style (#to_s) (defaults to: nil)

    Type of hierarchical traversal.

  • all (Boolean) (defaults to: true)

    Return inherited prefixes.

    If there is no progenitor of the object and all is true then AppConfigFor.env_prefixes will be returned.

Returns:

  • (Array<Symbol>)

    Environment prefixes for this object.

Raises:

See Also:



734
735
736
# File 'lib/app_config_for.rb', line 734

def progenitor_prefixes_of(object, style = nil, all = true)
  Array((progenitor_of(object, style) || all && AppConfigFor).try(:env_prefixes, all))
end

.progenitors_of(object, style = nil, unique = true) ⇒ Array<Object>

List of hierarchical progenitors of an object. Hierarchical precedence is controlled by the style.

Parameters:

  • object (Object)

    Object to get the progenitors from

  • style (#to_s) (defaults to: nil)

    Type of hierarchical traversal.

  • unique (Boolean) (defaults to: true)

    Remove duplicate progenitors.

Returns:

  • (Array<Object>)

Raises:

See Also:



747
748
749
750
751
752
753
754
755
756
757
758
759
760
# File 'lib/app_config_for.rb', line 747

def progenitors_of(object, style = nil, unique = true)
  style = verified_style!(style, object)
  unique = unique && style != :none
  if object && style != :none
    styles = style.to_s.split('_')
    if styles.size > 1
      styles.flat_map{ |style| progenitors_of(object, style, false) }
    else
      Array(progenitor_of(object, style)).yield_self { |x| x + progenitors_of(x.last, nil, false) }
    end
  else
    []
  end.yield_self { |result| unique ? result.reverse.uniq.reverse + [self] : result }
end

.remove_env_prefix(prefix, _ = false) ⇒ Array<Symbol>

Note:

Prefixes removed here will affect all consumers of AppConfigFor. For targeted changes see: #remove_env_prefix

Remove an environmental prefix from the existing list.

Parameters:

  • prefix (Symbol, Object)

    Prefix to remove.

    Non symbols are converted via AppConfigFor.prefix_from.

  • _ (defaults to: false)

    Ignored. Unlike #remove_env_prefix, the first parameter is ignored as there is no inheritance at this point.

Returns:

  • (Array<Symbol>)

    Current prefixes (without inheritance)



768
769
770
771
# File 'lib/app_config_for.rb', line 768

def remove_env_prefix(prefix, _ = false)
  env_prefixes(false, false).delete(prefix_from(prefix))
  env_prefixes(false)
end

.verified_style!(style = nil, object = nil) ⇒ Object

Verifies the inheritance style. If style is nil, the object, if given, will be queried for its env_inheritance. Otherwise the style will default to :namespace: return [Symbol] A valid inheritance style.

Parameters:

  • style (#to_s) (defaults to: nil)

    Inheritance style to verify.

  • object (Object) (defaults to: nil)

    Object to query for env_inheritance if style is nil.

Raises:

  • InvalidEnvInheritanceStyle - An invalid inheritance style was received.



779
780
781
782
783
# File 'lib/app_config_for.rb', line 779

def verified_style!(style = nil, object = nil)
  style ||= object.respond_to?(:env_inheritance) && object.env_inheritance || :namespace
  style = style.try(:to_sym) || style.to_s.to_sym
  EnvInheritanceStyles.include?(style) ? style : raise(InvalidEnvInheritanceStyle.new(style))
end

.versionGem::Version

Current version of this gem.

Returns:

  • (Gem::Version)

See Also:



9
10
11
# File 'lib/app_config_for/version.rb', line 9

def self.version
  gem_version
end

.yml_name_from(object) ⇒ String, Pathname

Determine the name of the yml file from the object given. No pathing is assumed. Anything not a Pathname is converted to an underscored string with '/' characters changed to underscores and a '.yml' extension Determination by object type is as follows:

  • Pathname -> pathname

  • Module -> module.name

  • Class -> class.name

  • String -> string

  • Symbol -> symbol.to_s

  • other -> other.class.name

Examples:

module Some
  class App
  end
end

# All of the following return 'some_app.yml'
yml_name_from(Some::App)
yml_name_from(Some::App.new)
yml_name_from(:some_app)
yml_name_from('Some/App')
yml_name_from('Some::App')

# Pathnames receive no conversion
yml_name_from(Pathname.new('not/a/yml_file.txt')) # => #<Pathname:not/a/yml_file.txt>

Parameters:

  • object (Object)

    Object to determine a yml name from.

Returns:

  • (String, Pathname)


812
813
814
815
816
817
818
819
820
821
822
823
824
825
# File 'lib/app_config_for.rb', line 812

def yml_name_from(object)
  if object.is_a?(Pathname)
    object
  else
    case object
    when String
      object
    when Symbol
      object.to_s
    else
      nearest_named_class(object).name
    end.underscore.gsub('/','_') + '.yml'
  end
end

Instance Method Details

#add_config_directories(*additional_directories, at_beginning: true) ⇒ Array<Pathname>

Add multiple additional directories to be used when searching for the config file. Any duplicates will be ignored.

Parameters:

  • additional_directories (Array<#to_s>)

    additional directories to add

  • at_beginning (Boolean) (defaults to: true)

    where to insert the new directories with respect to existing prefixes

    • true - Add to the beginning of the list.

    • false - Add to the end of the list.

Returns:

  • (Array<Pathname>)

    updated array of additional config directories

See Also:



102
103
104
105
106
107
108
# File 'lib/app_config_for.rb', line 102

def add_config_directories(*additional_directories, at_beginning: true)
  additional_directories = additional_directories.flatten.map { |d| Pathname.new(d.to_s) }
  directories = additional_config_directories(false).send(at_beginning ? :unshift : :push, additional_directories)
  directories.flatten!
  directories.uniq!
  directories.dup
end

#add_config_directory(additional_directory, at_beginning = true) ⇒ Array<Pathname>

Add an single additional directory to be used when searching for the config file. Any duplicates will be ignored.

Parameters:

  • additional_directory (#to_s)

    additional directory to add

  • at_beginning (Boolean) (defaults to: true)

    where to insert the new directory with respect to existing prefixes

    • true - Add to the beginning of the list.

    • false - Add to the end of the list.

Returns:

  • (Array<Pathname>)

    updated array of additional config directories

See Also:



119
120
121
# File 'lib/app_config_for.rb', line 119

def add_config_directory(additional_directory, at_beginning = true)
  add_config_directories additional_directory, at_beginning: at_beginning
end

#add_config_name(config_name, at_beginning = true) ⇒ Array<Object>

Add an additional base name to be used when locating the config file.

Parameters:

  • config_name (Object)

    Object to extract a config name from.

  • at_beginning (Boolean) (defaults to: true)

    where to insert the new config name with respect to existing names.

    • true - Add to the beginning of the list.

    • false - Add to the end of the list.

Returns:

  • (Array<Object>)

    current config names

See Also:



130
131
132
# File 'lib/app_config_for.rb', line 130

def add_config_name(config_name, at_beginning = true)
  add_config_names config_name, at_beginning: at_beginning
end

#add_config_names(*config_names, at_beginning: true) ⇒ Array<Object>

Add multiple additional base names to be used when locating the config file.

Parameters:

  • config_names (Array<Object>)

    Array of objects to extract a config name from.

  • at_beginning (Boolean) (defaults to: true)

    where to insert the new config names with respect to existing names.

    • true - Add to the beginning of the list.

    • false - Add to the end of the list.

Returns:

  • (Array<Object>)

    current config names

See Also:



141
142
143
144
145
146
# File 'lib/app_config_for.rb', line 141

def add_config_names(*config_names, at_beginning: true)
  names = config_names(false).send(at_beginning ? :unshift : :push, config_names)
  names.flatten!
  names.uniq!
  names.dup
end

#add_env_prefix(prefix = nil, at_beginning = true) ⇒ Array<Symbol>

Add an additional environmental prefix to be used when determining current environment.

Parameters:

  • prefix (Symbol, Object) (defaults to: nil)

    Prefix to add.

    nil is treated as self

    Non symbols are converted via AppConfigFor.prefix_from.

  • at_beginning (Boolean) (defaults to: true)

    where to insert the new prefix with respect to existing prefixes

    • true - Add to the beginning of the list.

    • false - Add to the end of the list.

Returns:

  • (Array<Symbol>)

    Current prefixes (without inheritance)

See Also:



157
158
159
160
# File 'lib/app_config_for.rb', line 157

def add_env_prefix(prefix = nil, at_beginning = true)
  env_prefixes(false, false).send(at_beginning ? :unshift : :push, AppConfigFor.prefix_from(prefix || self)).uniq!
  env_prefixes(false)
end

#additional_config_directories(dup = true) ⇒ Array<Pathname>

Directories to be checked in addition to the defaults when searching for the config file.

Parameters:

  • dup (Boolean) (defaults to: true)

    Return a duplicated array to prevent accidental side effects

Returns:

  • (Array<Pathname>)

See Also:



167
168
169
170
# File 'lib/app_config_for.rb', line 167

def additional_config_directories(dup = true)
  @additional_config_directories ||= []
  dup ? @additional_config_directories.dup : @additional_config_directories
end

#config_directoriesArray<Pathname>

All directories that will be used when searching for the config file. Search order is as follows:

  1. Rails configuration directories if Rails is present.

  2. Engine configuration directories if extended by an engine.

  3. Additional configuration directories.

  4. ./config within the current working directory.

All paths are expanded at time of call.

Returns:

  • (Array<Pathname>)

    directories in the order they will be searched.

See Also:



191
192
193
194
195
196
# File 'lib/app_config_for.rb', line 191

def config_directories
  directories = ['Rails'.safe_constantize&.application&.paths, try(:paths)].compact.map { |root| root["config"].existent.first }.compact
  directories.concat additional_config_directories
  directories.push(Pathname.getwd + 'config')
  directories.map { |directory| Pathname.new(directory).expand_path }.uniq
end

#config_directory=(directory) ⇒ Array<Pathname> Also known as: config_directories=

Clear all additional config directories and set to the directory given.

Parameters:

  • directory (#to_s)

    additional directory to use

Returns:

  • (Array<Pathname>)

    updated array of additional config directories

See Also:



177
178
179
180
# File 'lib/app_config_for.rb', line 177

def config_directory=(directory)
  additional_config_directories(false).clear
  add_config_directory(directory)
end

#config_file(name = nil, fallback = nil) ⇒ Pathname?

Configuration file that will be used. This is the first file from #config_files that exists or nil if none exists.

Parameters:

  • name (Symbol, Object) (defaults to: nil)

    Name of the config to load.

    Conversion to a file name will occur using AppConfigFor.yml_name_from.

    If name is nil #config_names will be used.

  • fallback (Symbol, Object) (defaults to: nil)

    If not nil, attempt to load a fallback configuration if the requested one cannot be found.

Returns:

  • (Pathname, nil)


205
206
207
208
209
210
211
# File 'lib/app_config_for.rb', line 205

def config_file(name = nil, fallback = nil)
  unless name.is_a?(Pathname)
    config_files(name).find(&:exist?)
  else
    name.exist? ? name.expand_path : nil
  end.yield_self { |file| file || fallback && config_file(fallback) }
end

#config_file?(name = nil, fallback = nil) ⇒ Boolean

Does a config file exit?

Parameters:

  • name (Symbol, Object) (defaults to: nil)

    Name of the config to load.

    Conversion to a file name will occur using AppConfigFor.yml_name_from.

    If name is nil #config_names will be used.

  • fallback (Symbol, Object) (defaults to: nil)

    If not nil, attempt to load a fallback configuration if the requested one cannot be found.

Returns:

  • (Boolean)


234
235
236
# File 'lib/app_config_for.rb', line 234

def config_file?(name = nil, fallback = nil)
  !config_file(name, fallback).blank?
end

#config_files(name = nil) ⇒ Array<Pathname>

The list of potential config files that will be searched for and the order in which they will be searched.

Parameters:

  • name (Symbol, Object) (defaults to: nil)

    Name of the config to load.

    Conversion to a file name will occur using AppConfigFor.yml_name_from.

    If name is nil, #config_names will be used.

    If name is object that responds to config_files, it will be called instead.

Returns:

  • (Array<Pathname>)


219
220
221
222
223
224
225
226
# File 'lib/app_config_for.rb', line 219

def config_files(name = nil)
  if name.respond_to?(:config_files) && name != self
    name.config_files
  else
    names = (name && name != self && Array(name) || config_names).map { |name| AppConfigFor.yml_name_from(name) }
    config_directories.map { |directory| names.map { |name| directory + name } }.flatten
  end
end

#config_for(name, env: nil, fallback: nil) ⇒ ActiveSupport::OrderedOptions

Configuration settings for the current environment. Shared sections in the yml config file are automatically merged into the returned configuration.

Examples:

config_for(:my_app)              # Load my_app.yml and extract the section relative to the current environment.
config_for(:my_app).log_level    # Get the configured logging level from my_app.yml for the current environment.
config_for("MyApp", env: 'test') # Load my_app.yml and extract the 'test' section.

module Other
  class App
  end
end
# Load other_app.yml and extract the 'production' section.
# Notice that Other::App does not need to extend AppConfigFor
config_for(Other::App, env: :production)

Parameters:

  • name (Symbol, Object)

    Name of the config to load.

    Conversion to a file name will occur using AppConfigFor.yml_name_from.

    If name is nil #config_names will be used.

  • env (Symbol, String) (defaults to: nil)

    name of environment to use. nil will use the current environment settings from #env

  • fallback (Symbol, Object) (defaults to: nil)

    If not nil, attempt to load a fallback configuration if the requested one cannot be found.

Returns:

  • (ActiveSupport::OrderedOptions)

Raises:

  • ConfigNotFound - No configuration file could be located.

  • LoadError - A configuration file was found but could not be properly read.

See Also:



262
263
264
265
266
267
268
269
270
271
272
# File 'lib/app_config_for.rb', line 262

def config_for(name, env: nil, fallback: nil)
  config, shared = config_options(name, fallback).fetch_values((env || self.env).to_sym, :shared) { nil }
  config ||= shared

  if config.is_a?(Hash)
    config = shared.deep_merge(config) if shared.is_a?(Hash)
    config = ActiveSupport::OrderedOptions.new.update(config)
  end

  config
end

#config_name=(new_config_name) ⇒ Array<Object> Also known as: config_names=

Clear all config names and set to the name given. Set the base name of the config file to use.

Parameters:

Returns:

  • (Array<Object>)

    current config names

See Also:



279
280
281
282
# File 'lib/app_config_for.rb', line 279

def config_name=(new_config_name)
  config_names(false).clear
  add_config_names(new_config_name)
end

#config_names(dup = true) ⇒ Object

Base names of the configuration file. Defaults to: [self]



287
288
289
290
# File 'lib/app_config_for.rb', line 287

def config_names(dup = true)
  @config_names ||= [self]
  dup ? @config_names.dup : @config_names
end

#config_options(name = nil, fallback = nil) ⇒ Hash

Configuration for all environments parsed from the #config_file.

Parameters:

  • name (Symbol, Object) (defaults to: nil)

    Name of the config to load.

    Conversion to a file name will occur using AppConfigFor.yml_name_from.

    If name is nil #config_names will be used.

  • fallback (Symbol, Object) (defaults to: nil)

    If not nil, attempt to load a fallback configuration if the requested one cannot be found.

Returns:

  • (Hash)

Raises:

  • ConfigNotFound - No configuration file could be located.

  • LoadError - A configuration file was found but could not be properly read.



300
301
302
303
304
305
306
307
308
309
# File 'lib/app_config_for.rb', line 300

def config_options(name = nil, fallback = nil)
  file = config_file(name, fallback).to_s
  ActiveSupport::ConfigurationFile.parse(file).deep_symbolize_keys
rescue SystemCallError => exception
  locations = name.is_a?(Pathname) ? Array(name) : config_files(name)
  locations += config_files(fallback) if fallback
  raise ConfigNotFound.new(locations, exception)
rescue => exception
  raise file ? LoadError.new(file, exception) : exception
end

#configured(reload = false) ⇒ ActiveSupport::OrderedOptions

Convenience method for #config_for(self). Caches the result for faster access.

Examples:

module Sample
  class App
    extend AppConfigFor
    @@logger = Logger.new($stdout, level: configured.level)
  end
end
Sample::App.configured.url    # Get the configured url from my_app.yml for the current environment

Parameters:

  • reload (Boolean) (defaults to: false)

    Update the cached config by rereading the configuration file.

Returns:

  • (ActiveSupport::OrderedOptions)

Raises:

  • ConfigNotFound - No configuration file could be located.

  • LoadError - A configuration file was found but could not be properly read.

See Also:



325
326
327
328
329
330
331
332
# File 'lib/app_config_for.rb', line 325

def configured(reload = false)
  if reload || !@configured
    # @disable_local_missing = true # Disable local method missing to prevent recursion
    @configured = config_for(nil, env: env(reload))
    # @disable_local_missing = false # Reenable local method missing since no exception occurred.
  end
  @configured
end

#configured!ActiveSupport::OrderedOptions

Convenience method for #configured(true).

Examples:

module Sample
  class App
    extend AppConfigFor
    mattr_accessor :logger, default: Logger.new($stdout)
    logger.level = configured.log_level
  end
end
# Switch to production
ENV['SAMPLE_APP_ENV'] = 'production'
# Update the log level with the production values
Sample::App.logger.level = Sample::App.configured!.log_level

Returns:

  • (ActiveSupport::OrderedOptions)

Raises:

  • ConfigNotFound - No configuration file could be located.

  • LoadError - A configuration file was found but could not be properly read.



350
351
352
# File 'lib/app_config_for.rb', line 350

def configured!
  configured(true)
end

#configured?(key) ⇒ Boolean

Note:

This is primarily used internally during #respond_to_missing? and #method_missing calls.

Check for the existence of a configuration setting. Handles exceptions and recursion.

Parameters:

  • key (#to_s)

    Key to check for

Returns:

  • (Boolean)
    • true - Configuration has the key

    • false - If one of the following:

      1. Configuration does not have the key

      2. Called recursively while retrieving the configuration

      3. An exception is raised while retrieving the configuration



363
364
365
366
367
368
369
370
371
372
373
374
375
376
# File 'lib/app_config_for.rb', line 363

def configured?(key)
  if @disable_local_missing
    false
  else
    @disable_local_missing = true
    begin
      configured.has_key?(key.to_s.to_sym)
    rescue Exception # One of the few times you ever want to catch this exception and not reraise it.
      false
    ensure
      @disable_local_missing = false
    end
  end
end

#env(reload = false) ⇒ ActiveSupport::EnvironmentInquirer

Returns the current runtime environment. Caches the result.

Examples:

module Sample
  extend AppConfigFor
end
Sample.env              # => 'development'
Sample.env.development? # => true
Sample.env.production?  # => false

Parameters:

  • reload (Boolean) (defaults to: false)

    Update the cached env by requerying the environment

Returns:



388
389
390
391
# File 'lib/app_config_for.rb', line 388

def env(reload = false)
  @env = ActiveSupport::EnvironmentInquirer.new(env_name) if reload || @env.nil?
  @env
end

#env!ActiveSupport::EnvironmentInquirer

Convenience method for #env(true).

Examples:

module Sample
  extend AppConfigFor
end
Sample.env              # => 'development'
Sample.env.development? # => true
Sample.env.production?  # => false
# Switch to production
ENV['SAMPLE_APP_ENV'] = 'production'
Sample.env.production?  # => false
Sample.env!.production? # => true

Returns:



406
407
408
# File 'lib/app_config_for.rb', line 406

def env!
  env(true)
end

#env=(environment) ⇒ ActiveSupport::EnvironmentInquirer

Set the runtime environment (without affecting environment variables)

Examples:

ENV['SAMPLE_ENV'] = 'test'
module Sample
  extend AppConfigFor
end
Sample.env        # => 'test'
Sample.env = 'development'
Sample.env        # => 'development'
ENV['SAMPLE_ENV'] # => 'test'

Parameters:

  • environment (#to_s)

Returns:



422
423
424
# File 'lib/app_config_for.rb', line 422

def env=(environment)
  @env = ActiveSupport::EnvironmentInquirer.new(environment.to_s)
end

#env_inheritanceSymbol

Current runtime environment inheritance style. Defaults to :namespace.

Returns:

  • (Symbol)


428
429
430
# File 'lib/app_config_for.rb', line 428

def env_inheritance
  @env_inheritance ||= :namespace
end

#env_inheritance=(style) ⇒ Symbol

Set the runtime environment inheritance.

Parameters:

  • style (#to_s)

    New inheritance style

Returns:

  • (Symbol)

Raises:

See Also:



437
438
439
# File 'lib/app_config_for.rb', line 437

def env_inheritance=(style)
  @env_inheritance = AppConfigFor.verified_style!(style)
end

#env_nameString

The name of the current runtime environment for this object.

Convenience method for AppConfigFor.env_name(env_prefixes)

If no value can be found, the default is 'development'.

Returns:

  • (String)

    current runtime environment.

See Also:



448
449
450
# File 'lib/app_config_for.rb', line 448

def env_name
  AppConfigFor.env_name(env_prefixes)
end

#env_prefixes(all = true, dup = true) ⇒ Array<Symbol>

Prefixes used to determine the environment name.

A prefix of :some_app will will cause AppConfigFor to react to the environment variable 'SOME_APP_ENV' The order of the prefixes will be the order in which AppConfigFor searches the environment variables. A prefix for self is automatically added at the time of extension/inclusion of AppConfigFor.

Parameters:

  • all (Boolean) (defaults to: true)

    Combine current prefixes with inherited prefixes.

  • dup (Boolean) (defaults to: true)

    Return a duplicate of the internal array to prevent accidental modification.

Returns:

  • (Array<Symbol>)

    Environment prefixes for this object.

See Also:



464
465
466
467
468
469
470
471
472
473
474
# File 'lib/app_config_for.rb', line 464

def env_prefixes(all = true, dup = true)
  unless @env_prefixes
    @env_prefixes = []
    add_env_prefix
  end
  if all
    @env_prefixes + AppConfigFor.progenitor_prefixes_of(self)
  else
    dup ? @env_prefixes.dup : @env_prefixes
  end
end

#initialize(*args) ⇒ Object

AppConfigFor can be included instead of extended. If this occurs, instances of the class will have their own list of prefixes. The default class prefix will be automatically added to the list.



88
89
90
91
# File 'lib/app_config_for.rb', line 88

def initialize(*args)
  add_env_prefix
  super
end

#remove_env_prefix(prefix, all = false) ⇒ Array<Symbol>

Remove an environmental prefix from the existing list.

Parameters:

  • prefix (Symbol, Object)

    Prefix to remove.

    nil is treated as self

    Non symbols are converted via AppConfigFor.prefix_from.

  • all (Boolean) (defaults to: false)

    Remove this prefix throughout the entire inheritance chain.

    USE WITH CAUTION: When true this will affect other consumers of AppConfigFor by altering their env prefix values.

Returns:

  • (Array<Symbol>)

    Current prefixes (without inheritance)

See Also:



518
519
520
521
522
523
524
525
526
# File 'lib/app_config_for.rb', line 518

def remove_env_prefix(prefix, all = false)
  if all
    remove_env_prefix(prefix)
    AppConfigFor.progenitor_of(self)&.remove_env_prefix(prefix, all)
  else
    env_prefixes(false, false).delete(AppConfigFor.prefix_from(prefix))
  end
  env_prefixes(all)
end

#respond_to_missing?(name, *args) ⇒ Boolean

Return true if the missing method is a configuration getter or setter.



530
531
532
# File 'lib/app_config_for.rb', line 530

def respond_to_missing?(name, *args)
  configured?(name.to_s.split('=').first.to_sym) || super
end