canister 0.9.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: 8d69f8befb7b0da9e4d982db5a64988fcc6d540e
4
+ data.tar.gz: e4cd5da5bfc6cfad289ede2651b55ccaeb165f8e
5
+ SHA512:
6
+ metadata.gz: ece48adf544fa81cae520ded5e0ec262090d257ada284449c4b59702a8e20c34c1e4e55c8273f57905be2e8791d4032ac03feb94c22dfe01f06e0ec46b84e775
7
+ data.tar.gz: cea1b3678cd466155d63e3ab6bff4b4ea0fd82eeda8e22a0a36a660f9b5e1cf046cd8e3ecdc8f17db32021c0c3752e843d4102cc4c9f99d5f626610c83d3efb7
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /Gemfile.lock
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,144 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
3
+ AllCops:
4
+ DisplayCopNames: true
5
+ TargetRubyVersion: 2.3
6
+ Exclude:
7
+ - '*.gemspec'
8
+
9
+ Naming/FileName:
10
+ ExpectMatchingDefinition: true
11
+ Exclude:
12
+ - 'bin/**/*'
13
+ - 'spec/**/*'
14
+ - 'lib/*/version.rb'
15
+
16
+ Style/Documentation:
17
+ Exclude:
18
+ - 'spec/**/*'
19
+
20
+ # We disable this cop because we want to use Pathname#/
21
+ # and this cop is not configurable at all.
22
+ Layout/SpaceAroundOperators:
23
+ Enabled: false
24
+
25
+ Security/YAMLLoad:
26
+ Exclude:
27
+ - 'spec/**/*'
28
+
29
+ Style/Alias:
30
+ EnforcedStyle: prefer_alias_method
31
+
32
+ Metrics/LineLength:
33
+ Max: 100
34
+ AllowHeredoc: true
35
+ AllowURI: true
36
+ URISchemes:
37
+ - http
38
+ - https
39
+
40
+ Metrics/BlockLength:
41
+ Exclude:
42
+ - 'spec/**/*_spec.rb'
43
+
44
+ Layout/ElseAlignment:
45
+ Enabled: false
46
+
47
+ Layout/FirstParameterIndentation:
48
+ EnforcedStyle: consistent
49
+
50
+ Layout/AlignParameters:
51
+ EnforcedStyle: with_fixed_indentation
52
+
53
+ Layout/CaseIndentation:
54
+ EnforcedStyle: end
55
+
56
+ Layout/ClosingParenthesisIndentation:
57
+ Enabled: false
58
+
59
+ Style/ClassAndModuleChildren:
60
+ EnforcedStyle: nested
61
+
62
+ Style/CommentAnnotation:
63
+ Enabled: false
64
+
65
+ # Does not work for multi-line copyright notices.
66
+ Style/Copyright:
67
+ Enabled: false
68
+
69
+ Layout/EmptyLineBetweenDefs:
70
+ AllowAdjacentOneLineDefs: true
71
+
72
+ # These two cops do not differentiate between the scope the file is describing
73
+ # and any namespaces it is nested under. If this is not acceptable,
74
+ # no_empty_lines produces the least offensive results.
75
+ Layout/EmptyLinesAroundClassBody:
76
+ Enabled: false
77
+ Layout/EmptyLinesAroundModuleBody:
78
+ Enabled: false
79
+
80
+ # Produces poor results.
81
+ Style/GuardClause:
82
+ Enabled: false
83
+
84
+ Style/IfUnlessModifier:
85
+ Enabled: false
86
+
87
+ Layout/IndentArray:
88
+ EnforcedStyle: consistent
89
+
90
+ Layout/IndentHash:
91
+ EnforcedStyle: consistent
92
+
93
+ Layout/AlignHash:
94
+ EnforcedColonStyle: table
95
+ EnforcedHashRocketStyle: table
96
+ EnforcedLastArgumentHashStyle: always_ignore
97
+
98
+ Layout/MultilineMethodCallIndentation:
99
+ EnforcedStyle: indented
100
+
101
+ Layout/MultilineOperationIndentation:
102
+ EnforcedStyle: indented
103
+
104
+ # Produces poor results.
105
+ Style/Next:
106
+ Enabled: false
107
+
108
+ Style/RedundantReturn:
109
+ AllowMultipleReturnValues: true
110
+
111
+ Style/RegexpLiteral:
112
+ AllowInnerSlashes: true
113
+
114
+ Style/Semicolon:
115
+ AllowAsExpressionSeparator: true
116
+
117
+ Style/StringLiterals:
118
+ EnforcedStyle: double_quotes
119
+
120
+ Style/StringLiteralsInInterpolation:
121
+ EnforcedStyle: double_quotes
122
+
123
+ Layout/SpaceInsideBlockBraces:
124
+ SpaceBeforeBlockParameters: false
125
+
126
+ Style/SymbolArray:
127
+ EnforcedStyle: brackets
128
+
129
+ Lint/BlockAlignment:
130
+ EnforcedStyleAlignWith: start_of_block
131
+ #EnforcedStyleAlignWith: start_of_line
132
+
133
+ Lint/EndAlignment:
134
+ EnforcedStyleAlignWith: start_of_line
135
+
136
+ Lint/DefEndAlignment:
137
+ EnforcedStyleAlignWith: def
138
+
139
+ Performance/RedundantMerge:
140
+ Enabled: false
141
+
142
+ Style/WordArray:
143
+ EnforcedStyle: brackets
144
+
data/.rubocop_todo.yml ADDED
File without changes
data/.travis.yml ADDED
@@ -0,0 +1,28 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4
5
+ - 2.3
6
+
7
+ branches:
8
+ only:
9
+ - master
10
+ - develop
11
+
12
+ env:
13
+ global:
14
+ - CC_TEST_REPORTER_ID=a492448053c934b2a3cfa2f86f3357491d11beda5499db7884ae13859870fd29
15
+
16
+ before_install: gem install bundler
17
+
18
+ before_script:
19
+ - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
20
+ - chmod +x ./cc-test-reporter
21
+ - ./cc-test-reporter before-build
22
+
23
+ script:
24
+ - bundle exec rspec --order=random
25
+
26
+ after_script:
27
+ - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT || true
28
+
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
6
+
7
+ # Specify your gem's dependencies in closet.gemspec
8
+ gemspec
9
+
10
+ group :development, :test do
11
+ gem "pry"
12
+ end
data/LICENSE.md ADDED
@@ -0,0 +1,27 @@
1
+ Copyright (c) 2018, The Regents of the University of Michigan.
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are
6
+ met:
7
+
8
+ * Redistributions of source code must retain the above copyright
9
+ notice, this list of conditions and the following disclaimer.
10
+ * Redistributions in binary form must reproduce the above copyright
11
+ notice, this list of conditions and the following disclaimer in the
12
+ documentation and/or other materials provided with the distribution.
13
+ * Neither the name of the The University of Michigan nor the
14
+ names of its contributors may be used to endorse or promote products
15
+ derived from this software without specific prior written permission.
16
+
17
+ THIS SOFTWARE IS PROVIDED BY THE REGENTS OF THE UNIVERSITY OF MICHIGAN AND
18
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
19
+ NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE
21
+ UNIVERSITY OF MICHIGAN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
23
+ TO,PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,100 @@
1
+ # Canister
2
+
3
+ [![Build Status](https://travis-ci.org/mlibrary/canister.svg?branch=master)](https://travis-ci.org/mlibrary/canister)
4
+ [![Maintainability](https://api.codeclimate.com/v1/badges/590e17334ea92100e297/maintainability)](https://codeclimate.com/github/mlibrary/canister/maintainability)
5
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/590e17334ea92100e297/test_coverage)](https://codeclimate.com/github/mlibrary/canister/test_coverage)
6
+
7
+
8
+ ## Summary
9
+
10
+ Canister is a simple IoC container for ruby. It has no dependencies and provides only
11
+ the functionality you need. It does not monkey-patch ruby or pollute the global
12
+ namespace, and most importantly *it expects to be invisible to your domain classes.*
13
+
14
+ It provides:
15
+
16
+ * Out-of-order declaration
17
+ * Caching
18
+ * Automatic dependency resolution
19
+ * Automatic cache invalidation on re-registration
20
+
21
+ ## Why do I need this? Especially in ruby?
22
+
23
+ Canister was created to make it easier to declare our setup for our application's
24
+ production and test environments in a single place, without needing to know
25
+ when exactly those objects were created.
26
+
27
+ *Canister is not a replacement for
28
+ dependency injection.* Rather, it is useful when you have designed your objects
29
+ to have their dependencies injected. For example, it would be a *mistake* to write
30
+ all of your classes such that they except a single parameter called `container`.
31
+
32
+ For more information on dependency injection and inversion of control containers in
33
+ ruby, please see
34
+ [this excellent article](https://gist.github.com/malakai97/b1d3bdf6d80c6f99a875930981243f9d)
35
+ by [Blair Anderson](https://github.com/blairanderson) that both sums up the issue
36
+ and was the inspiration for this gem.
37
+
38
+
39
+ ## Installation
40
+
41
+ Add it to your Gemfile and you're off to the races.
42
+
43
+ ## Usage
44
+
45
+ ```ruby
46
+ # Basic usage
47
+ container = Canister.new
48
+ container.register(:foo) { "foo" }
49
+ container.register(:bar) {|c| c.foo + "bar" }
50
+
51
+ container.bar #=> "foobar"
52
+ container[:bar] #=> "foobar"
53
+ container["bar"] #=> "foobar"
54
+
55
+ # Dependencies can be declared in any order
56
+ container.register(:after) {|c| "#{c.before} and after" }
57
+ container.register(:before) { "before" }
58
+ container.after #=> "before and after"
59
+
60
+ # Values are cached
61
+ container.register(:wait) { sleep 3; 27 }
62
+ container.wait
63
+ .
64
+ .
65
+ .
66
+ #=================> 27
67
+ container.wait #=> 27
68
+
69
+ # Caches are invalidated automatically
70
+ container.register(:foo) { "oof" }
71
+ container.bar #=> "oofbar"
72
+ ```
73
+
74
+ ## Contributing
75
+
76
+ Standard rules apply.
77
+
78
+ ## Compatibility
79
+
80
+ * ruby 2.3.x
81
+ * ruby 2.4.x
82
+
83
+ As Canister does not rely on any specific runtime environment other than
84
+ the ruby core, it is compatible with every ruby library and framework.
85
+
86
+ ## Authors
87
+
88
+ * The author and maintainer is [Bryan Hockey](https://github.com/malakai97)
89
+ * This project was inspired by
90
+ [this excellent article](https://gist.github.com/malakai97/b1d3bdf6d80c6f99a875930981243f9d)
91
+ by [Blair Anderson](https://github.com/blairanderson). (We are not affiliated, so
92
+ don't blame him if this breaks.)
93
+
94
+ ## License
95
+
96
+ Copyright (c) 2018 The Regents of the University of Michigan.
97
+ All Rights Reserved.
98
+ Licensed according to the terms of the Revised BSD License.
99
+ See LICENSE.md for details.
100
+
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
data/canister.gemspec ADDED
@@ -0,0 +1,33 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "canister/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "canister"
8
+ spec.version = Canister::VERSION
9
+ spec.authors = ["Bryan Hockey"]
10
+ spec.email = ["bhock@umich.edu"]
11
+
12
+ spec.summary = %q{A simple IoC container for ruby.}
13
+ spec.description = %q{
14
+ Canister is a simple IoC container for ruby. It has no dependencies and provides only
15
+ the functionality you need. It does not monkey-patch ruby or pollute the global
16
+ namespace, and most importantly it expects to be invisible to your domain classes.
17
+ }
18
+ spec.homepage = "https://github.com/mlibrary/canister"
19
+ spec.license = "Revised BSD"
20
+
21
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
22
+ f.match(%r{^(test|spec|features)/})
23
+ end
24
+ spec.bindir = "exe"
25
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
+ spec.require_paths = ["lib"]
27
+
28
+ spec.add_development_dependency "bundler", "~> 1.16"
29
+ spec.add_development_dependency "rake", "~> 10.0"
30
+ spec.add_development_dependency "rspec", "~> 3.0"
31
+ spec.add_development_dependency "rubocop"
32
+ spec.add_development_dependency "simplecov"
33
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Canister
4
+ VERSION = "0.9.0"
5
+ end
data/lib/canister.rb ADDED
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "canister/version"
4
+
5
+ # A container that registers keys to values that are
6
+ # resolved at runtime. This allows for out-of-order declaration,
7
+ # automatic dependency resolution, and--upon
8
+ # redeclaration--automatic dependency cache invalidation.
9
+ class Canister
10
+
11
+ def initialize
12
+ @stack = []
13
+ @registry = {}
14
+ @resolved = {}
15
+ @dependents = Hash.new do |hash, key|
16
+ hash[key] = []
17
+ end
18
+ yield self if block_given?
19
+ end
20
+
21
+ # We override method_missing to enable dot notation
22
+ # for accessing registered values.
23
+ def method_missing(method, *args, &block)
24
+ if handles?(method)
25
+ resolve(method)
26
+ else
27
+ super(method, *args, block)
28
+ end
29
+ end
30
+
31
+ # We override respond_to? to enable dot notation
32
+ # for accessing registered values.
33
+ def respond_to_missing?(method, include_all = false)
34
+ handles?(method) || super(method, include_all)
35
+ end
36
+
37
+ # Register a value to a key by passing a block. Note that
38
+ # the value will be that returned by the block. If the key
39
+ # has been registered before, the old registration is
40
+ # overwritten. Dependents of the original registration
41
+ # are automatically invalidated.
42
+ # @param key [Symbol]
43
+ # @yield self [Container] Yields this container.
44
+ # @return the value defined in the block
45
+ def register(key, &block)
46
+ invalidate(key) if registered?(key)
47
+ registry[key.to_sym] = block
48
+ self
49
+ end
50
+
51
+ # Recursively resolves the object that was registered to
52
+ # the key. This value is memoized.
53
+ # @param key [Symbol]
54
+ def resolve(key)
55
+ add_dependent(key)
56
+ stack << key
57
+ value = resolved[key.to_sym] ||= registry[key.to_sym].call(self)
58
+ stack.pop
59
+ value
60
+ end
61
+ alias_method :[], :resolve
62
+
63
+ def keys
64
+ registry.keys
65
+ end
66
+
67
+ private
68
+
69
+ attr_reader :dependents, :registry, :resolved, :stack
70
+
71
+ def handles?(method)
72
+ registered?(method)
73
+ end
74
+
75
+ def add_dependent(key)
76
+ unless stack.empty?
77
+ dependents[key.to_sym] << stack.last
78
+ end
79
+ end
80
+
81
+ def registered?(key)
82
+ registry.key?(key.to_sym)
83
+ end
84
+
85
+ def unresolve(key)
86
+ resolved.delete(key.to_sym)
87
+ end
88
+
89
+ def invalidate(key, first = true)
90
+ unresolve(key)
91
+ dependents[key.to_sym]
92
+ .each {|child| invalidate(child, false) }
93
+ dependents.delete(key.to_sym) if first
94
+ end
95
+
96
+ end
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: canister
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
5
+ platform: ruby
6
+ authors:
7
+ - Bryan Hockey
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-02-07 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.16'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.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: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: "\n Canister is a simple IoC container for ruby. It has no dependencies
84
+ and provides only\n the functionality you need. It does not monkey-patch ruby
85
+ or pollute the global\n namespace, and most importantly it expects to be invisible
86
+ to your domain classes.\n "
87
+ email:
88
+ - bhock@umich.edu
89
+ executables: []
90
+ extensions: []
91
+ extra_rdoc_files: []
92
+ files:
93
+ - ".gitignore"
94
+ - ".rspec"
95
+ - ".rubocop.yml"
96
+ - ".rubocop_todo.yml"
97
+ - ".travis.yml"
98
+ - Gemfile
99
+ - LICENSE.md
100
+ - README.md
101
+ - Rakefile
102
+ - canister.gemspec
103
+ - lib/canister.rb
104
+ - lib/canister/version.rb
105
+ homepage: https://github.com/mlibrary/canister
106
+ licenses:
107
+ - Revised BSD
108
+ metadata: {}
109
+ post_install_message:
110
+ rdoc_options: []
111
+ require_paths:
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ requirements: []
124
+ rubyforge_project:
125
+ rubygems_version: 2.6.13
126
+ signing_key:
127
+ specification_version: 4
128
+ summary: A simple IoC container for ruby.
129
+ test_files: []