app_config 0.1.0

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.
data/README ADDED
@@ -0,0 +1,39 @@
1
+ = AppConfig
2
+
3
+ An easy to use, customizable library to easily store and retrieve application
4
+ configuration, API keys or basically anything in 'key => value' pairs.
5
+
6
+
7
+ == Usage
8
+
9
+ Usage is simple. Just pass either a hash of options, or a block, to
10
+ AppConfig.configure. See AppConfig::Base for a list of valid options.
11
+
12
+ For example, given this YAML file:
13
+
14
+ ---
15
+ admin_email: 'admin@example.com'
16
+ api_name: 'Supr Webz 2.0'
17
+ api_key: 'SUPERAWESOMESERVICE'
18
+
19
+ Use it like so:
20
+
21
+ require 'app_config'
22
+
23
+ AppConfig.configure do |config|
24
+ config.storage_method = :yaml
25
+ config.path = '/path/to/app_config.yml'
26
+ end
27
+
28
+ AppConfig[admin_email] # => 'admin@example.com'
29
+ AppConfig[:api_name] # => 'Supr Webz 2.0'
30
+ AppConfig[:api_key] # => 'SUPERAWESOMESERVICE'
31
+
32
+ Want SQLite3 support? No problem!
33
+
34
+ AppConfig.configure do |config|
35
+ config.storage_method = :sqlite
36
+ config.database = '/path/to/database.sqlite3'
37
+ end
38
+
39
+ AppConfig[:column] # => 'value'
@@ -0,0 +1,77 @@
1
+ require 'spec/rake/spectask'
2
+
3
+ task :default => [:spec]
4
+
5
+ desc 'Start an irb session with AppConfig loaded'
6
+ task :console do
7
+ sh "irb -I ./lib -r 'app_config'"
8
+ end
9
+
10
+ desc 'Run the specs with autotest'
11
+ task :autotest do
12
+ ENV['RSPEC'] = 'true'
13
+ sh 'autotest'
14
+ end
15
+
16
+ desc 'Run all specs in spec directory'
17
+ Spec::Rake::SpecTask.new(:spec) do |t|
18
+ t.spec_opts = ['--options', 'spec/spec.opts']
19
+ t.spec_files = FileList['spec/**/*_spec.rb']
20
+ end
21
+
22
+ desc 'Run all specs in spec directory with RCov'
23
+ Spec::Rake::SpecTask.new(:rcov) do |t|
24
+ t.spec_opts = ['--options', 'spec/spec.opts']
25
+ t.spec_files = FileList['spec/**/*_spec.rb']
26
+ t.rcov = true
27
+ t.rcov_opts = lambda do
28
+ IO.readlines('spec/rcov.opts').map {|l| l.chomp.split ' '}.flatten
29
+ end
30
+ end
31
+
32
+ desc 'Generate API documentation'
33
+ task :doc do
34
+ Rake::Task['doc:api'].invoke
35
+ end
36
+
37
+ namespace :doc do
38
+ task :setup_rdoc do
39
+ @file_list = FileList[ "#{File.dirname(__FILE__)}/README",
40
+ "#{File.dirname(__FILE__)}/lib/**/*.rb" ]
41
+ # Substitute APP_ROOT with a dot. Makes for a better index in the generated docs.
42
+ @files = @file_list.collect {|f| f.gsub(/#{File.dirname(__FILE__)}/, '.')}
43
+ @options = %W[
44
+ --all
45
+ --inline-source
46
+ --line-numbers
47
+ --main README
48
+ --op #{File.join(File.dirname(__FILE__), 'doc', 'api')}
49
+ --title 'AppConfig API Documentation'
50
+ ]
51
+ # Generate a diagram, yes/no?
52
+ @options << '-d' if RUBY_PLATFORM !~ /win32/ && `which dot` =~ /\/dot/ && !ENV['NODOT']
53
+ end
54
+
55
+ task :api => [:setup_rdoc] do
56
+ run_rdoc(@options, @files)
57
+ end
58
+
59
+ desc 'Remove generated API documentation'
60
+ task :clear do
61
+ system("rm -rf #{File.dirname(__FILE__) + '/doc/api'}")
62
+ end
63
+
64
+ desc 'Rebuild API documentation'
65
+ task :rebuild do
66
+ Rake::Task['doc:clear'].invoke
67
+ Rake::Task['doc:api'].invoke
68
+ end
69
+ end
70
+
71
+ private
72
+
73
+ def run_rdoc(options, files)
74
+ options = options.join(' ') if options.is_a? Array
75
+ files = files.join(' ') if files.is_a? Array
76
+ system("rdoc #{options} #{files}")
77
+ end
@@ -0,0 +1,30 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__)
2
+
3
+ require 'yaml'
4
+
5
+ require 'core_ext/hashish'
6
+
7
+ module AppConfig
8
+ VERSION = '0.1.0'
9
+
10
+ autoload :Base, 'app_config/base'
11
+ autoload :Storage, 'app_config/storage'
12
+
13
+ def self.to_version
14
+ "#{self.class} v#{VERSION}"
15
+ end
16
+
17
+ # Access the configured <tt>key</tt>'s value.
18
+ def self.[](key)
19
+ error = "Must call '#{self}.configure' to setup storage!"
20
+ raise error if @@storage.nil?
21
+ @@storage[key]
22
+ end
23
+
24
+ # Accepts an +options+ hash or pass a block.
25
+ # See AppConfig::Base for valid options.
26
+ def self.configure(options = {}, &block)
27
+ @@storage = AppConfig::Base.new(options, &block)
28
+ end
29
+
30
+ end
@@ -0,0 +1,51 @@
1
+ module AppConfig
2
+
3
+ # The Base storage class.
4
+ # Acts as a wrapper for the different storage methods.
5
+ #
6
+ # See each storage method's documentation for their specific options.
7
+ class Base
8
+
9
+ attr_accessor :storage_method, :path
10
+
11
+ DEFAULTS = {
12
+ :storage_method => :yaml,
13
+ :path => File.expand_path(File.join(ENV['HOME'], '.app_config.yml'))
14
+ }
15
+
16
+ # Accepts either a hash of +options+ or a block (which overrides
17
+ # any options passed in the hash).
18
+ #
19
+ # Valid storage methods:
20
+ # * :sqlite
21
+ # * :yaml
22
+ def initialize(options = {}, &block)
23
+ DEFAULTS.merge(options).each_pair do |key, value|
24
+ self.send("#{ key }=", value)
25
+ end
26
+ yield self if block_given?
27
+ @storage = initialize_storage
28
+ end
29
+
30
+ # Access the <tt>key</tt>'s value in @storage.
31
+ def [](key)
32
+ @storage[key]
33
+ end
34
+
35
+ private
36
+
37
+ # This decides how to load the data, based on the +storage_method+.
38
+ def initialize_storage
39
+ case storage_method
40
+ when :sqlite
41
+ # TODO: Initialize SQLite3 storage.
42
+ when :yaml
43
+ AppConfig::Storage::Yaml.load(path)
44
+ else
45
+ raise 'Unknown storage method.'
46
+ end
47
+ end
48
+
49
+ end # Base
50
+
51
+ end # AppConfig
@@ -0,0 +1,5 @@
1
+ module AppConfig
2
+ module Storage
3
+ autoload :Yaml, 'app_config/storage/yaml'
4
+ end
5
+ end
@@ -0,0 +1,23 @@
1
+ module AppConfig
2
+ module Storage
3
+
4
+ # YAML storage method.
5
+ class Yaml
6
+ attr_reader :data
7
+
8
+ # Loads @data with the YAML file located at +path+.
9
+ #
10
+ # Defaults to $HOME/.app_config.yml
11
+ def initialize(path)
12
+ @data = Hashish.new(YAML.load_file(path))
13
+ end
14
+
15
+ # Creates a new Yaml storage with the given +path+ and returns the data.
16
+ def self.load(path)
17
+ new(path).data
18
+ end
19
+
20
+ end # Yaml
21
+
22
+ end # Storage
23
+ end # AppConfig
@@ -0,0 +1,124 @@
1
+ # Stolen from Rails Active Support 2.3.0 and renamed to Hashish.
2
+ #
3
+ # This class has dubious semantics and we only have it so that
4
+ # people can write params[:key] instead of params['key']
5
+ # and they get the same value for both keys.
6
+ class Hashish < Hash
7
+ def initialize(constructor = {})
8
+ if constructor.is_a?(Hash)
9
+ super()
10
+ update(constructor)
11
+ else
12
+ super(constructor)
13
+ end
14
+ end
15
+
16
+ def default(key = nil)
17
+ if key.is_a?(Symbol) && include?(key = key.to_s)
18
+ self[key]
19
+ else
20
+ super
21
+ end
22
+ end
23
+
24
+ alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
25
+ alias_method :regular_update, :update unless method_defined?(:regular_update)
26
+
27
+ # Assigns a new value to the hash:
28
+ #
29
+ # hash = HashWithIndifferentAccess.new
30
+ # hash[:key] = "value"
31
+ #
32
+ def []=(key, value)
33
+ regular_writer(convert_key(key), convert_value(value))
34
+ end
35
+
36
+ # Updates the instantized hash with values from the second:
37
+ #
38
+ # hash_1 = HashWithIndifferentAccess.new
39
+ # hash_1[:key] = "value"
40
+ #
41
+ # hash_2 = HashWithIndifferentAccess.new
42
+ # hash_2[:key] = "New Value!"
43
+ #
44
+ # hash_1.update(hash_2) # => {"key"=>"New Value!"}
45
+ #
46
+ def update(other_hash)
47
+ other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
48
+ self
49
+ end
50
+
51
+ alias_method :merge!, :update
52
+
53
+ # Checks the hash for a key matching the argument passed in:
54
+ #
55
+ # hash = HashWithIndifferentAccess.new
56
+ # hash["key"] = "value"
57
+ # hash.key? :key # => true
58
+ # hash.key? "key" # => true
59
+ #
60
+ def key?(key)
61
+ super(convert_key(key))
62
+ end
63
+
64
+ alias_method :include?, :key?
65
+ alias_method :has_key?, :key?
66
+ alias_method :member?, :key?
67
+
68
+ # Fetches the value for the specified key, same as doing hash[key]
69
+ def fetch(key, *extras)
70
+ super(convert_key(key), *extras)
71
+ end
72
+
73
+ # Returns an array of the values at the specified indices:
74
+ #
75
+ # hash = HashWithIndifferentAccess.new
76
+ # hash[:a] = "x"
77
+ # hash[:b] = "y"
78
+ # hash.values_at("a", "b") # => ["x", "y"]
79
+ #
80
+ def values_at(*indices)
81
+ indices.collect {|key| self[convert_key(key)]}
82
+ end
83
+
84
+ # Returns an exact copy of the hash.
85
+ def dup
86
+ HashWithIndifferentAccess.new(self)
87
+ end
88
+
89
+ # Merges the instantized and the specified hashes together, giving precedence to the values from the second hash
90
+ # Does not overwrite the existing hash.
91
+ def merge(hash)
92
+ self.dup.update(hash)
93
+ end
94
+
95
+ # Removes a specified key from the hash.
96
+ def delete(key)
97
+ super(convert_key(key))
98
+ end
99
+
100
+ def stringify_keys!; self end
101
+ def symbolize_keys!; self end
102
+ def to_options!; self end
103
+
104
+ # Convert to a Hash with String keys.
105
+ def to_hash
106
+ Hash.new(default).merge(self)
107
+ end
108
+
109
+ protected
110
+ def convert_key(key)
111
+ key.kind_of?(Symbol) ? key.to_s : key
112
+ end
113
+
114
+ def convert_value(value)
115
+ case value
116
+ when Hash
117
+ value.with_indifferent_access
118
+ when Array
119
+ value.collect { |e| e.is_a?(Hash) ? e.with_indifferent_access : e }
120
+ else
121
+ value
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,20 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Base do
4
+
5
+ it 'should raise error on unknown option' do
6
+ lambda do
7
+ Base.new(:unknown => 'option')
8
+ end.should raise_error(NoMethodError)
9
+ end
10
+
11
+ it 'should have default options' do
12
+ default_path = File.expand_path(File.join(ENV['HOME'], '.app_config.yml'))
13
+ # mock up the YAML stuff, so it won't puke
14
+ YAML.should_receive(:load_file).with(default_path).and_return({:api => 'key'})
15
+ base = Base.new
16
+ base.storage_method.should == :yaml
17
+ base.path.should == default_path
18
+ end
19
+
20
+ end
@@ -0,0 +1,17 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ include AppConfig::Storage
4
+ describe Yaml do
5
+
6
+ it 'should have some values' do
7
+ config_for_yaml
8
+ AppConfig[:api_key].should_not be_nil
9
+ end
10
+
11
+ it 'should raise file not found' do
12
+ lambda do
13
+ config_for_yaml(:path => 'not/a/real/file.yml')
14
+ end.should raise_error(Errno::ENOENT)
15
+ end
16
+
17
+ end
@@ -0,0 +1,7 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe AppConfig do
4
+ it 'should have a version' do
5
+ AppConfig.to_version.should_not be_nil
6
+ end
7
+ end
@@ -0,0 +1,18 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Hashish do
4
+ before(:each) do
5
+ @strings = { 'key' => 'value', 'four' => 20 }
6
+ @symbols = { :key => 'value', :four => 20 }
7
+ end
8
+
9
+ it 'should not give a fuck about symbols' do
10
+ hashish = Hashish.new(@strings)
11
+ hashish[:key].should == 'value'
12
+ end
13
+
14
+ it 'should not give a fuck about strings' do
15
+ hashish = Hashish.new(@symbols)
16
+ hashish['key'].should == 'value'
17
+ end
18
+ end
@@ -0,0 +1,4 @@
1
+ ---
2
+ admin_email: 'admin@example.com'
3
+ api_name: 'Supr Webz 2.0'
4
+ api_key: 'SUPERAWESOMESERVICE'
@@ -0,0 +1 @@
1
+ --exclude "spec/*,gems/*"
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --format progress
3
+ --loadby mtime
4
+ --reverse
@@ -0,0 +1,17 @@
1
+ require 'spec'
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/app_config')
4
+
5
+ Spec::Runner.configure do |config|
6
+ include AppConfig
7
+ end
8
+
9
+ FIXTURE = File.expand_path(File.dirname(__FILE__) + '/fixtures/app_config.yml')
10
+ def config_for_yaml(opts = {})
11
+ path = opts[:path] || FIXTURE
12
+ @yaml = {
13
+ :storage_method => :yaml,
14
+ :path => path,
15
+ }
16
+ AppConfig.configure(@yaml.merge(opts))
17
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: app_config
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Dale Campbell
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-03-13 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: An easy to use, customizable library to easily store and retrieve application configuration
17
+ email:
18
+ - dale@save-state.net
19
+ executables: []
20
+
21
+ extensions: []
22
+
23
+ extra_rdoc_files: []
24
+
25
+ files:
26
+ - README
27
+ - Rakefile
28
+ - lib/app_config/base.rb
29
+ - lib/app_config/storage/yaml.rb
30
+ - lib/app_config/storage.rb
31
+ - lib/app_config.rb
32
+ - lib/core_ext/hashish.rb
33
+ - spec/app_config
34
+ - spec/app_config/base_spec.rb
35
+ - spec/app_config/storage
36
+ - spec/app_config/storage/yaml_spec.rb
37
+ - spec/app_config_spec.rb
38
+ - spec/core_ext
39
+ - spec/core_ext/hashish_spec.rb
40
+ - spec/fixtures
41
+ - spec/fixtures/app_config.yml
42
+ - spec/rcov.opts
43
+ - spec/spec.opts
44
+ - spec/spec_helper.rb
45
+ has_rdoc: false
46
+ homepage: http://oshuma.github.com/app_config
47
+ post_install_message:
48
+ rdoc_options: []
49
+
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: "0"
63
+ version:
64
+ requirements: []
65
+
66
+ rubyforge_project:
67
+ rubygems_version: 1.3.1
68
+ signing_key:
69
+ specification_version: 2
70
+ summary: Quick and easy application configuration.
71
+ test_files: []
72
+