mysettingslogic 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/settingslogic.rb +190 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: de00322bc80f8460d6cbe0f788cd7d990b68598c6c507ed85168e34487bb9dec
|
4
|
+
data.tar.gz: 779432a4edcad5b6cdbc585519f000a7912b20de6fb3c86ab0f76b69eb953a17
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2f70ec6e332ada01cf3efad8bee20e4299bc6ef9c30e285c851fbd8c3c6bbdcd29ddbd420811d2dce5f4cb63694018f203bd5892bfb80ea51f410cd4b5928886
|
7
|
+
data.tar.gz: f1a5dd630886966efd19eefdada7f06123d3ebd0bf75694c25a2a47bdcaa57aaf8ee856fec71fa15ad1f562fa4fd921d4be9278f5879794598d40cc4922716f7
|
@@ -0,0 +1,190 @@
|
|
1
|
+
require "yaml"
|
2
|
+
require "erb"
|
3
|
+
require 'open-uri'
|
4
|
+
|
5
|
+
# A simple settings solution using a YAML file. See README for more information.
|
6
|
+
class Settingslogic < Hash
|
7
|
+
class MissingSetting < StandardError; end
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def name # :nodoc:
|
11
|
+
self.superclass != Hash && instance.key?("name") ? instance.name : super
|
12
|
+
end
|
13
|
+
# Enables Settings.get('nested.key.name') for dynamic access
|
14
|
+
def get(key)
|
15
|
+
parts = key.split('.')
|
16
|
+
curs = self
|
17
|
+
while p = parts.shift
|
18
|
+
curs = curs.send(p)
|
19
|
+
end
|
20
|
+
curs
|
21
|
+
end
|
22
|
+
|
23
|
+
def source(value = nil)
|
24
|
+
@source ||= value
|
25
|
+
end
|
26
|
+
|
27
|
+
def namespace(value = nil)
|
28
|
+
@namespace ||= value
|
29
|
+
end
|
30
|
+
|
31
|
+
def suppress_errors(value = nil)
|
32
|
+
@suppress_errors ||= value
|
33
|
+
end
|
34
|
+
|
35
|
+
def [](key)
|
36
|
+
instance.fetch(key.to_s, nil)
|
37
|
+
end
|
38
|
+
|
39
|
+
def []=(key, val)
|
40
|
+
# Setting[:key][:key2] = 'value' for dynamic settings
|
41
|
+
val = new(val, source) if val.is_a? Hash
|
42
|
+
instance.store(key.to_s, val)
|
43
|
+
instance.create_accessor_for(key, val)
|
44
|
+
end
|
45
|
+
|
46
|
+
def load!
|
47
|
+
instance
|
48
|
+
true
|
49
|
+
end
|
50
|
+
|
51
|
+
def reload!
|
52
|
+
@instance = nil
|
53
|
+
load!
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
def instance
|
58
|
+
return @instance if @instance
|
59
|
+
@instance = new
|
60
|
+
create_accessors!
|
61
|
+
@instance
|
62
|
+
end
|
63
|
+
|
64
|
+
def method_missing(name, *args, &block)
|
65
|
+
instance.send(name, *args, &block)
|
66
|
+
end
|
67
|
+
|
68
|
+
# It would be great to DRY this up somehow, someday, but it's difficult because
|
69
|
+
# of the singleton pattern. Basically this proxies Setting.foo to Setting.instance.foo
|
70
|
+
def create_accessors!
|
71
|
+
instance.each do |key,val|
|
72
|
+
create_accessor_for(key)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def create_accessor_for(key)
|
77
|
+
return unless key.to_s =~ /^\w+$/ # could have "some-setting:" which blows up eval
|
78
|
+
instance_eval "def #{key}; instance.send(:#{key}); end"
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
# Initializes a new settings object. You can initialize an object in any of the following ways:
|
84
|
+
#
|
85
|
+
# Settings.new(:application) # will look for config/application.yml
|
86
|
+
# Settings.new("application.yaml") # will look for application.yaml
|
87
|
+
# Settings.new("/var/configs/application.yml") # will look for /var/configs/application.yml
|
88
|
+
# Settings.new(:config1 => 1, :config2 => 2)
|
89
|
+
#
|
90
|
+
# Basically if you pass a symbol it will look for that file in the configs directory of your rails app,
|
91
|
+
# if you are using this in rails. If you pass a string it should be an absolute path to your settings file.
|
92
|
+
# Then you can pass a hash, and it just allows you to access the hash via methods.
|
93
|
+
def initialize(hash_or_file = self.class.source, section = nil)
|
94
|
+
#puts "new! #{hash_or_file}"
|
95
|
+
case hash_or_file
|
96
|
+
when nil
|
97
|
+
raise Errno::ENOENT, "No file specified as Settingslogic source"
|
98
|
+
when Hash
|
99
|
+
self.replace hash_or_file
|
100
|
+
else
|
101
|
+
file_contents = open(hash_or_file).read
|
102
|
+
hash = file_contents.empty? ? {} : YAML.load(ERB.new(file_contents).result, aliases:true).to_hash
|
103
|
+
if self.class.namespace
|
104
|
+
hash = hash[self.class.namespace] or return missing_key("Missing setting '#{self.class.namespace}' in #{hash_or_file}")
|
105
|
+
end
|
106
|
+
self.replace hash
|
107
|
+
end
|
108
|
+
@section = section || self.class.source # so end of error says "in application.yml"
|
109
|
+
create_accessors!
|
110
|
+
end
|
111
|
+
|
112
|
+
# Called for dynamically-defined keys, and also the first key deferenced at the top-level, if load! is not used.
|
113
|
+
# Otherwise, create_accessors! (called by new) will have created actual methods for each key.
|
114
|
+
def method_missing(name, *args, &block)
|
115
|
+
key = name.to_s
|
116
|
+
return missing_key("Missing setting '#{key}' in #{@section}") unless has_key? key
|
117
|
+
value = fetch(key)
|
118
|
+
create_accessor_for(key)
|
119
|
+
value.is_a?(Hash) ? self.class.new(value, "'#{key}' section in #{@section}") : value
|
120
|
+
end
|
121
|
+
|
122
|
+
def [](key)
|
123
|
+
fetch(key.to_s, nil)
|
124
|
+
end
|
125
|
+
|
126
|
+
def []=(key,val)
|
127
|
+
# Setting[:key][:key2] = 'value' for dynamic settings
|
128
|
+
val = self.class.new(val, @section) if val.is_a? Hash
|
129
|
+
store(key.to_s, val)
|
130
|
+
create_accessor_for(key, val)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Returns an instance of a Hash object
|
134
|
+
def to_hash
|
135
|
+
Hash[self]
|
136
|
+
end
|
137
|
+
|
138
|
+
# This handles naming collisions with Sinatra/Vlad/Capistrano. Since these use a set()
|
139
|
+
# helper that defines methods in Object, ANY method_missing ANYWHERE picks up the Vlad/Sinatra
|
140
|
+
# settings! So settings.deploy_to title actually calls Object.deploy_to (from set :deploy_to, "host"),
|
141
|
+
# rather than the app_yml['deploy_to'] hash. Jeezus.
|
142
|
+
def create_accessors!
|
143
|
+
self.each do |key,val|
|
144
|
+
create_accessor_for(key)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# Use instance_eval/class_eval because they're actually more efficient than define_method{}
|
149
|
+
# http://stackoverflow.com/questions/185947/ruby-definemethod-vs-def
|
150
|
+
# http://bmorearty.wordpress.com/2009/01/09/fun-with-rubys-instance_eval-and-class_eval/
|
151
|
+
def create_accessor_for(key, val=nil)
|
152
|
+
return unless key.to_s =~ /^\w+$/ # could have "some-setting:" which blows up eval
|
153
|
+
instance_variable_set("@#{key}", val)
|
154
|
+
self.class.class_eval <<-EndEval
|
155
|
+
def #{key}
|
156
|
+
return @#{key} if @#{key}
|
157
|
+
return missing_key("Missing setting '#{key}' in #{@section}") unless has_key? '#{key}'
|
158
|
+
value = fetch('#{key}')
|
159
|
+
@#{key} = if value.is_a?(Hash)
|
160
|
+
self.class.new(value, "'#{key}' section in #{@section}")
|
161
|
+
elsif value.is_a?(Array) && value.all?{|v| v.is_a? Hash}
|
162
|
+
value.map{|v| self.class.new(v)}
|
163
|
+
else
|
164
|
+
value
|
165
|
+
end
|
166
|
+
end
|
167
|
+
EndEval
|
168
|
+
end
|
169
|
+
|
170
|
+
def symbolize_keys
|
171
|
+
|
172
|
+
inject({}) do |memo, tuple|
|
173
|
+
|
174
|
+
k = (tuple.first.to_sym rescue tuple.first) || tuple.first
|
175
|
+
|
176
|
+
v = k.is_a?(Symbol) ? send(k) : tuple.last # make sure the value is accessed the same way Settings.foo.bar works
|
177
|
+
|
178
|
+
memo[k] = v && v.respond_to?(:symbolize_keys) ? v.symbolize_keys : v #recurse for nested hashes
|
179
|
+
|
180
|
+
memo
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
|
185
|
+
def missing_key(msg)
|
186
|
+
return nil if self.class.suppress_errors
|
187
|
+
|
188
|
+
raise MissingSetting, msg
|
189
|
+
end
|
190
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mysettingslogic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Johnson
|
@@ -45,7 +45,8 @@ email:
|
|
45
45
|
executables: []
|
46
46
|
extensions: []
|
47
47
|
extra_rdoc_files: []
|
48
|
-
files:
|
48
|
+
files:
|
49
|
+
- lib/settingslogic.rb
|
49
50
|
homepage: ''
|
50
51
|
licenses: []
|
51
52
|
metadata: {}
|