app_config 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
+