rconfigurator 0.0.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/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in configurator.gemspec
4
+ gem "rspec"
data/LICENSE.txt ADDED
File without changes
data/README ADDED
@@ -0,0 +1,87 @@
1
+ === Welcome to RConfigurator!
2
+
3
+ --- Configuration shouldn't be hard...
4
+
5
+ ...and loading configuration for your Ruby application has never been easier.
6
+
7
+ RConfigurator automatically "hydrates" your application's module constants by walking
8
+ through a .yml file. If you've got module constants strewn throughout your project,
9
+ you can use RConfigurator to aggregate these into one place.
10
+
11
+ --- Usage
12
+
13
+ To get this going, you just have to require 'rconfigurator' and provide use with the
14
+ name of the project and the location of the configuration file:
15
+
16
+ require 'rconfigurator'
17
+ RConfigurator.configure! "ExampleModule", "/path/to/my/config"
18
+
19
+ Configurator will analyze the file and 'inflate' your module constants using the data it finds there. Let's say you've got the following module constants:
20
+
21
+ ExampleModule::KEY = 'value'
22
+ ExampleModule::NUMERIC_DATA = 3.221
23
+ ExampleModule::SampleModule::SOME_KEY = 'another value'
24
+ ExampleModule::KEY_SHOULD_BE_MODULE = I::Am::A::Module
25
+
26
+ RConfigurator can create these for you (before you've even defined the modules
27
+ themselves!) if you point it to the following .yml file:
28
+
29
+ key: value
30
+ numeric_data: 3.221
31
+ sample_module:
32
+ some_key: another value
33
+ key_should_be_module: I::Am::A::Module
34
+
35
+
36
+ RConfigurator even handles some common edge cases for you, in particular the case
37
+ when the value is itself a module. RConfigurator will construct the module context
38
+ in place just before it needs a reference.
39
+
40
+ For a better feel of how this ends up being useful, or perhaps some inspiration,
41
+ here's an example of part of a real configuration file I am using for another small project:
42
+
43
+ version: 0.3.9
44
+ release: alpha
45
+ authors: joseph weissman
46
+ license: artistic license <http://www.perlfoundation.org/artistic_license_2_0>
47
+
48
+ # support module config
49
+ support:
50
+ logging:
51
+ use_chainsaw: true
52
+ chainsaw:
53
+ hostname: 'localhost'
54
+ port: 8071
55
+
56
+ # graphics subsystem config
57
+ graphics:
58
+ default_window_options:
59
+ fullscreen: true
60
+ width: 1920
61
+ height: 1080
62
+
63
+ # ...
64
+
65
+
66
+ --- RConfig
67
+
68
+ RConfigurator comes with a debugger that will output the statements it will 'eval'. You can
69
+ invoke this utility as 'rconfig [file1] [file2] ...' assuming you have installed the gem.
70
+
71
+ Running rconfig over the first example yaml file gives us the module structure we are expecting:
72
+
73
+ module HypotheticalParentModule; module SampleModule; SOME_KEY = "another value"; end; ; end
74
+ module I; module Am; module A; module Module; end; end; end; end;
75
+ module HypotheticalParentModule; KEY_SHOULD_BE_MODULE = I::Am::A::Module; ; end
76
+ module HypotheticalParentModule; KEY = "value"; ; end
77
+ module HypotheticalParentModule; NUMERIC_DATA = 3.221; ; end
78
+
79
+
80
+
81
+ --- Problems?
82
+
83
+ Please log bug reports and enhancement proposals here, or feel free to email the author/maintainer of RConfigurator, Joseph Weissman, jweissman1986 (at) gmail.com
84
+
85
+ --- Conclusion
86
+
87
+ So far in practice, I have found that it is definitely convenient to be able to architecturally separate 'tuning' from code. I like that I can instantiate complex module structures just by adding a few lines of YAML.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => [ :spec, :install ]
data/bin/rconfig ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ unless ARGV.count > 0
4
+ puts "rconfig -- RConfiguration file verify"
5
+ puts "USAGE: rconfig [file1] [file2] ... "
6
+ end
7
+
8
+
9
+ require 'rubygems'
10
+ require 'rconfigurator'
11
+ require 'yaml'
12
+
13
+ ARGV.each do |config_file|
14
+ RConfigurator.configure!("HypotheticalParentModule", config_file, true)
15
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require 'rconfigurator/version'
4
+ Gem::Specification.new do |s|
5
+ s.name = "rconfigurator"
6
+ s.version = RConfigurator::VERSION
7
+ s.authors = ["Joseph Weissman"]
8
+ s.email = ["jweissman1986@gmail.com"]
9
+ s.homepage = ""
10
+ s.summary = %q{RConfigurator "hydrates" your Ruby application's module constants by walking
11
+ through a yaml file}
12
+ s.description = %q{Got constants strewn throughout your project?
13
+ You can use RConfigurator to aggregate their definitions into one place.}
14
+
15
+ s.rubyforge_project = "rconfigurator"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ # specify any dependencies here; for example:
23
+ # s.add_development_dependency "rspec"
24
+ # s.add_runtime_dependency "rest-client"
25
+ # s.add_runtime_dependency "rspec"
26
+ end
@@ -0,0 +1,89 @@
1
+ require "rconfigurator/version"
2
+ require "rconfigurator/utilities"
3
+ # require "rconfigurator/configurator"
4
+
5
+
6
+ # make a 'binding' to the local scope visible
7
+ $__global_scope = binding()
8
+
9
+ module RConfigurator
10
+
11
+ #
12
+ # Use this configure! method to both create a new configurator AND
13
+ # launch the configuration process in one go.
14
+ #
15
+ def self.configure!(name, file, debug=false)
16
+ configurator = Configurator.new(name, file)
17
+ configurator.configure(debug)
18
+ end
19
+
20
+ #
21
+ # "Hydrate" a Ruby application's module constants from a configuration .yml
22
+ #
23
+ class Configurator
24
+
25
+ include StringUtilities
26
+
27
+ #
28
+ # Configurator.new takes the name of the project and a configuration file
29
+ # It does not perform any configuration yet; you must also call configure
30
+ # if RConfigurator is invoked this way.
31
+ #
32
+ def initialize(project_name, config_file, opts={})
33
+ @project_name = project_name
34
+ @config_file = config_file
35
+ @data = YAML::load(File.open(@config_file)).to_hash
36
+ end
37
+
38
+ #
39
+ # Kicks off our recursive enumeration of the configuration
40
+ # data and module constant generation business logic.
41
+ #
42
+ def configure(debug=false)
43
+ parse_and_recursively_create_constants!(@data, [], debug)
44
+ end
45
+
46
+ #
47
+ # configure application based on an easily-managed .yml file -- use 'eval'
48
+ # to generate constants based on the structure of the hash we get from the yaml.
49
+ # most of the business logic for recursively parsing a hash and creating module
50
+ # constants basically just involves tracking module names properly.
51
+ #
52
+ def parse_and_recursively_create_constants!(hash, module_context = [], debug=false)
53
+ hash.each do |key, value|
54
+ if value.is_a? Hash
55
+ module_name = convert_string_to_camel_case(key)
56
+ context = module_context.dup << module_name
57
+ parse_and_recursively_create_constants!(hash[key], context, debug)
58
+ else
59
+ value_is_a_module = false
60
+
61
+ if value.is_a? String
62
+ if value.include? "::"
63
+ value_is_a_module = true
64
+ else
65
+ value = "\"#{value}\""
66
+ end
67
+ end
68
+
69
+ if value_is_a_module
70
+ # explicitly build out this module (since it doesn't exist) so that we can talk about it
71
+ expression = value.split('::').map { |module_name| "module #{module_name}; "}.join(' ')
72
+ value.split('::').count.times { expression << "end; "}
73
+ eval(expression, $__global_scope)
74
+ puts(expression) if debug
75
+ end
76
+
77
+ # define the given constant
78
+ depth = module_context.count
79
+ expr = module_context.map { |module_name| "module #{module_name}; " }.join(" ")
80
+ expr << "#{key.upcase} = #{value}; "
81
+ depth.times { expr << "end; "}
82
+ expr = "module #{@project_name}; #{expr}; end"
83
+ eval(expr, $__global_scope)
84
+ puts(expr) if debug
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1 @@
1
+ # placeholder for gem process, apparently? any, the real logic is in rconfigurator/configurator.rb
@@ -0,0 +1,13 @@
1
+ module RConfigurator
2
+
3
+ #
4
+ # takes a string_with_underbars and ConvertsToCamelCase
5
+ #
6
+ module StringUtilities
7
+ def convert_string_to_camel_case(string)
8
+ new_string = string.gsub(/^[a-z]|_+[a-z]/) { |a| a.upcase }
9
+ new_string.gsub!('_', '')
10
+ new_string
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module RConfigurator
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,27 @@
1
+ libs = %w[ lib/ ]
2
+ libs.each { |lib| $:.unshift lib unless $:.include? lib }
3
+
4
+ require 'rconfigurator'
5
+
6
+ describe RConfigurator, "performs dynamic Ruby application initialization" do
7
+ it "parses a yaml configuration file and generates module constants" do
8
+ # p RConfigurator.methods - Module.methods
9
+
10
+ RConfigurator.configure!("ExampleModuleName", "spec/resources/sample.yml")
11
+
12
+ # n.b., these values are defined in the config file at spec/resources/sample.yml
13
+ ExampleModuleName::KEY.should == 'value'
14
+ end
15
+ it "should construct numeric constants correctly" do
16
+ ExampleModuleName::NUMERIC_DATA.should == 3.221
17
+ end
18
+
19
+ it "should handle nested constants" do
20
+ ExampleModuleName::SampleModule::SOME_KEY.should == 'another value'
21
+ end
22
+
23
+ it "should explicitly construct modules if passed as values" do
24
+ ExampleModuleName::KEY_SHOULD_BE_MODULE.should be_a_kind_of(Module)
25
+ ExampleModuleName::KEY_SHOULD_BE_MODULE.should == I::Am::A::Module
26
+ end
27
+ end
@@ -0,0 +1,23 @@
1
+ ###########################################
2
+ #
3
+ # testing config file
4
+ #
5
+ #
6
+
7
+ key: value
8
+ numeric_data: 3.221
9
+
10
+ sample_module:
11
+ some_key: another value
12
+
13
+ key_should_be_module: I::Am::A::Module
14
+
15
+ #
16
+ # So, RConfigurator.configure! should create
17
+ #
18
+ # Sample::KEY = value
19
+ # Sample::NUMERIC_DATA = 3.221
20
+ # Sample::SampleModule::SOME_KEY = 'another value'
21
+ #
22
+ # ...etc.
23
+ #
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rconfigurator
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 2
10
+ version: 0.0.2
11
+ platform: ruby
12
+ authors:
13
+ - Joseph Weissman
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-09-23 00:00:00 Z
19
+ dependencies: []
20
+
21
+ description: |-
22
+ Got constants strewn throughout your project?
23
+ You can use RConfigurator to aggregate their definitions into one place.
24
+ email:
25
+ - jweissman1986@gmail.com
26
+ executables:
27
+ - rconfig
28
+ extensions: []
29
+
30
+ extra_rdoc_files: []
31
+
32
+ files:
33
+ - .gitignore
34
+ - Gemfile
35
+ - LICENSE.txt
36
+ - README
37
+ - Rakefile
38
+ - bin/rconfig
39
+ - configurator.gemspec
40
+ - lib/rconfigurator.rb
41
+ - lib/rconfigurator/configurator.rb
42
+ - lib/rconfigurator/utilities.rb
43
+ - lib/rconfigurator/version.rb
44
+ - spec/rconfigurator/rconfigurator_spec.rb
45
+ - spec/resources/sample.yml
46
+ homepage: ""
47
+ licenses: []
48
+
49
+ post_install_message:
50
+ rdoc_options: []
51
+
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ hash: 3
60
+ segments:
61
+ - 0
62
+ version: "0"
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ hash: 3
69
+ segments:
70
+ - 0
71
+ version: "0"
72
+ requirements: []
73
+
74
+ rubyforge_project: rconfigurator
75
+ rubygems_version: 1.8.5
76
+ signing_key:
77
+ specification_version: 3
78
+ summary: RConfigurator "hydrates" your Ruby application's module constants by walking through a yaml file
79
+ test_files:
80
+ - spec/rconfigurator/rconfigurator_spec.rb
81
+ - spec/resources/sample.yml