lib/envied.rb in envied-0.7.0 vs lib/envied.rb in envied-0.7.1
- old
+ new
@@ -1,238 +1,56 @@
require 'envied/version'
require 'envied/cli'
-require 'virtus'
+require 'envied/coercer'
+require 'envied/variable'
+require 'envied/configuration'
class ENVied
- module Hashable
- def to_hash
- require 'rack/utils'
- ::Rack::Utils.parse_nested_query(self)
- end
- end
-
- module Arrayable
- def to_a
- self.split(/(?<!\\), ?/).map{|i| i.gsub(/\\,/,',') }
- end
- end
-
- class Configuration
- include Virtus.model
-
- def self.variable(name, type = :String, options = {})
- options = { default: nil, strict: true, group: self.current_group }.merge(options)
- type = Array if type == :Array
- attribute(name, type, options)
- end
-
- def self.group(name, &block)
- self.current_group = name.to_sym
- yield
- ensure
- self.current_group = :default
- end
-
- def self.enable_defaults
- (@enable_defaults ||= false).respond_to?(:call) ?
- @enable_defaults.call :
- @enable_defaults
- end
-
- def self.enable_defaults!(value = nil, &block)
- value ||= block if block_given?
- @enable_defaults = value
- end
-
- class << self
- alias_method :defaults_enabled?, :enable_defaults
- alias_method :enable_defaults=, :enable_defaults!
- attr_writer :current_group
- end
-
- def self.current_group
- @current_group ||= :default
- end
- end
-
- def self.configuration(options = {}, &block)
- if block_given?
- @configuration = build_configuration(&block).tap do |c|
- options.each {|k, v| c.public_send("#{k}=", v) }
- end
- end
- @configuration ||= build_configuration
- end
-
- def self.configure(options = {}, &block)
- deprecation_warning "ENVied.configure will be deprecated. Please generate an Envfile instead (see the envied command)."
- configuration(options, &block)
- end
-
class << self
- attr_accessor :required_groups
+ attr_reader :env, :config
end
- def self.build_configuration(&block)
- Class.new(Configuration).tap do |c|
- c.instance_eval(&block) if block_given?
- end
- end
-
def self.require(*groups)
- groups.compact!
- @instance = nil
- if groups.any?
- self.required_groups = groups.map(&:to_sym)
- else
- self.required_groups = [:default]
- end
- ensure_configured!
+ @config ||= Configuration.load
+ @env ||= EnvProxy.new(@config, groups: required_groups(*groups))
+
error_on_missing_variables!
error_on_uncoercible_variables!
-
- _required_variables = required_variables
- group_configuration = build_configuration do
- _required_variables.each do |v|
- @attribute_set << v
- end
- end
- @instance = group_configuration.new(env)
end
- def self.springified_require(*args)
- springify { ENVied.require(*args) }
- end
-
- def self.springify(&block)
- if defined?(Spring) && Spring.respond_to?(:watcher)
- Spring.after_fork(&block)
- else
- block.call
- end
- end
-
- def self.ensure_configured!
- # Backward compat: load Envfile only when it's present
- configure_via_envfile if envfile_exist?
- end
-
- def self.envfile
- File.expand_path('Envfile')
- end
-
- def self.envfile_exist?
- File.exist?(envfile)
- end
-
- def self.configure_via_envfile
- configuration { eval(File.read(ENVied.envfile)) }
- end
-
def self.error_on_missing_variables!
- if missing_variable_names.any?
- raise "Please set the following ENV-variables: #{missing_variable_names.sort.join(',')}"
- end
+ names = env.missing_variables.map(&:name)
+ raise "The following environment variables should be set: #{names * ', '}" if names.any?
end
def self.error_on_uncoercible_variables!
- # TODO default values should have defined type
- if non_coercible_variables.any?
- single_error = "ENV['%{name}'] ('%{value}' can't be coerced to %{type})"
- errors = non_coercible_variables.map do |v|
- var_type = v.type.to_s.split("::").last
- single_error % { name: v.name, value: env_value_or_default(v), type: var_type }
- end.join ", "
-
- raise "Some ENV-variables are not coercible: #{errors}"
+ errors = env.uncoercible_variables.map do |v|
+ "%{name} ('%{value}' can't be coerced to %{type})" % {name: v.name, value: env.value_to_coerce(v), type: v.type }
end
+ raise "The following environment variables are not coercible: #{errors.join(", ")}" if errors.any?
end
- def self.env_value(variable)
- env[variable.name.to_s]
+ def self.required_groups(*groups)
+ result = groups.compact
+ result.any? ? result.map(&:to_sym) : [:default]
end
- def self.env
- @env ||= begin
- Hash[ENV.to_hash.map {|k,v| [k, v.dup.extend(Hashable, Arrayable)] }]
+ def self.springify(&block)
+ if spring_enabled?
+ Spring.after_fork(&block)
+ else
+ block.call
end
end
- def self.env_value_or_default(variable)
- env_value(variable) || default_value(variable)
+ def self.spring_enabled?
+ defined?(Spring) && Spring.respond_to?(:watcher)
end
- # Yields the assigned default for the variable.
- # When defaults are disabled, nil is returned.
- def self.default_value(variable)
- defaults_enabled? ? variable.default_value.value : nil
- end
-
- # A list of all configured variable names.
- #
- # @example
- # ENVied.required_variable_names
- # # => [:DATABASE_URL]
- #
- # @return [Array<Symbol>] the list of variable names
- def self.required_variable_names
- required_variables.map(&:name).map(&:to_sym)
- end
-
- def self.required_variables
- from_required_group = ->(var){ self.required_groups.include?(var.options[:group]) }
- configured_variables.to_a.keep_if(&from_required_group)
- end
-
- def self.configured_variables
- configuration.attribute_set.dup#.to_a.keep_if(&var_from_required_group)
- end
-
- def self.provided_variable_names
- ENV.keys.map(&:to_sym)
- end
-
- def self.non_coercible_variables
- required_variables.reject(&method(:variable_coercible?))
- end
-
- def self.variable_coercible?(variable)
- var_value = env_value_or_default(variable)
- return true if var_value.respond_to?(:call)
-
- !variable.coerce(var_value).nil?
- rescue Virtus::CoercionError
- return false
- end
-
- def self.missing_variable_names
- unprovided = required_variable_names - provided_variable_names
- unprovided -= names_of_required_variables_with_defaults if defaults_enabled?
- unprovided
- end
-
- def self.names_of_required_variables_with_defaults
- required_variables_with_defaults.map(&:name).map(&:to_sym)
- end
-
- def self.required_variables_with_defaults
- required_variables.map do |v|
- v unless v.default_value.value.nil?
- end.compact
- end
-
- def self.defaults_enabled?
- configuration.enable_defaults
- end
-
def self.method_missing(method, *args, &block)
- respond_to_missing?(method) ? @instance.public_send(method, *args, &block) : super
+ respond_to_missing?(method) ? (env && env[method.to_s]) : super
end
def self.respond_to_missing?(method, include_private = false)
- @instance.respond_to?(method) || super
- end
-
- def self.deprecation_warning(msg)
- puts "DEPRECATION WARNING: #{msg}"
+ (env && env.has_key?(method)) || super
end
end