Class: Setting
Defined Under Namespace
Classes: AlreadyLoaded, FileError, NotFound
Instance Attribute Summary collapse
-
#available_settings ⇒ Object
readonly
Returns the value of attribute available_settings.
Class Method Summary collapse
-
.[](value) ⇒ Object
In [] invocation syntax, we return settings value 'as is' without Hash conversions.
-
.available_settings ⇒ Object
DEPRECATED: Please use
method accessors
instead. -
.load(args = {}) ⇒ Object
This method can be called only once.
-
.method_missing(method, *args, &block) ⇒ Object
In Method invocation syntax we collapse Hash values and return a single value if 'default' is found among keys or Hash has only one key/value pair.
- .reload(args = {}) ⇒ Object
- .respond_to?(method_name, include_private = false) ⇒ Boolean
Instance Method Summary collapse
-
#collapse_hashes(v, args) ⇒ Object
This method performs collapsing of the Hash settings values if the Hash contains 'default' value, or just 1 element.
- #has_key?(key) ⇒ Boolean
-
#initialize ⇒ Setting
constructor
Instance Methods =================================================================.
- #load(params) ⇒ Object
- #loaded? ⇒ Boolean
- #value_for(key, args = []) ⇒ Object
Constructor Details
#initialize ⇒ Setting
Instance Methods
84 85 86 |
# File 'lib/setting.rb', line 84 def initialize @available_settings ||= new_available_settings end |
Instance Attribute Details
#available_settings ⇒ Object (readonly)
Returns the value of attribute available_settings.
13 14 15 |
# File 'lib/setting.rb', line 13 def available_settings @available_settings end |
Class Method Details
.[](value) ⇒ Object
In [] invocation syntax, we return settings value 'as is' without Hash conversions.
For example, if the YML data is: tax:
default: 0.0
california: 7.5
Then calling Setting returns
{ 'default' => "0.0", 'california' => "7.5"}
71 72 73 |
# File 'lib/setting.rb', line 71 def self.[](value) self.instance.value_for(value) end |
.available_settings ⇒ Object
DEPRECATED: Please use method accessors
instead.
76 77 78 |
# File 'lib/setting.rb', line 76 def self.available_settings self.instance.available_settings end |
.load(args = {}) ⇒ Object
This method can be called only once.
Parameter hash looks like this:
{ :files => [ "file1.yml", "file2.yml", ...],
:path => "/var/www/apps/my-app/current/config/settings",
:local => true }
If :local => true is set, we will load all *.yml files under :path/local directory after all files in :files have been loaded. “Local” settings thus take precedence by design. See README for more details.
27 28 29 30 |
# File 'lib/setting.rb', line 27 def self.load(args = {}) raise AlreadyLoaded.new('Settings already loaded') if self.instance.loaded? self.instance.load(args) end |
.method_missing(method, *args, &block) ⇒ Object
In Method invocation syntax we collapse Hash values and return a single value if 'default' is found among keys or Hash has only one key/value pair.
For example, if the YML data is: tax:
default: 0.0
california: 7.5
Then calling Setting.tax returns “0.0”“
This is the preferred method of using settings class.
49 50 51 52 53 |
# File 'lib/setting.rb', line 49 def self.method_missing(method, *args, &block) self.instance.value_for(method, args) do |v, args| self.instance.collapse_hashes(v, args) end end |
.reload(args = {}) ⇒ Object
32 33 34 |
# File 'lib/setting.rb', line 32 def self.reload(args = {}) self.instance.load(args) end |
.respond_to?(method_name, include_private = false) ⇒ Boolean
55 56 57 58 |
# File 'lib/setting.rb', line 55 def self.respond_to?(method_name, include_private = false) self.instance.available_settings.has_key?(method_name.to_s.sub(/\?\z/, '')) || super end |
Instance Method Details
#collapse_hashes(v, args) ⇒ Object
This method performs collapsing of the Hash settings values if the Hash contains 'default' value, or just 1 element.
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/setting.rb', line 118 def collapse_hashes(v, args) out = if v.is_a?(Hash) if args.empty? if v.has_key?("default") v['default'].nil? ? "" : v['default'] elsif v.keys.size == 1 v.values.first else v end else v[args.shift.to_s] end else v end if out.is_a?(Hash) && !args.empty? collapse_hashes(out, args) elsif out.is_a?(Hash) && out.has_key?('default') out['default'] else out end end |
#has_key?(key) ⇒ Boolean
88 89 90 91 |
# File 'lib/setting.rb', line 88 def has_key?(key) @available_settings.has_key?(key) || (key[-1,1] == '?' && @available_settings.has_key?(key.chop)) end |
#load(params) ⇒ Object
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/setting.rb', line 147 def load(params) # reset settings hash @available_settings = new_available_settings @loaded = false files = [] path = params[:path] || Dir.pwd params[:files].each do |file| files << File.join(path, file) end if params[:local] files << Dir.glob(File.join(path, 'local', '*.yml')).sort end files.flatten.each do |file| begin # Ruby versions before 3.0.3 include Psych < 3.3.2, which does not include `unsafe_load`. In those versions, # `load` is the behavior we want (in later versions, `load` uses `safe_load`, which doesn't support aliases and # requires allowlisting classes used in files. if Psych::VERSION < '3.3.2' @available_settings.deep_merge!(YAML::load(ERB.new(IO.read(file)).result) || {}) if File.exist?(file) else @available_settings.deep_merge!(YAML::unsafe_load(ERB.new(IO.read(file)).result) || {}) if File.exist?(file) end rescue Exception => e raise FileError.new("Error parsing file #{file}, with: #{e.}") end end @loaded = true @available_settings end |
#loaded? ⇒ Boolean
143 144 145 |
# File 'lib/setting.rb', line 143 def loaded? @loaded end |
#value_for(key, args = []) ⇒ Object
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/setting.rb', line 93 def value_for(key, args = []) name = key.to_s raise NotFound.new("#{name} was not found") unless has_key?(name) bool = false if name[-1,1] == '?' name.chop! bool = true end v = @available_settings[name] if block_given? v = yield(v, args) end if v.is_a?(Integer) && bool v.to_i > 0 else v end end |