Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dramatic changes #15

Closed
wants to merge 61 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
e7a135d
Add save! to Storage::YAML
DSIW Aug 27, 2012
61d44c6
bump to 1.0.3
DSIW Aug 27, 2012
cbd123e
Refactore tempfile
DSIW Aug 28, 2012
3026432
Add access by methods
DSIW Aug 28, 2012
5456801
Add option :creation to AppConfig::setup
DSIW Aug 28, 2012
543a9af
Add feature for automatic write
DSIW Aug 28, 2012
2b42719
bump to 1.0.4
DSIW Aug 28, 2012
8b3e959
Refactoring a lot
DSIW Aug 28, 2012
5307ce9
bump to 2.0.0
DSIW Aug 28, 2012
757b404
Rename option :creation to :create
DSIW Sep 2, 2012
d963044
Update version in Gemfile.lock
DSIW Sep 2, 2012
c213b82
Add module Configurable
DSIW Sep 3, 2012
86730ab
bump to 2.0.1
DSIW Sep 3, 2012
c1468eb
Change capsulation: App::Configurable.force? is private
DSIW Sep 3, 2012
8e930cb
Tabularize arguments of autoload
DSIW Sep 11, 2012
0e36e01
Alias config to _config
DSIW Sep 11, 2012
1ba958f
config will be reloaded if block is given or option is set
DSIW Sep 11, 2012
9a8fb21
should not refresh config if options 'force' is false
DSIW Sep 11, 2012
e1af8c1
Add class Force
DSIW Sep 11, 2012
9b99447
Add tests to util/force
DSIW Sep 11, 2012
e6b9490
Fix Force#false
DSIW Sep 11, 2012
70bd6fc
Add super call in initialize
DSIW Sep 11, 2012
f0bc93a
Config will reload if options hash changes
DSIW Sep 11, 2012
82e4123
bump to 2.0.2
DSIW Sep 11, 2012
deca67a
Removes collection for specs
DSIW Sep 11, 2012
4867e03
Add mongodb test files to gitignore
DSIW Sep 12, 2012
b57f501
Remove force if options changes
DSIW Sep 12, 2012
d1ea944
Add default values in intialize
DSIW Sep 12, 2012
e0b0deb
Return true if hash has been written in file
DSIW Sep 12, 2012
42c618c
Remove useless &block
DSIW Sep 12, 2012
08620d8
Refactoring options hash
DSIW Sep 12, 2012
5c09fd8
Add some blocks and add helper load_yaml_of_config
DSIW Sep 12, 2012
74b9804
Change setup method for better understanding
DSIW Sep 12, 2012
70da721
New config will be saved if force
DSIW Sep 12, 2012
852141a
Add travis-ci config file
DSIW Sep 13, 2012
8d6eebc
Clean up
DSIW Sep 13, 2012
27645b2
Refactoring
DSIW Sep 13, 2012
2c2fc01
Fix YAML.load_file for ruby 1.9.3p194
DSIW Sep 13, 2012
3755fa0
Remove ruby 1.8.7 for travis-ci
DSIW Sep 13, 2012
6430793
Remove version of dependency rspec
DSIW Sep 13, 2012
3e96693
Add status images of travis-ci and dependencies
DSIW Sep 13, 2012
c33a9b5
Fix status images
DSIW Sep 13, 2012
c7646fa
Change @@options and @@storage to object variables
DSIW Sep 14, 2012
8806062
Add documentation
DSIW Sep 14, 2012
02d8cd0
Rename method save? to save_changes?; Clarify clear and clear!
DSIW Sep 14, 2012
1cf741b
Add doc to YAML
DSIW Sep 14, 2012
b418a5d
Add doc to Memory
DSIW Sep 14, 2012
cac6949
Add doc to gitignore
DSIW Sep 15, 2012
fae94cd
Add method store; fix dup; format will be downcase in save!; dynamic …
DSIW Sep 15, 2012
5c1ad43
Add specs to check convert methods and setter
DSIW Sep 15, 2012
120f037
Fix memory storage; fix yield
DSIW Sep 15, 2012
c934120
Fix dynamic setter; initialize with data and options
DSIW Sep 15, 2012
2e89d7f
Cleanup memory
DSIW Sep 15, 2012
b0583bb
Cleanup mongo
DSIW Sep 15, 2012
510a090
Fix yaml
DSIW Sep 15, 2012
5e5a77d
Add to_json to Hashish
DSIW Sep 15, 2012
40757fb
Add specs to check dynamic setter
DSIW Sep 15, 2012
4994e6c
Add doc
DSIW Sep 15, 2012
78584d6
bump to 2.0.3
DSIW Sep 15, 2012
c4e3f80
Update README
DSIW Sep 15, 2012
a231adc
Handle ?? in doc
DSIW Sep 15, 2012
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ coverage/
doc/api/
pkg/
tmp/**/*
start_mongod.sh
spec/fixtures/db/
doc
21 changes: 21 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
language: ruby
rvm:
- 1.9.2
- 1.9.3
#script: bundle exec rake test
script: bundle exec rake spec
#before_install:
#- gem update --system
#- gem --version
env:
- USE_PLYMOUTH="no"
branches:
only:
- master
notifications:
email:
recipients:
- [email protected]
on_succes: change
# [always|never|change]
on_failure: always
4 changes: 2 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
app_config (1.0.1)
app_config (2.0.2)

GEM
remote: http://rubygems.org/
Expand Down Expand Up @@ -39,6 +39,6 @@ DEPENDENCIES
maruku
mongo
rake
rspec (~> 2.10.0)
rspec
simplecov
yard
107 changes: 88 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# AppConfig
# AppConfig [![Build Status](https://secure.travis-ci.org/DSIW/app_config.png)](http://travis-ci.org/DSIW/app_config) [![Dependency Status](https://gemnasium.com/DSIW/app_config.png)](https://gemnasium.com/DSIW/app_config)

An easy to use, customizable library to easily store and retrieve application
(or library) configuration, API keys or basically anything in 'key/value' pairs.
Expand All @@ -10,21 +10,40 @@ Usage is simple. Just pass either a hash of options, or a block, to {AppConfig.

In it's simplest form, you can use it like so:

AppConfig.setup(:admin_email => '[email protected]')
# ..or..
AppConfig.setup do |config|
config = AppConfig.setup do |config|
config[:admin_email] = '[email protected]'
# Other setter:
# config["admin_email"] = '[email protected]'
# config.admin_email = '[email protected]'
end

# Strings or symbols as keys.
AppConfig[:admin_email] # => '[email protected]'
# Strings or symbols or dynamic methods as keys.
config[:admin_email] #=> '[email protected]'
config["admin_email"] #=> '[email protected]'
config.admin_email #=> '[email protected]'

You may also specify the storage method along with options specific to that storage method.
Check the [wiki](https://github.com/Oshuma/app_config/wiki) for more usage examples.

If you like to use the {AppConfig::Configurable} module, see how easy it is:

module Client
include Configurable

def set_config
# Use it everywhere you want
config.api_url = "http://example.com/api/"
config.api_key = "2H28dsaa4"
config.api_version = "2"
end
end

Please scroll down to the last chapter for more informtation and details.


## Deprecation Note

Version `1.0` is \***not**\* backwards compatible with `0.7.1`! See the [wiki](https://github.com/Oshuma/app_config/wiki)
Version `2.0` is ***not*** backwards compatible with `1.0` and `0.7.1`! See the [wiki](https://github.com/Oshuma/app_config/wiki)
for upgrade instructions.


Expand All @@ -39,14 +58,34 @@ Given this YAML file:

Use it like so:

AppConfig.setup(:yaml => '/path/to/app_config.yml')
config = AppConfig.setup(:yaml => '/path/to/app_config.yml')

# Later on...
# Strings or symbols as keys.
AppConfig['admin_email'] # => '[email protected]'
AppConfig[:api_name] # => 'Supr Webz 2.0'
AppConfig[:api_key] # => 'SUPERAWESOMESERVICE'
# Strings or symbols or dynamic methods as keys.
config['admin_email'] #=> '[email protected]'
config.api_name #=> 'Supr Webz 2.0'
config[:api_key] #=> 'SUPERAWESOMESERVICE'

### Create the YAML file, if it doesn't exist

I like to create the YAML file, if it doesn't exist

config = AppConfig.setup(:yaml => '/path/to/file_doesnt_exist.yml', :create => true)
# File will be created with all non-existing directories.

# Later on...
config['admin_email'] = '[email protected]'
config['admin_email'] #=> '[email protected]'

### Save all changes automatically

When you use your config sometimes, it would be nice, if your config will be saved automatically to your YAML file.

config = AppConfig.setup(:yaml => '/path/to/app_config.yml', :save_changes => true)

# Later on...
config['admin_email'] #=> '[email protected]'
# YAML file will be written and includes 'admin_email'.

## AppConfig::Storage::Mongo

Expand All @@ -60,13 +99,12 @@ constant for the default Mongo connection options.
:collection => 'app_config' # default
}

AppConfig.setup(:mongo => mongo_opts)
config = AppConfig.setup(:mongo => mongo_opts)

AppConfig[:admin_email]
# => '[email protected]'
config[:admin_email] #=> '[email protected]'

# Override an existing value (saves to the database):
AppConfig[:admin_email] = '[email protected]'
config[:admin_email] = '[email protected]'

The values are read/saved (by default) to the `app_config` database and
`app_config` collection. These defaults can be overridden, however, which
Expand All @@ -75,7 +113,6 @@ might lend well to versioned configurations; collection names such as

AppConfig.setup(:mongo => { :collection => 'app_config_v2' })


## Environment Mode

There's also an 'environment mode' where you can organize the config
Expand All @@ -91,12 +128,44 @@ sort of like the Rails database config. Given this YAML file:
Set the `:env` option to your desired environment.

# Rails.root/config/initializers/app_config.rb
AppConfig.setup({
config = config.setup({
:yaml => "#{Rails.root}/config/app_config.yml",
:env => Rails.env # or any string
})

# Uses the given environment section of the config.
AppConfig[:title]
config[:title]
# => 'Production Mode'

## Module Configurable

You can include the module `Configurable` to have access to your configuration in all your code.
This module is created to include it in all classes where you want to have access to your configuration.


### Forcing or reloading

Your access by _config_ is cached. So if you'd like to have another object, you could do this by passing :force or :reload.

config.object_id #=> 123456
config(:force => true).object_id #=> 654321
# ..or..
config(:reload => true)

#### New object, because :force is set
config(:force => true)

#### New object, because :force is set and block is given
config(:force => true) { |config| config[:key] = "value" }

#### New object, because :force isn't set and block is given
config { |config| config[:key] = "value" }

#### No new object, because :force is false and block is given
config(:force => false) { |config| config[:key] = "value" }

#### Creates a new object and YAML file will be empty
config(:yaml => "path/to/file.yml", :force => true, :save_changes => true)
File.read("path/to/file.yml") #=> "--- {}"

See {AppConfig::Configurable#config} for datails.
2 changes: 1 addition & 1 deletion app_config.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Gem::Specification.new do |s|
s.add_development_dependency 'maruku'
s.add_development_dependency 'mongo'
s.add_development_dependency 'rake'
s.add_development_dependency 'rspec', '~> 2.10.0'
s.add_development_dependency 'rspec'
s.add_development_dependency 'simplecov'
s.add_development_dependency 'yard'

Expand Down
116 changes: 64 additions & 52 deletions lib/app_config.rb
Original file line number Diff line number Diff line change
@@ -1,81 +1,93 @@
require 'core_ext/hashish'

# @example Usage
# config = AppConfig.setup do |config|
# config[:key] = "value"
# config[:newkey] = "newvalue"
# end
# config[:tmp] = "/tmp"
# config[:newkey] #=> "newvalue"
# config.tmp #=> "/tmp"
#
# config.key # raises ArgumentError, because Hash#key needs an argument.
# # But you can use:
# config._key #=> "value"
module AppConfig
VERSION = '1.0.2'
# Version of this Gem.
VERSION = '2.0.3'

autoload :Error, 'app_config/error'
autoload :Storage, 'app_config/storage'
autoload :Error, 'app_config/error'
autoload :Storage, 'app_config/storage'
autoload :Configurable, 'app_config/configurable'
autoload :Force, 'util/force'

class << self

# Accepts an `options` hash or a block.
# Accepts an _options_ hash or a block.
# See each storage method's documentation for their specific options.
#
# Valid storage methods:
# * `:memory` - {AppConfig::Storage::Memory AppConfig::Storage::Memory}
# * `:mongo` - {AppConfig::Storage::Mongo AppConfig::Storage::Mongo}
# * `:yaml` - {AppConfig::Storage::YAML AppConfig::Storage::YAML}
def setup(options = {}, &block)
@@options = options

if @@options[:yaml]
@@storage = AppConfig::Storage::YAML.new(@@options.delete(:yaml))
elsif @@options[:mongo]
@@storage = AppConfig::Storage::Mongo.new(@@options.delete(:mongo))
# * *:memory* - {AppConfig::Storage::Memory AppConfig::Storage::Memory}
# * *:mongo* - {AppConfig::Storage::Mongo AppConfig::Storage::Mongo}
# * *:yaml* - {AppConfig::Storage::YAML AppConfig::Storage::YAML}
#
# @param options [Hash]
#
# It will be configured by the _options_ hash. _options_ can have the following
# keys:
# * *:yaml*: Path to YAML file.
# * *:mongo*: Options for MongoDB database.
# * *:create*: This will create the specified YAML file. (:yaml has to be included.)
# * *:save_changes*: Every change in your storage object will be saved in your YAML file. (:yaml has to be included.)
#
# @yieldparam [Storage] config
#
# @note Your yielded block will be returned.
#
# @example Initialization without
# config = AppConfig.setup
# config.class #=> AppConfig::Storage::Memory
#
# @example Initialization with :yaml
# config = AppConfig.setup(:yaml => "/path/to/file.yml")
# config.class #=> AppConfig::Storage::YAML
#
# @example Initialization with :mongo
# config = AppConfig.setup(:mongo => {:username => "usename", :password => "password"})
# config.class #=> AppConfig::Storage::Mongo
#
# @return [Storage] config
def setup(options = {})
@options = options

if @options[:yaml]
@storage = AppConfig::Storage::YAML.new(@options.delete(:yaml), @options)
elsif @options[:mongo]
@storage = AppConfig::Storage::Mongo.new(@options.delete(:mongo))
else
@@storage = AppConfig::Storage::Memory.new(@@options)
@storage = AppConfig::Storage::Memory.new({}, @options)
end

yield @@storage if block_given?
yield storage if block_given?

to_hash
storage
end

# Returns `true` if {AppConfig.setup AppConfig.setup} has been called.
# @return true if {AppConfig.setup AppConfig.setup} has been called.
def setup?
!!(defined?(@@storage) && !@@storage.empty?)
end

# Clears the `@@storage`.
def reset!
if defined?(@@storage)
remove_class_variable(:@@storage)
true
else
false
end
end

# Access the configured `key`'s value.
def [](key)
setup unless setup?
storage[key]
end

# Set a new `value` for `key` (persistence depends on the type of Storage).
def []=(key, value)
setup unless setup?
storage[key] = value
end

def empty?
storage.empty?
end

def to_hash
setup? ? storage.to_hash : Hashish.new
!!(defined?(@storage) && [email protected]?)
end

private

def environment
(@@options[:environment] || @@options[:env]) || nil
(@options[:environment] || @options[:env]) || nil
end
alias_method :env, :environment

# Returns the `@@storage` contents, which is what is exposed as the configuration.
# @return the `@storage` contents, which is what is exposed as the configuration.
def storage
environment ? @@storage[environment] : @@storage
environment ? @storage[environment] : @storage
end

end # self
Expand Down
Loading