abyss 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in abyss.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ gem 'rspec'
8
+ gem 'autotest'
9
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Jesse Trimble
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,46 @@
1
+ # Abyss
2
+
3
+ Ruby DSL for defining arbitrarily-deep configuration.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'abyss'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install abyss
18
+
19
+ ## Usage
20
+
21
+ Abyss.configure do
22
+
23
+ # An arbitrarily-named configuration group
24
+ #
25
+ rush do
26
+
27
+ # Define arbitrary properties
28
+ #
29
+ year_founded '1968'
30
+ members ["Geddy", "Alex", "Neil"]
31
+
32
+ end
33
+
34
+ end
35
+
36
+ # Accessing...
37
+ Abyss.configuration.rush.year_founded #=> "1968"
38
+ Abyss.configuration.rush.members #=> ["Geddy", "Alex", "Neil"]
39
+
40
+ ## Contributing
41
+
42
+ 1. Fork it
43
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
44
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
45
+ 4. Push to the branch (`git push origin my-new-feature`)
46
+ 5. Create new Pull Request
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/abyss/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Jesse Trimble"]
6
+ gem.email = ["jesseltrimble@gmail.com"]
7
+ gem.description = %q{Manage arbitrarily-deep configurations through a friendly DSL.}
8
+ gem.summary = %q{Manage arbitrarily-deep configurations through a friendly DSL.}
9
+ gem.homepage = ""
10
+
11
+ gem.add_dependency "activesupport", '~> 3.2.0'
12
+
13
+ gem.files = `git ls-files`.split($\)
14
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
15
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
16
+ gem.name = "abyss"
17
+ gem.require_paths = ["lib"]
18
+ gem.version = Abyss::VERSION
19
+ end
@@ -0,0 +1,20 @@
1
+ require "abyss/version"
2
+ require "abyss/errors"
3
+ require "abyss/deep_store"
4
+ require "abyss/store"
5
+
6
+ module Abyss
7
+
8
+ class << self
9
+ attr_accessor :configuration
10
+ end
11
+
12
+ # Public interface to Abyss Configuragion API
13
+ # See Store for examples.
14
+ #
15
+ def self.configure(&block)
16
+ self.configuration ||= Store.new
17
+ self.configuration.instance_eval &block
18
+ end
19
+
20
+ end
@@ -0,0 +1,82 @@
1
+ require 'active_support/ordered_hash'
2
+
3
+ module Abyss
4
+
5
+ # = DeepStore
6
+ # === Abstract Class
7
+ #
8
+ # An object meant for configuration that allows arbitrary configuration
9
+ # properties and arbitrarily deep configuration groups.
10
+ #
11
+ # Meant to be subclassed. The power of this class lies in the 'assign'
12
+ # method.
13
+ #
14
+ # Examples:
15
+ #
16
+ # class MyConfig < DeepStore
17
+ #
18
+ # def assign(property_name, values)
19
+ # # values is an array of the arguments picked up by #method_missing
20
+ # self.configurations[property_name] = manipulate(values)
21
+ # end
22
+ #
23
+ # private
24
+ #
25
+ # def manipulate(values)
26
+ # # something important...
27
+ # values
28
+ # end
29
+ #
30
+ # end
31
+ #
32
+ # my_config = MyConfig.new
33
+ # my_config.my_config_group do # arbitrary configuration group
34
+ # my_configuration_property "Hardy har!", "Grumblegrumblegrumble..." # configuration item, also arbitrary
35
+ # end
36
+ #
37
+ # my_config.my_config_group.my_configuration_property #=> [ "Hardy har!", "Grumblegrumblegrumble..." ]
38
+ #
39
+ class DeepStore
40
+
41
+ attr_accessor :configurations
42
+
43
+ def initialize #:nodoc:
44
+ @configurations = ActiveSupport::OrderedHash.new {}
45
+ end
46
+
47
+ # If a block is passed, add a configuration group named `method_name`
48
+ # (which is just a new instance of DeepStore) and evaluate the block
49
+ # against the new instance.
50
+ #
51
+ # If one or more arguments are supplied, calls `#assign(method_name, args)
52
+ #
53
+ # If no arguments are supplied, return the entity stored by `method_name`.
54
+ # Could be a DeepStore instance or some arbitrary configuration.
55
+ #
56
+ def method_missing(method_name, *args, &block)
57
+ raise ArgumentError.new("Can't supply both a method argument and a block.") if block_given? && args.size > 0
58
+
59
+ if block_given?
60
+ @configurations[method_name] ||= self.class.new
61
+ @configurations[method_name].instance_eval &block
62
+ end
63
+
64
+ return get(method_name) if args.length == 0
65
+
66
+ assign(method_name, args)
67
+ end
68
+
69
+ # Abstract method. Override this in a subclass to do processing on the
70
+ # config name / value to be stored.
71
+ #
72
+ def assign(name, values)
73
+ raise Errors::AbstractMethod.new("#assign")
74
+ end
75
+
76
+ def get(method_name) #:nodoc:
77
+ @configurations[method_name]
78
+ end
79
+
80
+ end
81
+
82
+ end
@@ -0,0 +1,19 @@
1
+ module Abyss
2
+
3
+ module Errors
4
+
5
+ class AbstractMethod < RuntimeError
6
+ attr_accessor :name
7
+
8
+ def initialize(name)
9
+ self.name = name
10
+ end
11
+
12
+ def message
13
+ "Abstract method: must override #{name} in a base class."
14
+ end
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,34 @@
1
+ module Abyss
2
+
3
+ # = Store
4
+ #
5
+ # Utility for Abyss configuration.
6
+ # Intended for use within a host app's initializer, eg:
7
+ # /config/initializers/foundation.rb
8
+ #
9
+ # Examples:
10
+ #
11
+ # Abyss.configure do
12
+ # title 'Abyss Demo'
13
+ #
14
+ # backend do
15
+ # support do
16
+ # email 'info@factorylabs.com'
17
+ # phone '303-555-1234'
18
+ # end
19
+ # end
20
+ #
21
+ # end
22
+ #
23
+ class Store < DeepStore
24
+
25
+ # Overrides DeepStore#assign. Simply assigns the configuration name to the
26
+ # first value.
27
+ #
28
+ def assign(name, values)
29
+ self.configurations[name] = values.first
30
+ end
31
+
32
+ end
33
+
34
+ end
@@ -0,0 +1,3 @@
1
+ module Abyss
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,116 @@
1
+ require 'spec_helper'
2
+
3
+ module Abyss
4
+
5
+ describe ".configure" do
6
+
7
+ before { Abyss.configuration = nil }
8
+
9
+ it 'is shorthand for the Abyss Config API' do
10
+ expected_block = Proc.new { }
11
+ fake_config = mock()
12
+ Store.stub(:new).and_return(fake_config)
13
+ fake_config.should_receive(:instance_eval).with(&expected_block)
14
+
15
+ Abyss.configure &expected_block
16
+ end
17
+
18
+ end
19
+
20
+ describe DeepStore do
21
+
22
+ context "when dealing directly with an instance of DeepStore" do
23
+
24
+ subject { DeepStore.new }
25
+
26
+ describe "#initialize" do
27
+
28
+ it 'sets its #configurations to an empty OrderedHash' do
29
+ subject.configurations.should == ActiveSupport::OrderedHash.new
30
+ end
31
+
32
+ end
33
+
34
+ describe "#get" do
35
+
36
+ it "returns what is stored in its #configurations" do
37
+ subject.configurations = { thing: 'foo' }
38
+ subject.get(:thing).should == 'foo'
39
+ end
40
+
41
+ end
42
+
43
+ describe "#assign" do
44
+
45
+ it 'raises an error about subclassing' do
46
+ expect {
47
+ subject.some_nonexistent_method "foo"
48
+ }.to raise_error /must override #assign in a base class/i
49
+ end
50
+
51
+ end
52
+
53
+ describe "#method_missing behavior" do
54
+
55
+ context "when given a block and no args" do
56
+
57
+ let(:config_mock) { mock }
58
+ let(:empty_proc) { proc {} }
59
+
60
+ before do
61
+ # force evaluation since we stub :new
62
+ subject
63
+ end
64
+
65
+ it "creates a new named configuration group" do
66
+ subject.some_undefined_method &empty_proc
67
+ subject.some_undefined_method.should be_instance_of subject.class
68
+ end
69
+
70
+ it "evaluates the block against a new configuration instance" do
71
+ DeepStore.stub(:new).and_return(config_mock)
72
+ config_mock.should_receive(:instance_eval).with &empty_proc
73
+ subject.some_undefined_method &empty_proc
74
+ end
75
+
76
+ end
77
+
78
+ context "with no arguments and no block" do
79
+
80
+ it "returns a configuration stored by the method name" do
81
+ subject.should_receive(:get).with(:some_undefined_method)
82
+ subject.some_undefined_method
83
+ end
84
+
85
+ end
86
+
87
+ context "with an argument" do
88
+
89
+ it "calls #assign on itself, passing the method name and args list" do
90
+ subject.should_receive(:assign).with(:some_undefined_method, ['foo'])
91
+ subject.some_undefined_method 'foo'
92
+ end
93
+
94
+ end
95
+
96
+ describe "invalid scenarios" do
97
+
98
+ context "with an argument and a block" do
99
+
100
+ it "raises an InvalidArguemnt error" do
101
+ expect {
102
+ subject.some_undefined_method("foo") {}
103
+ }.to raise_error ArgumentError, /can't supply both a method argument and a block/i
104
+ end
105
+
106
+ end
107
+
108
+ end
109
+
110
+ end
111
+
112
+ end
113
+
114
+ end
115
+
116
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ module Abyss
4
+
5
+ describe ".configure" do
6
+
7
+ before { Abyss.configuration = nil }
8
+
9
+ it 'is shorthand for the Abyss Store API' do
10
+ expected_block = Proc.new { }
11
+ fake_config = mock()
12
+ Store.stub(:new).and_return(fake_config)
13
+ fake_config.should_receive(:instance_eval).with(&expected_block)
14
+
15
+ Abyss.configure &expected_block
16
+ end
17
+
18
+ end
19
+
20
+ describe Store do
21
+
22
+ subject { Store.new }
23
+
24
+ it "is a subclass of DeepStore" do
25
+ subject.should be_a DeepStore
26
+ end
27
+
28
+ describe "#assign" do
29
+
30
+ it "assigns the method name to the first passed value in #configurations" do
31
+ subject.assign("thing", ["foo"])
32
+ subject.configurations["thing"].should == "foo"
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1 @@
1
+ require 'abyss'
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: abyss
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jesse Trimble
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-11 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activesupport
16
+ requirement: &70310377219460 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 3.2.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70310377219460
25
+ description: Manage arbitrarily-deep configurations through a friendly DSL.
26
+ email:
27
+ - jesseltrimble@gmail.com
28
+ executables: []
29
+ extensions: []
30
+ extra_rdoc_files: []
31
+ files:
32
+ - .gitignore
33
+ - .rspec
34
+ - Gemfile
35
+ - LICENSE
36
+ - README.md
37
+ - Rakefile
38
+ - abyss.gemspec
39
+ - lib/abyss.rb
40
+ - lib/abyss/deep_store.rb
41
+ - lib/abyss/errors.rb
42
+ - lib/abyss/store.rb
43
+ - lib/abyss/version.rb
44
+ - spec/abyss/deep_store_spec.rb
45
+ - spec/abyss/store_spec.rb
46
+ - spec/spec_helper.rb
47
+ homepage: ''
48
+ licenses: []
49
+ post_install_message:
50
+ rdoc_options: []
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ! '>='
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ requirements: []
66
+ rubyforge_project:
67
+ rubygems_version: 1.8.10
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: Manage arbitrarily-deep configurations through a friendly DSL.
71
+ test_files:
72
+ - spec/abyss/deep_store_spec.rb
73
+ - spec/abyss/store_spec.rb
74
+ - spec/spec_helper.rb