context_builder 1.0.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: dc7094c8368581bb8a384b57deac815028f2c015
4
+ data.tar.gz: 5835eed9347d8f2da14a68ef37304038bdd54142
5
+ SHA512:
6
+ metadata.gz: 1b476f296a9e08a26102a914b413c96e678825bf40eade145dd811786bc23f617219f4f5eed2c84ed5c476b5653f7096b0cc47b339049c5b2f8f459371cb5f2f
7
+ data.tar.gz: c6c958d2ddee170cab52e0c90f0fdabc18748afdfe7675398f2a1df86b554689bb2689f181bc9d6e40e77ca8099d4fec893665bdc6905df17ee2b58a005ae17f
data/.gitignore ADDED
@@ -0,0 +1,22 @@
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
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 David McCullars
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 David McCullars
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.
data/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # ContextBuilder
2
+
3
+ This gem provides a way of extending modules with context attributes. Modules
4
+ that extend Context will receive the class method :context_attr which is
5
+ used to specify one or more context attributes that the extended module provides.
6
+ Each of these attributes will be accessible by name on classes that include the
7
+ extended module. The value of that method is determined as the first non-nil
8
+ value from a hash provided to initialize_context or one of any number of lookup_NAME
9
+ methods in the class or any module included by the class.
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ gem 'context_builder'
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install context_builder
24
+
25
+ ## Example
26
+
27
+ module Personage
28
+
29
+ extend ContextBuilder
30
+
31
+ context_attr :name, :age
32
+ context_attr(:race) { |options| options[:race] || options[:ethnicity] }
33
+
34
+ def lookup_age
35
+ ENV['AGE']
36
+ end
37
+
38
+ end
39
+
40
+ class User
41
+
42
+ include Personage
43
+
44
+ def initialize(name)
45
+ initialize_context(:name => name, :ethnicity => 'unknown')
46
+ end
47
+
48
+ def lookup_age
49
+ 'N/A' unless name == 'Greg'
50
+ end
51
+
52
+ end
53
+
54
+ User.new('Fred').inspect
55
+ >> #<User name=Fred age=N/A race=unknown>
56
+
57
+ ENV['AGE'] = '27'
58
+ User.new('Greg').inspect
59
+ >> #<User name=Greg age=27 race=unknown>
60
+
61
+ ## Usage Notes
62
+
63
+ It is important to place 'extend Context' AFTER any self.included methods
64
+ defined on the extended module. Otherwise, the self.included method will
65
+ overwrite the one from Context, rendering the 'extend' useless.
66
+
67
+ ## Contributing
68
+
69
+ 1. Fork it ( https://github.com/[my-github-username]/context_builder/fork )
70
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
71
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
72
+ 4. Push to the branch (`git push origin my-new-feature`)
73
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'context_builder/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "context_builder"
8
+ spec.version = ContextBuilder::VERSION
9
+ spec.authors = ["David McCullars"]
10
+ spec.email = ["david.mccullars@gmail.com"]
11
+ spec.summary = %q{This gem provides a way of extending modules with context attributes.}
12
+ spec.description = %q{This gem provides a way of extending modules with context attributes.}
13
+ spec.homepage = "https://github.com/david-mccullars/context_builder"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.6"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency 'rspec', '~> 2.14'
24
+ spec.add_development_dependency 'simplecov', '~> 0.8'
25
+ spec.add_development_dependency 'simplecov-html', '~> 0.8'
26
+ spec.add_development_dependency 'simplecov-rcov', '~> 0.2'
27
+ end
@@ -0,0 +1,25 @@
1
+ require "context_builder/version"
2
+
3
+ module ContextBuilder
4
+
5
+ autoload :BaseClassDefiner, 'context_builder/base_class_definer'
6
+
7
+ def self.extended(base_mod)
8
+ base_mod.module_eval do
9
+ @__context_attrs = {}
10
+ end
11
+
12
+ orig_included = base_mod.method(:included)
13
+ base_mod.define_singleton_method(:included) do |base_class|
14
+ BaseClassDefiner.new(base_class).define_all(@__context_attrs)
15
+ orig_included.call(base_class)
16
+ end
17
+ end
18
+
19
+ def context_attr(*names, &block)
20
+ names.flatten.each do |name|
21
+ @__context_attrs[name.to_sym] = block
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,66 @@
1
+ module ContextBuilder
2
+ class BaseClassDefiner
3
+
4
+ attr_reader :base_class
5
+
6
+ def initialize(base_class)
7
+ @base_class = base_class
8
+ end
9
+
10
+ def define_all(all_attrs)
11
+ define_initialize_context_method(all_attrs)
12
+ define_all_attr_methods(all_attrs)
13
+ define_context_method(all_attrs)
14
+ define_to_hash_method(all_attrs)
15
+ define_inspect_method(all_attrs)
16
+ end
17
+
18
+ private
19
+
20
+ def define_initialize_context_method(all_attrs)
21
+ base_class.send(:define_method, :initialize_context) do |options|
22
+ all_attrs.each do |name, block|
23
+ @__context ||= {}
24
+ @__context[name] = block ? block.call(options) : options[name]
25
+ end
26
+ end
27
+ end
28
+
29
+ def define_all_attr_methods(all_attrs)
30
+ all_attrs.keys.each do |name|
31
+ base_class.send(:define_method, name) do
32
+ @__context ||= {}
33
+ @__context[name] ||= [self.class, *self.class.included_modules].reduce(nil) do |val, mod|
34
+ val ||= begin
35
+ if mod.method_defined? "lookup_#{name}"
36
+ mod.instance_method("lookup_#{name}").bind(self).call
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ def define_context_method(all_attrs)
45
+ base_class.send(:define_method, :context) do
46
+ all_attrs.keys.reduce({}) do |hash, name|
47
+ hash.merge! name => send(name)
48
+ end
49
+ end
50
+ end
51
+
52
+ def define_to_hash_method(all_attrs)
53
+ base_class.send(:define_method, :to_hash) do
54
+ context
55
+ end
56
+ end
57
+
58
+ def define_inspect_method(all_attrs)
59
+ base_class.send(:define_method, :inspect) do
60
+ data = to_hash.map { |a| a.join '=' }.join ', '
61
+ "#<#{self.class.name} #{data}>"
62
+ end
63
+ end
64
+
65
+ end
66
+ end
@@ -0,0 +1,3 @@
1
+ module ContextBuilder
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+ require 'context_builder'
3
+
4
+ describe ContextBuilder do
5
+
6
+ let(:clazz) do
7
+ Class.new do
8
+ def lookup_bar
9
+ 'bar from clazz'
10
+ end
11
+ def self.name
12
+ 'TestClass'
13
+ end
14
+ end
15
+ end
16
+
17
+ let(:mod) do
18
+ Module.new do
19
+ extend ContextBuilder
20
+
21
+ context_attr :foo, :bar
22
+ context_attr(:baz) { |options| options[:not_baz] }
23
+
24
+ def lookup_bar
25
+ 'bar from mod'
26
+ end
27
+
28
+ def lookup_foo
29
+ 'foo from mod'
30
+ end
31
+ end
32
+ end
33
+
34
+ subject { clazz.tap { |c| c.send(:include, mod) }.new }
35
+
36
+ specify 'initialize context with options' do
37
+ subject.initialize_context(:foo => 12, :bar => 'stuff', :not_baz => 'weird, huh?')
38
+ expect(subject.to_hash).to eq(:foo => 12, :bar => 'stuff', :baz => 'weird, huh?')
39
+ end
40
+
41
+ specify 'initialize context from lookups' do
42
+ expect(subject.to_hash).to eq(:foo => 'foo from mod', :bar => 'bar from clazz', :baz => nil)
43
+ end
44
+
45
+ specify 'provides inspect method on extended modules' do
46
+ expect(subject.inspect).to eq('#<TestClass foo=foo from mod, bar=bar from clazz, baz=>')
47
+ end
48
+
49
+ specify 'preserve included on extended modules' do
50
+ mod2 = Module.new do
51
+ def self.included(base)
52
+ base.send(:define_method, :inspect) do
53
+ 'preserved inspect'
54
+ end
55
+ end
56
+ extend ContextBuilder
57
+ end
58
+ clazz2 = Class.new { include mod2 }
59
+ expect(clazz2.new.inspect).to eq('preserved inspect')
60
+ end
61
+
62
+ specify 'overwrite included on extended modules' do
63
+ mod.module_eval do
64
+ def self.included(base)
65
+ # By defining this AFTER 'extend Context', we kill self.included
66
+ # and prevent Context from doing anything to clazz
67
+ end
68
+ end
69
+ expect { subject.initialize_context }.to raise_error(/undefined method/)
70
+ end
71
+
72
+ end
@@ -0,0 +1,10 @@
1
+ require 'rspec'
2
+ require 'simplecov'
3
+ require 'simplecov-rcov'
4
+ SimpleCov.start
5
+ SimpleCov.formatter = Class.new do
6
+ def format(result)
7
+ SimpleCov::Formatter::HTMLFormatter.new.format(result)
8
+ SimpleCov::Formatter::RcovFormatter.new.format(result)
9
+ end
10
+ end
metadata ADDED
@@ -0,0 +1,142 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: context_builder
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - David McCullars
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
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'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.14'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.14'
55
+ - !ruby/object:Gem::Dependency
56
+ name: simplecov
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.8'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.8'
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov-html
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.8'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.8'
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov-rcov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.2'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.2'
97
+ description: This gem provides a way of extending modules with context attributes.
98
+ email:
99
+ - david.mccullars@gmail.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - Gemfile
106
+ - LICENSE
107
+ - LICENSE.txt
108
+ - README.md
109
+ - Rakefile
110
+ - context_builder.gemspec
111
+ - lib/context_builder.rb
112
+ - lib/context_builder/base_class_definer.rb
113
+ - lib/context_builder/version.rb
114
+ - spec/lib/context_builder_spec.rb
115
+ - spec/spec_helper.rb
116
+ homepage: https://github.com/david-mccullars/context_builder
117
+ licenses:
118
+ - MIT
119
+ metadata: {}
120
+ post_install_message:
121
+ rdoc_options: []
122
+ require_paths:
123
+ - lib
124
+ required_ruby_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ required_rubygems_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ requirements: []
135
+ rubyforge_project:
136
+ rubygems_version: 2.2.2
137
+ signing_key:
138
+ specification_version: 4
139
+ summary: This gem provides a way of extending modules with context attributes.
140
+ test_files:
141
+ - spec/lib/context_builder_spec.rb
142
+ - spec/spec_helper.rb