config_module 0.0.3 → 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.
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
-