app_config 0.4.1 → 0.5.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.
data/Rakefile CHANGED
@@ -1,8 +1,8 @@
1
- require 'spec/rake/spectask'
1
+ require 'rspec/core/rake_task'
2
2
 
3
3
  FileList[File.dirname(__FILE__) + '/tasks/**/*.rake'].each { |task| load task }
4
4
 
5
- task :default => [:spec]
5
+ task :default => :spec
6
6
 
7
7
  desc 'Start an irb session with AppConfig loaded'
8
8
  task :console do
@@ -4,30 +4,47 @@ $LOAD_PATH.unshift File.dirname(__FILE__)
4
4
  require 'core_ext/hashish'
5
5
 
6
6
  module AppConfig
7
- VERSION = '0.4.1'
7
+ VERSION = '0.5.2'
8
8
 
9
9
  autoload :Base, 'app_config/base'
10
10
  autoload :Error, 'app_config/error'
11
11
  autoload :Storage, 'app_config/storage'
12
12
 
13
- # Returns the AppConfig version string.
14
- def self.to_version
15
- "#{self.name} v#{VERSION}"
16
- end
13
+ class << self
17
14
 
18
- # Access the configured <tt>key</tt>'s value.
19
- def self.[](key)
20
- @@storage[key]
21
- end
15
+ # Accepts an +options+ hash or a block.
16
+ # See AppConfig::Base for valid storage methods.
17
+ def setup(options = {}, &block)
18
+ @@storage = AppConfig::Base.new(options, &block)
19
+ end
22
20
 
23
- # Accepts an +options+ hash or a block.
24
- # See AppConfig::Base for valid storage methods.
25
- def self.setup(options = {}, &block)
26
- @@storage = AppConfig::Base.new(options, &block)
27
- end
21
+ # Clears the <tt>@@storage</tt>.
22
+ def reset!
23
+ @@storage = nil if defined?(@@storage)
24
+ end
28
25
 
29
- def self.to_hash
30
- @@storage.to_hash
31
- end
26
+ # Access the configured <tt>key</tt>'s value.
27
+ def [](key)
28
+ validate!
29
+ @@storage[key]
30
+ end
32
31
 
32
+ # Set a new <tt>value</tt> for <tt>key</tt> (persistence depends on the type of Storage).
33
+ def []=(key, value)
34
+ validate!
35
+ @@storage[key] = value
36
+ end
37
+
38
+ def to_hash
39
+ validate!
40
+ @@storage.to_hash
41
+ end
42
+
43
+ private
44
+
45
+ def validate!
46
+ raise AppConfig::Error::NotSetup unless defined?(@@storage) && @@storage
47
+ end
48
+
49
+ end # self
33
50
  end # AppConfig
@@ -30,7 +30,19 @@ module AppConfig
30
30
 
31
31
  # Access the <tt>key</tt>'s value in storage.
32
32
  def [](key)
33
- storage[key]
33
+ if storage.respond_to?(:[])
34
+ storage[key]
35
+ else
36
+ raise AppConfig::Error::MustOverride.new('#[]')
37
+ end
38
+ end
39
+
40
+ def []=(key, value)
41
+ if storage.respond_to?(:[]=)
42
+ storage[key] = value
43
+ else
44
+ raise AppConfig::Error::MustOverride.new('#[]=')
45
+ end
34
46
  end
35
47
 
36
48
  def environment
@@ -74,7 +86,7 @@ module AppConfig
74
86
  when :yaml
75
87
  AppConfig::Storage::YAML.load(@options)
76
88
  else
77
- raise Error::UnknownStorageMethod
89
+ raise AppConfig::Error::UnknownStorageMethod
78
90
  end
79
91
  end
80
92
 
@@ -1,7 +1,7 @@
1
1
  module AppConfig
2
2
  module Error
3
3
 
4
- class NotConfigured < Exception
4
+ class NotSetup < Exception
5
5
  def to_s; "Must call 'AppConfig.setup' to setup storage!"; end
6
6
  end
7
7
 
@@ -1,8 +1,9 @@
1
1
  module AppConfig
2
2
  module Storage
3
- autoload :BaseStorage, 'app_config/storage/base_storage'
4
- autoload :Memory, 'app_config/storage/memory'
5
- autoload :Sqlite, 'app_config/storage/sqlite'
6
- autoload :YAML, 'app_config/storage/yaml'
3
+ autoload :Base, 'app_config/storage/base'
4
+ autoload :Memory, 'app_config/storage/memory'
5
+ autoload :Mongo, 'app_config/storage/mongo'
6
+ autoload :Sqlite, 'app_config/storage/sqlite'
7
+ autoload :YAML, 'app_config/storage/yaml'
7
8
  end
8
9
  end
@@ -1,6 +1,6 @@
1
1
  module AppConfig
2
2
  module Storage
3
- class BaseStorage
3
+ class Base
4
4
 
5
5
  attr_reader :data
6
6
 
@@ -1,6 +1,6 @@
1
1
  module AppConfig
2
2
  module Storage
3
- class Memory < BaseStorage
3
+ class Memory < Storage::Base
4
4
 
5
5
  def initialize(options)
6
6
  @data = Hashish.new(options)
@@ -0,0 +1,73 @@
1
+ begin
2
+ require 'mongo'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ require 'mongo'
6
+ end
7
+
8
+ module AppConfig
9
+ module Storage
10
+
11
+ # Mongo storage method.
12
+ class Mongo < Storage::Base
13
+
14
+ DEFAULTS = {
15
+ :host => 'localhost',
16
+ :port => '27017',
17
+ :database => 'app_config',
18
+ :collection => 'app_config',
19
+ :user => nil,
20
+ :password => nil
21
+ }
22
+
23
+ def initialize(options)
24
+ @connected = false
25
+ @options = DEFAULTS.merge(options)
26
+ setup_connection
27
+ @data = fetch_data
28
+ end
29
+
30
+ def [](key)
31
+ @data[key]
32
+ end
33
+
34
+ def []=(key, value)
35
+ @data[key] = value
36
+ save!
37
+ end
38
+
39
+ private
40
+
41
+ def save!
42
+ collection.save(@data)
43
+ end
44
+
45
+ def setup_connection
46
+ @connection = ::Mongo::Connection.new(@options[:host], @options[:port].to_i)
47
+ authenticate_connection if @options[:user] && @options[:password]
48
+ end
49
+
50
+ def authenticate_connection
51
+ database.authenticate(@options[:user], @options[:password])
52
+ end
53
+
54
+ def connected?
55
+ @connection && @connection.connected?
56
+ end
57
+
58
+ def fetch_data
59
+ raise 'Not connected to MongoDB' unless connected?
60
+ Hashish.new(collection.find_one)
61
+ end
62
+
63
+ def database
64
+ @database ||= @connection.db(@options[:database])
65
+ end
66
+
67
+ def collection
68
+ @collection ||= database.collection(@options[:collection])
69
+ end
70
+
71
+ end # Mongo
72
+ end # Storage
73
+ end # AppConfig
@@ -9,7 +9,7 @@ module AppConfig
9
9
  end
10
10
 
11
11
  # SQLite3 storage method.
12
- class Sqlite < BaseStorage
12
+ class Sqlite < Storage::Base
13
13
 
14
14
  DEFAULTS = {
15
15
  :database => File.expand_path(File.join(ENV['HOME'], '.app_config.sqlite3')),
@@ -4,7 +4,7 @@ module AppConfig
4
4
  require 'yaml'
5
5
 
6
6
  # YAML storage method.
7
- class YAML < BaseStorage
7
+ class YAML < Storage::Base
8
8
 
9
9
  DEFAULTS = {
10
10
  :path => File.expand_path(File.join(ENV['HOME'], '.app_config.yml'))
@@ -1,9 +1,9 @@
1
- # Stolen from Rails Active Support and aliased to Hashish.
1
+ # Stolen from Rails Active Support and renamed to Hashish.
2
2
  #
3
3
  # This class has dubious semantics and we only have it so that
4
4
  # people can write params[:key] instead of params['key']
5
5
  # and they get the same value for both keys.
6
- class HashWithIndifferentAccess < Hash
6
+ class Hashish < Hash
7
7
  def initialize(constructor = {})
8
8
  if constructor.is_a?(Hash)
9
9
  super()
@@ -117,24 +117,23 @@ class HashWithIndifferentAccess < Hash
117
117
  end
118
118
 
119
119
  protected
120
- def convert_key(key)
121
- key.kind_of?(Symbol) ? key.to_s : key
122
- end
123
120
 
124
- def convert_value(value)
125
- case value
126
- when Hash
127
- value.with_indifferent_access
128
- when Array
129
- value.collect { |e| e.is_a?(Hash) ? e.with_indifferent_access : e }
130
- else
131
- value
132
- end
121
+ def convert_key(key)
122
+ key.kind_of?(Symbol) ? key.to_s : key
123
+ end
124
+
125
+ def convert_value(value)
126
+ case value
127
+ when Hash
128
+ value.with_indifferent_access
129
+ when Array
130
+ value.collect { |e| e.is_a?(Hash) ? e.with_indifferent_access : e }
131
+ else
132
+ value
133
133
  end
134
- end
134
+ end
135
135
 
136
- # Simple alias.
137
- Hashish = HashWithIndifferentAccess
136
+ end # Hashish
138
137
 
139
138
  class Hash
140
139
  def with_indifferent_access
@@ -0,0 +1,25 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe AppConfig::Storage::Mongo do
4
+
5
+ before(:each) do
6
+ pending "TODO: Spec this out"
7
+ end
8
+
9
+ it 'should have some values' do
10
+ config_for_mongo
11
+ AppConfig[:api_key].should_not be_nil
12
+ end
13
+
14
+ it 'should update the values' do
15
+ config_for_mongo
16
+ original_key = AppConfig[:api_key]
17
+ AppConfig[:api_key] = 'SOME_NEW_API_KEY'
18
+
19
+ # Reload the data.
20
+ AppConfig.reset!
21
+ config_for_mongo
22
+
23
+ AppConfig[:api_key].should == 'SOME_NEW_API_KEY'
24
+ end
25
+ end
@@ -0,0 +1,27 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe AppConfig::Storage::YAML do
4
+
5
+ it 'should have some values' do
6
+ config_for_yaml
7
+ AppConfig[:api_key].should_not be_nil
8
+ end
9
+
10
+ it 'should raise file not found' do
11
+ lambda do
12
+ config_for_yaml(:path => 'not/a/real/file.yml')
13
+ end.should raise_error(Errno::ENOENT)
14
+ end
15
+
16
+ it 'parses the URI properly' do
17
+ AppConfig.setup(:uri => "yaml://#{fixture('app_config.yml')}")
18
+ AppConfig[:api_key].should_not be_nil
19
+ end
20
+
21
+ it 'saves the new value in memory' do
22
+ config_for_yaml
23
+ AppConfig[:new_key] = 'new value'
24
+ AppConfig[:new_key].should == 'new value'
25
+ end
26
+
27
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe AppConfig::Storage do
4
+
5
+ it 'responds to .setup()' do
6
+ AppConfig.should respond_to(:setup)
7
+ end
8
+
9
+ end
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ describe AppConfig do
4
+
5
+ it 'has a version' do
6
+ AppConfig::VERSION.should_not be_nil
7
+ end
8
+
9
+ it 'responds to .setup()' do
10
+ AppConfig.should respond_to(:setup)
11
+ end
12
+
13
+ it 'responds to .reset!()' do
14
+ AppConfig.should respond_to(:reset!)
15
+ end
16
+
17
+ it 'should have to_hash' do
18
+ config_for_yaml
19
+ AppConfig.to_hash.class.should == Hash
20
+ end
21
+
22
+ it 'should reset @@storage' do
23
+ config_for_yaml # configure first
24
+ AppConfig.reset! # then reset
25
+ lambda do
26
+ AppConfig[:some_key]
27
+ end.should raise_error(AppConfig::Error::NotSetup)
28
+ end
29
+
30
+ it 'Error::NotSetup is raised when calling to_hash()' do
31
+ # First, reset the storage variable.
32
+ AppConfig.send(:class_variable_set, :@@storage, nil)
33
+ lambda do
34
+ AppConfig.to_hash
35
+ end.should raise_error(AppConfig::Error::NotSetup)
36
+ end
37
+
38
+ describe 'environment mode' do
39
+ it 'should load the proper environment' do
40
+ config_for_yaml(:path => fixture('env_app_config.yml'),
41
+ :env => 'development')
42
+ AppConfig[:api_key].should_not be_nil
43
+ end
44
+ end
45
+
46
+ 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,17 @@
1
+ defaults: &defaults
2
+ title: 'AppConfig Env Mode'
3
+ admin_email: 'admin@example.com'
4
+ api_name: 'Supr Webz 2.0'
5
+ api_key: 'SUPERAWESOMESERVICE'
6
+
7
+ development:
8
+ <<: *defaults
9
+ admin_email: 'dev@example.com'
10
+
11
+ production:
12
+ <<: *defaults
13
+ title: 'AppConfig Env Production Mode!'
14
+
15
+ test:
16
+ <<: *defaults
17
+ admin_email: 'test@example.com'
@@ -0,0 +1,43 @@
1
+ require 'rubygems' if RUBY_VERSION =~ /^1\.8/
2
+ require 'rspec'
3
+
4
+ require File.expand_path("#{File.dirname(__FILE__)}/../lib/app_config")
5
+
6
+ RSpec.configure do |config|
7
+ include AppConfig
8
+
9
+ # Returns the full path to the +name+ fixture file.
10
+ def fixture(name)
11
+ File.expand_path(File.join(File.dirname(__FILE__), 'fixtures', name))
12
+ end
13
+
14
+ # AppConfig.setup wrapper. Accepts a hash of +options+.
15
+ def config_for(options)
16
+ AppConfig.reset!
17
+ AppConfig.setup(options)
18
+ end
19
+
20
+ # Setup YAML options and pass to config_for().
21
+ def config_for_yaml(opts = {})
22
+ path = opts[:path] || fixture('app_config.yml')
23
+ yaml = {
24
+ :storage_method => :yaml,
25
+ :path => path,
26
+ }
27
+ config_for(yaml.merge(opts))
28
+ end
29
+
30
+ def config_for_mongo(opts = {})
31
+ mongo = {
32
+ :storage_method => :mongo,
33
+ :host => 'localhost',
34
+ :database => 'app_config_spec',
35
+ :environment => 'test',
36
+ }
37
+ begin
38
+ config_for(mongo.merge(opts))
39
+ rescue Mongo::ConnectionFailure
40
+ pending "***** Mongo specs require a running MongoDB server *****"
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ def run_specs
4
+ system('rake spec')
5
+ end
6
+
7
+ # Ctrl-\
8
+ Signal.trap('QUIT') do
9
+ puts "\n--- Running all specs ---\n"
10
+ run_specs
11
+ end
12
+
13
+ # Ctrl-C
14
+ Signal.trap('INT') { abort("\n") }
15
+
16
+
17
+ if __FILE__ == $0
18
+ system("watchr #{$0}")
19
+ else
20
+ run_specs
21
+
22
+ [
23
+ 'lib/(.*/)?.*\.rb',
24
+ 'spec/(.*/)?.*_spec\.rb'
25
+ ].each do |pattern|
26
+ watch(pattern) { |md| run_specs }
27
+ end
28
+ end
@@ -0,0 +1,47 @@
1
+ APP_ROOT = File.join(File.dirname(__FILE__), '..')
2
+
3
+ desc 'Generate API documentation'
4
+ task :doc do
5
+ Rake::Task['doc:api'].invoke
6
+ end
7
+
8
+ namespace :doc do
9
+ task :setup_rdoc do
10
+ @file_list = FileList[ "#{File.join(APP_ROOT, 'README')}",
11
+ "#{APP_ROOT}/lib/**/*.rb" ]
12
+ # Substitute APP_ROOT with a dot. Makes for a better index in the generated docs.
13
+ @files = @file_list.collect {|f| f.gsub(/#{APP_ROOT}/, '.')}
14
+ @options = %W[
15
+ --all
16
+ --inline-source
17
+ --line-numbers
18
+ --op #{File.join(APP_ROOT, 'doc', 'api')}
19
+ --title 'AppConfig API Documentation'
20
+ ]
21
+ # Generate a diagram, yes/no?
22
+ @options << '-d' if RUBY_PLATFORM !~ /win32/ && `which dot` =~ /\/dot/ && !ENV['NODOT']
23
+ end
24
+
25
+ task :api => [:setup_rdoc] do
26
+ run_rdoc(@options, @files)
27
+ end
28
+
29
+ desc 'Remove generated API documentation'
30
+ task :clear do
31
+ sh "rm -rf #{File.join(APP_ROOT, 'doc', 'api')}"
32
+ end
33
+
34
+ desc 'Rebuild API documentation'
35
+ task :rebuild do
36
+ Rake::Task['doc:clear'].invoke
37
+ Rake::Task['doc:api'].invoke
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ def run_rdoc(options, files)
44
+ options = options.join(' ') if options.is_a? Array
45
+ files = files.join(' ') if files.is_a? Array
46
+ sh "rdoc #{options} #{files}"
47
+ end
@@ -0,0 +1,26 @@
1
+ APP_DIR = File.join(File.dirname(__FILE__), '..')
2
+ GEMSPEC = File.join(APP_DIR, 'app_config.gemspec')
3
+
4
+ desc 'Build the gem'
5
+ task :gem => ['gem:build']
6
+
7
+ namespace :gem do
8
+ task :build do
9
+ sh "gem build #{GEMSPEC}"
10
+ end
11
+
12
+ desc 'Remove the gem'
13
+ task :clean do
14
+ sh "rm -f #{APP_DIR}/*.gem"
15
+ end
16
+
17
+ desc 'Clean and rebuild the gem'
18
+ task :rebuild => ['gem:clean', 'gem:build']
19
+
20
+ desc 'Rebuild and install the gem'
21
+ task :install => ['gem:rebuild'] do
22
+ gem = FileList["#{APP_DIR}/*.gem"].first
23
+ raise 'Gem not found!' unless gem && File.exists?(gem)
24
+ sh "sudo gem uninstall app_config; sudo gem install --no-ri --no-rdoc #{gem}"
25
+ end
26
+ end
@@ -0,0 +1,5 @@
1
+ desc 'Run all specs'
2
+ RSpec::Core::RakeTask.new(:spec) do |t|
3
+ t.rspec_opts = ['--color', '--format progress']
4
+ t.pattern = FileList['spec/**/*_spec.rb']
5
+ end
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: app_config
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ hash: 15
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 5
9
+ - 2
10
+ version: 0.5.2
5
11
  platform: ruby
6
12
  authors:
7
13
  - Dale Campbell
@@ -9,10 +15,41 @@ autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
17
 
12
- date: 2009-10-25 00:00:00 -05:00
18
+ date: 2010-11-05 00:00:00 -04:00
13
19
  default_executable:
14
- dependencies: []
15
-
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: sqlite3-ruby
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 25
30
+ segments:
31
+ - 1
32
+ - 3
33
+ - 1
34
+ version: 1.3.1
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: rspec
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 13
46
+ segments:
47
+ - 2
48
+ - 0
49
+ - 1
50
+ version: 2.0.1
51
+ type: :development
52
+ version_requirements: *id002
16
53
  description: An easy to use, customizable library to easily store and retrieve application configuration.
17
54
  email:
18
55
  - oshuma@gmail.com
@@ -23,17 +60,30 @@ extensions: []
23
60
  extra_rdoc_files: []
24
61
 
25
62
  files:
26
- - Rakefile
27
63
  - README
28
- - lib/app_config.rb
29
- - lib/app_config/base.rb
64
+ - Rakefile
30
65
  - lib/app_config/error.rb
31
66
  - lib/app_config/storage.rb
32
- - lib/app_config/storage/base_storage.rb
67
+ - lib/app_config/base.rb
33
68
  - lib/app_config/storage/memory.rb
34
69
  - lib/app_config/storage/sqlite.rb
70
+ - lib/app_config/storage/mongo.rb
35
71
  - lib/app_config/storage/yaml.rb
72
+ - lib/app_config/storage/base.rb
73
+ - lib/app_config.rb
36
74
  - lib/core_ext/hashish.rb
75
+ - spec/watchr.rb
76
+ - spec/fixtures/app_config.yml
77
+ - spec/fixtures/env_app_config.yml
78
+ - spec/app_config_spec.rb
79
+ - spec/app_config/storage_spec.rb
80
+ - spec/app_config/storage/yaml_spec.rb
81
+ - spec/app_config/storage/mongo_spec.rb
82
+ - spec/spec_helper.rb
83
+ - spec/core_ext/hashish_spec.rb
84
+ - tasks/doc.rake
85
+ - tasks/rspec.rake
86
+ - tasks/gem.rake
37
87
  has_rdoc: true
38
88
  homepage: http://oshuma.github.com/app_config
39
89
  licenses: []
@@ -45,21 +95,27 @@ rdoc_options:
45
95
  require_paths:
46
96
  - lib
47
97
  required_ruby_version: !ruby/object:Gem::Requirement
98
+ none: false
48
99
  requirements:
49
100
  - - ">="
50
101
  - !ruby/object:Gem::Version
102
+ hash: 3
103
+ segments:
104
+ - 0
51
105
  version: "0"
52
- version:
53
106
  required_rubygems_version: !ruby/object:Gem::Requirement
107
+ none: false
54
108
  requirements:
55
109
  - - ">="
56
110
  - !ruby/object:Gem::Version
111
+ hash: 3
112
+ segments:
113
+ - 0
57
114
  version: "0"
58
- version:
59
115
  requirements: []
60
116
 
61
- rubyforge_project: app-config
62
- rubygems_version: 1.3.5
117
+ rubyforge_project:
118
+ rubygems_version: 1.3.7
63
119
  signing_key:
64
120
  specification_version: 3
65
121
  summary: Quick and easy application configuration.