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.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/settingslogic.rb +190 -0
  3. metadata +3 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5e710432765a4074e290768ced0028a1e2274a52e18d6c84357297efdb6e2a13
4
- data.tar.gz: 33f5787dcffd7156d714828d439430f2ce256b56f396e0c340924828d581e961
3
+ metadata.gz: de00322bc80f8460d6cbe0f788cd7d990b68598c6c507ed85168e34487bb9dec
4
+ data.tar.gz: 779432a4edcad5b6cdbc585519f000a7912b20de6fb3c86ab0f76b69eb953a17
5
5
  SHA512:
6
- metadata.gz: 6250d8ac98a9e581ce9534713c06b1eab51d45d81d4a33c7577c6899e801398c3bc84c43ec3ef2f8c6729adfe03a86696aab326ed553aded4a2eb460e8536094
7
- data.tar.gz: 0652c46d8eb4ec8d84ab802ad08828353b86a91e68bbbad668904cc9de9b8f3e779b3647cad06e8b7f43345364558007e03287bac5aadffa64fe687bdb7a1a3e
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.1
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: {}