config_module 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4ff9be2b58fa4690a4341b05c51578ca4066810c
4
+ data.tar.gz: 0c6aeb9814bf45f447b86091c869804954909a3b
5
+ SHA512:
6
+ metadata.gz: 9308b74b9f72f8c1f58384cb6063ed8736349628b5e30d338fa7f42290f5aabfc2e87e0b76f1c9b8ca1c2685d9bff2c13525d93db915cffd6639d5560e0e159a
7
+ data.tar.gz: 083a6b61d0e40931f2335ef76b02db1e07bbca73cb8523f0667247f1650b0938fb0dae2a00669c80a39f1577200f80bc56d74c733165ae554d5466469395d26f
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm --create ruby-2.0.0-p0@config_module
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in config_module.gemspec
4
4
  gemspec
5
+
6
+ gem 'uspec', git: '../uspec'
@@ -16,4 +16,7 @@ Gem::Specification.new do |gem|
16
16
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
17
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
18
  gem.require_paths = ["lib"]
19
+
20
+ gem.add_development_dependency 'pry'
21
+ gem.add_development_dependency 'pry-theme'
19
22
  end
data/lib/config_module.rb CHANGED
@@ -1,71 +1,38 @@
1
- require_relative 'config_module/version'
2
1
  require 'ostruct'
3
2
  require 'yaml'
3
+ require 'pry'
4
+
5
+ require_relative 'config_module/version'
6
+ require_relative 'config_module/exceptions'
7
+ require_relative 'config_module/config_option'
8
+ require_relative 'config_module/config_helper'
4
9
 
5
10
  module ConfigModule
6
11
  def [] key
7
- config.send key
12
+ __config_module_helper.config.send key
8
13
  end
9
14
 
10
15
  def config
11
- @config ||= ConfigOption.wrap load_config
16
+ __config_module_helper.config
12
17
  end
13
18
 
14
19
  protected
15
20
 
16
- def config_file file
17
- @config_file = file
21
+ def config_file new_config_file
22
+ __config_module_helper.config_file = new_config_file
18
23
  end
19
24
 
20
- def namespace *name
21
- @namespace = Array name
25
+ def namespace *new_namespace
26
+ __config_module_helper.namespaces = *new_namespace
22
27
  end
23
28
 
24
29
  private
25
30
 
26
- def namespaced?
27
- !(@namespace.nil? || @namespace.empty?)
28
- end
29
-
30
- def load_config
31
- file = YAML.load_file(@config_file)
32
-
33
- if namespaced? then
34
- @namespace.inject(file) do |file, ns|
35
- file.include?(ns) && file[ns] || file.include?(ns.to_sym) && file[ns.to_sym]
36
- end
37
- else
38
- file
39
- end
31
+ def __config_module_helper
32
+ @__config_module_helper ||= ConfigHelper.new
40
33
  end
41
34
 
42
35
  def method_missing name
43
- ConfigOption.wrap config.get name
44
- rescue NoMethodError => error
45
- if error.name == name then
46
- raise NoMethodError, "undefined method `#{name}' for #{self}", caller(1)
47
- else
48
- raise
49
- end
50
- end
51
-
52
- class ConfigOption < OpenStruct
53
- def self.wrap data
54
- if data.is_a? Hash then
55
- ConfigOption.new data
56
- else
57
- data
58
- end
59
- end
60
-
61
- def get name
62
- if @table.include? name then
63
- self.class.wrap @table[name]
64
- else
65
- raise ConfigOption::NotFound
66
- end
67
- end
68
-
69
- class NotFound < RangeError; end
36
+ __config_module_helper.method_missing_handler name, caller(1)
70
37
  end
71
38
  end
@@ -0,0 +1,40 @@
1
+ module ConfigModule
2
+ class ConfigHelper
3
+ attr :raw_config
4
+ attr_accessor :config_file, :namespaces
5
+
6
+ def config
7
+ @config ||= ConfigOption.wrap load_config
8
+ end
9
+
10
+ def method_missing_handler name, source
11
+ config.send name
12
+ rescue NoMethodError => error
13
+ if error.name == name then
14
+ raise # ConfigOption::NotFoundError.new(name, source)#, source
15
+ else
16
+ raise
17
+ end
18
+ end
19
+
20
+ def load_config
21
+ @raw_config = YAML.load_file config_file
22
+
23
+ load_namespaces_from raw_config
24
+ end
25
+
26
+ def load_namespaces_from tree
27
+ return tree unless namespaced?
28
+
29
+ Array(namespaces).inject(ConfigOption.wrap tree) do |subtree, ns|
30
+ raise(InvalidNamespaceError.new(ns, subtree)) unless subtree.respond_to? ns
31
+
32
+ subtree.send ns
33
+ end
34
+ end
35
+
36
+ def namespaced?
37
+ !(namespaces.nil? || namespaces.empty?)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,41 @@
1
+ module ConfigModule
2
+ class ConfigOption < OpenStruct
3
+ include Enumerable
4
+
5
+ def self.wrap data
6
+ if data.is_a? Hash then
7
+ ConfigOption.new data
8
+ else
9
+ data
10
+ end
11
+ end
12
+
13
+ def each
14
+ return to_enum __method__ unless block_given?
15
+ @table.each_pair{|p| yield p}
16
+ end
17
+
18
+ def method_missing name, *args, &block
19
+ result = super
20
+
21
+ if result || @table.include?(name) then
22
+ self.class.wrap result
23
+ else
24
+ raise ConfigOption::NotFoundError.new name, self
25
+ end
26
+ end
27
+
28
+ def new_ostruct_member name
29
+ name = name.to_sym
30
+ unless respond_to? name
31
+ define_singleton_method(name) { self.class.wrap @table[name] }
32
+ define_singleton_method("#{name}=") { |x| modifiable[name] = x }
33
+ end
34
+ name
35
+ end
36
+
37
+ class NotFoundError < ::ConfigModule::ConfigError
38
+ def identifier; :key; end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,21 @@
1
+ module ConfigModule
2
+ class ConfigError < NoMethodError
3
+ def initialize name, object
4
+ @name, @object = name, object
5
+ super "invalid #{identifier} `#{name}' for #{object_info}"
6
+ end
7
+ attr :name, :object
8
+
9
+ def object_info
10
+ if object.is_a?(Class) then
11
+ object.name
12
+ else
13
+ "instance of `#{object.class} < #{object.class.superclass}'"
14
+ end
15
+ end
16
+ end
17
+
18
+ class InvalidNamespaceError < ConfigError
19
+ def identifier; :namespace; end
20
+ end
21
+ end
@@ -1,3 +1,3 @@
1
1
  module ConfigModule
2
- VERSION = "0.0.3"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -0,0 +1,6 @@
1
+ ---
2
+ production:
3
+ foo: bar
4
+ noodle: boom!
5
+ dictionary:
6
+ configuration: An arrangement of elements in a particular form, figure, or combination.
File without changes
@@ -0,0 +1,16 @@
1
+ require_relative 'spec_helper'
2
+
3
+ hash = {a: {b: 5}}
4
+ opt = ConfigModule::ConfigOption.new hash
5
+
6
+ spec 'ConfigOptions are Enumerable' do
7
+ opt.map{|k,v| v[:b]} == [5]
8
+ end
9
+
10
+ spec 'to_ary' do
11
+ begin
12
+ opt.to_ary
13
+ rescue NoMethodError => error
14
+ error.class == ConfigModule::ConfigOption::NotFoundError
15
+ end
16
+ end
@@ -1,12 +1,6 @@
1
- require_relative 'mutest'
2
- extend Mutest
3
-
4
- require_relative '../lib/config_module'
5
- module Rails; def self.env; 'production'; end; end
1
+ require_relative 'spec_helper'
6
2
  require_relative 'example_config'
7
3
 
8
- Dir.chdir File.dirname(__FILE__)
9
-
10
4
  spec 'modules extended with ConfigModule will load configurations' do
11
5
  ExampleConfig.foo == 'bar'
12
6
  end
@@ -15,12 +9,12 @@ spec 'modules extended with ConfigModule have "namespace" methods' do
15
9
  ExampleConfig.methods.include? :namespace
16
10
  end
17
11
 
18
- spec 'nested hash values are properly wrapped' do
19
- ExampleConfig.dictionary.class == ConfigModule::ConfigOption
12
+ spec 'config modules have [] methods' do
13
+ ExampleConfig.respond_to? :[]
20
14
  end
21
15
 
22
- spec 'config modules have [] methods' do
23
- ExampleConfig[:dictionary].keys.include? :configuration
16
+ spec 'nested hash values are properly wrapped' do
17
+ ExampleConfig.dictionary.class == ConfigModule::ConfigOption
24
18
  end
25
19
 
26
20
  spec 'subkeys are accessible with methods' do
@@ -43,7 +37,7 @@ end
43
37
  spec 'missing keys raise exception when called as methods' do
44
38
  begin
45
39
  FalseNil.nonexistant
46
- rescue ConfigModule::ConfigOption::NotFound
40
+ rescue ConfigModule::ConfigOption::NotFoundError
47
41
  true
48
42
  end
49
43
  end
@@ -57,3 +51,17 @@ end
57
51
  spec 'multiple namespaces can be set' do
58
52
  MultipleExample.configuration == ExampleConfig.dictionary.configuration
59
53
  end
54
+
55
+ module InvalidNamespaceExample
56
+ extend ConfigModule
57
+ config_file './config/example.yml'
58
+ namespace :jimmy, :pop, :ali
59
+ end
60
+
61
+ spec 'incorrect namespaces raise informative errors' do
62
+ begin
63
+ InvalidNamespaceExample.whatever
64
+ rescue => error
65
+ error.class == ConfigModule::InvalidNamespaceError
66
+ end
67
+ end
File without changes
@@ -0,0 +1,23 @@
1
+ require_relative 'spec_helper'
2
+
3
+ def self.helper
4
+ if @helper then @helper
5
+ else
6
+ @helper = ConfigModule::ConfigHelper.new
7
+ @helper.config_file = './config/example.yml'
8
+ @helper.namespaces = 'production'
9
+ @helper.config
10
+ @helper
11
+ end
12
+ end
13
+
14
+ table = helper.load_config.instance_variable_get(:@table)
15
+
16
+ spec 'namespaces obtain subtrees of the full config' do
17
+ table.keys == [:foo, :noodle, :dictionary]
18
+ end
19
+
20
+ spec 'specifying a namespace forces #config to return that subtree the first time its called' do
21
+ symbolized_keys_from_full_config = helper.raw_config['production'].keys.map(&:to_sym)
22
+ symbolized_keys_from_full_config == table.keys
23
+ end
@@ -0,0 +1,10 @@
1
+ require 'bundler/setup'
2
+ require 'uspec'
3
+
4
+ Dir.chdir File.dirname(__FILE__)
5
+
6
+ require_relative '../lib/config_module'
7
+
8
+ extend Uspec
9
+
10
+ module Rails; def self.env; 'production'; end; end
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: config_module
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
5
- prerelease:
4
+ version: 0.1.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Anthony Cook
@@ -10,7 +9,35 @@ autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
11
  date: 2013-02-27 00:00:00.000000000 Z
13
- dependencies: []
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pry
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry-theme
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
14
41
  description: Wrap a configuration file in a module for easy use throughout your application.
15
42
  Inspired by Rails.
16
43
  email:
@@ -20,45 +47,51 @@ extensions: []
20
47
  extra_rdoc_files: []
21
48
  files:
22
49
  - .gitignore
50
+ - .rvmrc
23
51
  - Gemfile
24
52
  - README.markdown
25
53
  - Rakefile
26
54
  - config_module.gemspec
27
55
  - lib/config_module.rb
56
+ - lib/config_module/config_helper.rb
57
+ - lib/config_module/config_option.rb
58
+ - lib/config_module/exceptions.rb
28
59
  - lib/config_module/version.rb
29
- - test/config/example.yml
30
- - test/config/false_nil.yml
31
- - test/example_config.rb
32
- - test/mutest.rb
33
- - test/test.rb
60
+ - spec/config/example.yml
61
+ - spec/config/false_nil.yml
62
+ - spec/config_helper_spec.rb
63
+ - spec/config_module_spec.rb
64
+ - spec/example_config.rb
65
+ - spec/namespace_spec.rb
66
+ - spec/spec_helper.rb
34
67
  homepage: http://github.com/acook/config_module
35
68
  licenses: []
69
+ metadata: {}
36
70
  post_install_message:
37
71
  rdoc_options: []
38
72
  require_paths:
39
73
  - lib
40
74
  required_ruby_version: !ruby/object:Gem::Requirement
41
- none: false
42
75
  requirements:
43
- - - ! '>='
76
+ - - '>='
44
77
  - !ruby/object:Gem::Version
45
78
  version: '0'
46
79
  required_rubygems_version: !ruby/object:Gem::Requirement
47
- none: false
48
80
  requirements:
49
- - - ! '>='
81
+ - - '>='
50
82
  - !ruby/object:Gem::Version
51
83
  version: '0'
52
84
  requirements: []
53
85
  rubyforge_project:
54
- rubygems_version: 1.8.25
86
+ rubygems_version: 2.0.0
55
87
  signing_key:
56
- specification_version: 3
88
+ specification_version: 4
57
89
  summary: Load important configuration files into their own modules!
58
90
  test_files:
59
- - test/config/example.yml
60
- - test/config/false_nil.yml
61
- - test/example_config.rb
62
- - test/mutest.rb
63
- - test/test.rb
64
- has_rdoc:
91
+ - spec/config/example.yml
92
+ - spec/config/false_nil.yml
93
+ - spec/config_helper_spec.rb
94
+ - spec/config_module_spec.rb
95
+ - spec/example_config.rb
96
+ - spec/namespace_spec.rb
97
+ - spec/spec_helper.rb
@@ -1,6 +0,0 @@
1
- ---
2
- :production:
3
- :foo: bar
4
- :noodle: boom!
5
- :dictionary:
6
- :configuration: An arrangement of elements in a particular form, figure, or combination.
data/test/mutest.rb DELETED
@@ -1,112 +0,0 @@
1
- module Mutest
2
- def spec description
3
- print ' -- ', description
4
-
5
- return puts(': ' + yellow('pending') + vspace) unless block_given?
6
-
7
- begin
8
- result = yield
9
- rescue => result
10
- end
11
-
12
- print ': ', colorize(result, caller), "\n"
13
- end
14
-
15
- module Color
16
-
17
- def colors
18
- {
19
- red: 1,
20
- green: 2,
21
- yellow: 3,
22
- white: 7
23
- }
24
- end
25
-
26
- def color hue, text = nil
27
- esc("3#{colors[hue]};1") + "#{text}#{normal if text}"
28
- end
29
-
30
- def esc seq
31
- "\e[#{seq}m"
32
- end
33
-
34
- def normal text=nil
35
- esc(0) + text.to_s
36
- end
37
-
38
- def colorize result, source
39
- if result == true then
40
- green result
41
- elsif result == false then
42
- red result
43
- elsif result.is_a? Exception then
44
- [
45
- red('Exception'), vspace,
46
- hspace, 'Spec encountered an Exception ', newline,
47
- hspace, 'in spec at ', source.first, vspace,
48
- hspace, message(result), vspace,
49
- white(trace result)
50
- ].join
51
- else
52
- [
53
- red('Unknown Result'), vspace,
54
- hspace, 'Spec did not return a boolean value ', newline,
55
- hspace, 'in spec at ', source.first, vspace,
56
- hspace, red(classinfo(result)), result.inspect, newline
57
- ].join
58
- end
59
- end
60
-
61
- def trace error
62
- error.backtrace.inject(String.new) do |text, line|
63
- text << hspace + line + newline
64
- end
65
- end
66
-
67
- def message error
68
- red(classinfo error) + error.message
69
- end
70
-
71
- def classinfo object
72
- "#{classify object} < #{superclass object}: "
73
- end
74
-
75
- def classify object
76
- object.is_a?(Module) ? object : object.class
77
- end
78
-
79
- def superclass object
80
- classify(object).superclass
81
- end
82
-
83
- def hspace
84
- ' '
85
- end
86
-
87
- def vspace
88
- newline + newline
89
- end
90
-
91
- def newline
92
- $/
93
- end
94
-
95
- private
96
-
97
- def method_missing name, *args, &block
98
- if colors.keys.include? name then
99
- color name, *args
100
- else
101
- super
102
- end
103
- end
104
-
105
- end
106
-
107
- private
108
-
109
- include Color
110
- end
111
-
112
-