settings 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2009 Ben Alavi for Citrusbyte
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,83 @@
1
+ Settings
2
+ ========
3
+
4
+ A special hash for application-wide settings.
5
+
6
+ Description
7
+ -----------
8
+
9
+ Small and simple specialized Hash which is helpful for storing immutable,
10
+ required key/value pairs to be loaded from a YAML file.
11
+
12
+ New instances of `SettingsHash` are readonly -- any attempt to write to the
13
+ Hash after initialization will fail with a `TypeError`.
14
+
15
+ Any attempt to read a key which is not set will raise a
16
+ `SettingsHash::SettingNotFound` error.
17
+
18
+ `SettingsHash` supports an optional namespace which can be used to define
19
+ multiple groups of settings within a single .yml file. For example, "test" and
20
+ "development" might be different namespaces for different running environments.
21
+
22
+ Usage
23
+ -----
24
+
25
+ ### General
26
+
27
+ settings = SettingsHash.new('path/to/settings.yml')
28
+ settings = SettingsHash.new('path/to/settings.yml', 'foo') => loads settings under the 'foo' namespace
29
+
30
+ ### Rails
31
+
32
+ Put your environment-specific `settings.yml` in `config/settings.yml`. It may
33
+ look something like this:
34
+
35
+ development:
36
+ memcached: true
37
+ test:
38
+ memcached: false
39
+
40
+ This file will automatically be loaded into a `Settings` global which can be
41
+ accessed like a normal Hash:
42
+
43
+ Settings[:memcached] => true (development environment)
44
+ Settings[:memcached] => false (test environment)
45
+
46
+ Installation
47
+ ------------
48
+
49
+ $ gem sources -a http://gems.github.com (you only have to do this once)
50
+ $ sudo gem install citrusbyte-settings
51
+
52
+ Testing
53
+ -------
54
+
55
+ Tests require Contest gem:
56
+
57
+ http://github.com/citrusbyte/contest
58
+
59
+ License
60
+ -------
61
+
62
+ Copyright (c) 2009 Ben Alavi for Citrusbyte
63
+
64
+ Permission is hereby granted, free of charge, to any person
65
+ obtaining a copy of this software and associated documentation
66
+ files (the "Software"), to deal in the Software without
67
+ restriction, including without limitation the rights to use,
68
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
69
+ copies of the Software, and to permit persons to whom the
70
+ Software is furnished to do so, subject to the following
71
+ conditions:
72
+
73
+ The above copyright notice and this permission notice shall be
74
+ included in all copies or substantial portions of the Software.
75
+
76
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
77
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
78
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
79
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
80
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
81
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
82
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
83
+ OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,35 @@
1
+ require 'rake'
2
+ require 'rake/gempackagetask'
3
+ require 'rake/testtask'
4
+ require 'rake/clean'
5
+
6
+ gem_spec_file = 'settings.gemspec'
7
+
8
+ gem_spec = eval(File.read(gem_spec_file)) rescue nil
9
+
10
+ task :default => :test
11
+
12
+ Rake::TestTask.new(:test) do |t|
13
+ t.pattern = 'test/**/*_test.rb'
14
+ t.verbose = false
15
+ end
16
+
17
+ Rake::GemPackageTask.new(gem_spec) do |pkg|
18
+ pkg.need_zip = false
19
+ pkg.need_tar = false
20
+ rm_f FileList['pkg/**/*.*']
21
+ end if gem_spec
22
+
23
+ desc "Generate the gemspec file."
24
+ task :gemspec do
25
+ require 'erb'
26
+
27
+ File.open(gem_spec_file, 'w') do |f|
28
+ f.write ERB.new(File.read("#{gem_spec_file}.erb")).result(binding)
29
+ end
30
+ end
31
+
32
+ desc "Builds and installs the gem."
33
+ task :install => :repackage do
34
+ `sudo gem install pkg/#{gem_spec.name}-#{gem_spec.version}.gem`
35
+ end
data/lib/settings.rb ADDED
@@ -0,0 +1,9 @@
1
+ # Rails-specific initialization, only here because if you try to set a global
2
+ # constant in init.rb it gets removed, but if you require a file that sets a
3
+ # global constant it seems to work -- not sure why?
4
+ #
5
+ # Also, Rails gem-dependencies expect a file with the name of the gem in lib
6
+ # that defines a constant with the same name -- hence we have to file called
7
+ # settings.rb which defines Settings for Rails to be happy =)
8
+ require 'settings_hash'
9
+ Settings = SettingsHash.new(File.join(Rails.root, 'config', 'settings.yml'), Rails.env)
@@ -0,0 +1,60 @@
1
+ require 'yaml'
2
+
3
+ class Hash
4
+ # From ActiveSupport lib/active_support/core_ext/hash/keys.rb line 22-27
5
+ # Altered to recursively symbolize all keys in nested hashes
6
+ def symbolize_keys
7
+ inject({}) do |options, (key, value)|
8
+ options[(key.to_sym rescue key) || key] = (value.is_a?(Hash) ? value.symbolize_keys : value)
9
+ options
10
+ end
11
+ end
12
+ end
13
+
14
+ # A very simple "readonly" hash implementation. Freezes itselfs on
15
+ # initialization so that any attempts to change will result in a TypeError
16
+ class ReadonlyHash < Hash
17
+ class << self
18
+ def [](*args)
19
+ new(super(*args))
20
+ end
21
+ end
22
+
23
+ def initialize(hash)
24
+ update hash
25
+ freeze
26
+ end
27
+ end
28
+
29
+ class SettingsHash < ReadonlyHash
30
+ # Raised when attempting to access a key which has not been set.
31
+ class SettingNotFound < StandardError;end;
32
+
33
+ # Creates a new SettingsHash from a YAML file located at the given path.
34
+ #
35
+ # Optionally loads only the settings within the given namespace (if a
36
+ # namespace is given)
37
+ #
38
+ # SettingsHash.new('/path/to/settings.yml') => { :foo => { :bar => 'baz' }, :bam => 'bang' }
39
+ # SettingsHash.new('/path/to/settings.yml, 'foo') => { :bar => 'baz' }
40
+ #
41
+ # Note that hash keys are symbolized (as seen in example above)
42
+ def initialize(path, namespace=nil)
43
+ raise "No settings file found: #{path}" unless File.exists?(path)
44
+ settings = YAML.load_file(path)
45
+
46
+ if namespace
47
+ raise "No settings defined for #{namespace} in settings file: #{path}" unless settings[namespace]
48
+ settings = settings[namespace]
49
+ end
50
+
51
+ super(settings.symbolize_keys)
52
+ end
53
+
54
+ # Access the value at the given key, raises SettingsHash::SettingNotFound if
55
+ # the key is not set.
56
+ def [](key)
57
+ raise SettingNotFound.new("No setting found for #{key}") unless has_key?(key)
58
+ super
59
+ end
60
+ end
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'settings'
File without changes
@@ -0,0 +1 @@
1
+ baz: bang
@@ -0,0 +1,4 @@
1
+ test:
2
+ foo: bar
3
+ abc:
4
+ def: 123
@@ -0,0 +1,80 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require 'contest'
4
+ require File.dirname(__FILE__) + "/../lib/settings_hash"
5
+
6
+ def fixture_path
7
+ File.join(File.dirname(__FILE__), 'fixtures')
8
+ end
9
+
10
+ class SettingsTest < Test::Unit::TestCase
11
+ context "settings file exists" do
12
+ context "and has values" do
13
+ context "in test namespace" do
14
+ context "and namespace exists" do
15
+ setup do
16
+ @settings = SettingsHash.new(File.join(fixture_path, 'settings.yml'), 'test')
17
+ end
18
+
19
+ should "return hash of settings" do
20
+ assert @settings.is_a?(SettingsHash)
21
+ end
22
+
23
+ should "symbolize keys" do
24
+ assert @settings.has_key?(:foo)
25
+ end
26
+
27
+ should "symbolize nested keys" do
28
+ assert @settings[:abc].has_key?(:def)
29
+ end
30
+
31
+ should "set nested values" do
32
+ assert_equal 123, @settings[:abc][:def]
33
+ end
34
+
35
+ should "have bar for :foo" do
36
+ assert_equal 'bar', @settings[:foo]
37
+ end
38
+
39
+ should "freeze settings" do
40
+ assert_raise TypeError do
41
+ @settings[:foo] = 'baz'
42
+ end
43
+ end
44
+
45
+ should "return value for key if set" do
46
+ assert_equal 'bar', @settings[:foo]
47
+ end
48
+
49
+ should "raise if key is not set" do
50
+ assert_raise SettingsHash::SettingNotFound do
51
+ @settings[:bar]
52
+ end
53
+ end
54
+ end
55
+
56
+ context "and namespace doesnt exist" do
57
+ should "raise" do
58
+ assert_raise RuntimeError do
59
+ SettingsHash.new(File.join(fixture_path, 'settings.yml'), 'foo')
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ context "outside of test namespace" do
66
+ should "return hash of settings" do
67
+ assert_equal({ :baz => 'bang' }, SettingsHash.new(File.join(fixture_path, 'no_namespace.yml')))
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ context "settings file doesnt exist" do
74
+ should "raise" do
75
+ assert_raise RuntimeError do
76
+ SettingsHash.new(File.join(fixture_path, 'missing.yml'))
77
+ end
78
+ end
79
+ end
80
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: settings
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Ben Alavi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-04-25 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Small and simple specialized Hash which is helpful for storing immutable, required key/value pairs to be loaded from a YAML file.
17
+ email: ben.alavi@citrusbyte.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - lib/settings.rb
26
+ - lib/settings_hash.rb
27
+ - README.markdown
28
+ - LICENSE
29
+ - Rakefile
30
+ - rails/init.rb
31
+ - test/fixtures/empty.yml
32
+ - test/fixtures/no_namespace.yml
33
+ - test/fixtures/settings.yml
34
+ - test/settings_test.rb
35
+ has_rdoc: true
36
+ homepage: http://labs.citrusbyte.com/projects/settings
37
+ licenses: []
38
+
39
+ post_install_message:
40
+ rdoc_options: []
41
+
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: "0"
49
+ version:
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ requirements: []
57
+
58
+ rubyforge_project: settings
59
+ rubygems_version: 1.3.4
60
+ signing_key:
61
+ specification_version: 3
62
+ summary: A special hash for application-wide settings
63
+ test_files: []
64
+