hesburgh-lib 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: 19be6eece64491b61c05c61eb9d8deb705d2b6c2
4
+ data.tar.gz: cf13adff46b6df8cc67b20cb83860e8c50942aca
5
+ SHA512:
6
+ metadata.gz: dd540b822d3f937261a94a1463443130214b936e7ce56e6de0dd8aacc6c68288b5a9ceb56d892f86a7a950ab06aa88d4d15e66bb4fe0b8787d376e17d06bc620
7
+ data.tar.gz: 52541e39a80a3a5a4945b9e24c5363a204a10d332f115069ddfa19abc06c263512c31d69f37657096b5c6975fdd0902af6fe0ee6845a4add8eef39ab389abb86
data/LICENSE ADDED
@@ -0,0 +1,14 @@
1
+ ##########################################################################
2
+ # Copyright 2014 University of Notre Dame
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
data/README.md ADDED
@@ -0,0 +1,14 @@
1
+ # Hesburgh::Lib
2
+
3
+ [![Build Status](https://travis-ci.org/ndlib/hesburgh-lib.png?branch=master)](https://travis-ci.org/ndlib/hesburgh-lib)
4
+ [![Code Climate](https://codeclimate.com/github/ndlib/hesburgh-lib.png)](https://codeclimate.com/github/ndlib/hesburgh-lib)
5
+ [![Coverage Status](https://img.shields.io/coveralls/ndlib/hesburgh-lib.svg)](https://coveralls.io/r/ndlib/hesburgh-lib)
6
+ [![Documentation Status](http://inch-ci.org/github/ndlib/hesburgh-lib.svg?branch=master)](http://inch-ci.org/github/ndlib/hesburgh-lib)
7
+ [![APACHE 2 License](http://img.shields.io/badge/APACHE2-license-blue.svg)](./LICENSE)
8
+
9
+ A toolbox of code that may be reusable.
10
+
11
+ ## Usage
12
+
13
+ None of the classes in this gem should be autoloaded.
14
+ It is up to *you, the developer,* to explicitly require the class.
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env ruby -wU
2
+
3
+ # *****************************************************************************
4
+ #
5
+ # CONFIGURATION OPTIONS
6
+ #
7
+ # *****************************************************************************
8
+
9
+ CONFIG_KEYS = [:REPOSITORY_PATH].freeze
10
+
11
+ REPOSITORY_PATH = ENV.fetch('REPOSITORY_PATH') { Dir.pwd }
12
+
13
+ # *****************************************************************************
14
+ #
15
+ # HELP OPTIONS
16
+ #
17
+ # *****************************************************************************
18
+
19
+ if ARGV.grep(/^-+h(elp)?$/i).size > 0
20
+ $stdout.puts ""
21
+ $stdout.puts "$ #{File.basename(__FILE__)} <gem1> <gem2>"
22
+ $stdout.puts ""
23
+ $stdout.puts "This script will update the given gem dependency, one at a time, and commit the"
24
+ $stdout.puts "change."
25
+ $stdout.puts ""
26
+ $stdout.puts "Current Configuration:"
27
+ CONFIG_KEYS.each do |key|
28
+ $stdout.puts "\t#{key}='#{Object.const_get(key)}'"
29
+ end
30
+ $stdout.puts ""
31
+ $stdout.puts "You can override the configuration option by adding the corresponding"
32
+ $stdout.puts "ENV variable."
33
+ $stdout.puts ""
34
+ $stdout.puts "Example:"
35
+ $stdout.puts "$ REPOSITORY_PATH=/path/to/repository #{File.basename(__FILE__)}"
36
+ exit(0)
37
+ end
38
+
39
+ # *****************************************************************************
40
+ #
41
+ # GUARD CONDITIONS
42
+ #
43
+ # *****************************************************************************
44
+
45
+ GEM_NAMES = ARGV
46
+
47
+ # Guard that we have a clean working directory
48
+ if `cd #{REPOSITORY_PATH} && git status --porcelain`.strip.size > 0
49
+ $stderr.puts "Repository @ #{REPOSITORY_PATH} did not have a clean working directory"
50
+ exit!(2)
51
+ end
52
+
53
+ GEM_NAMES.each do |gem_name|
54
+ # Guard that the update can happen
55
+ unless system("cd #{REPOSITORY_PATH} && bundle update #{gem_name}")
56
+ $stderr.puts "Unable to update #{gem_name}. See previous output."
57
+ exit!(3)
58
+ end
59
+
60
+ # Commit the changes
61
+ `cd #{REPOSITORY_PATH}; git add Gemfile.lock`
62
+
63
+ path_to_commit_message = File.expand_path(File.join(REPOSITORY_PATH, '../COMMIT.msg'))
64
+ begin
65
+ File.open(path_to_commit_message, 'w+') do |file|
66
+ file.puts "Updating #{gem_name} dependency"
67
+ file.puts ""
68
+
69
+ message = "`$ #{File.basename(__FILE__)} #{gem_name}`"
70
+ CONFIG_KEYS.each_with_object(message) do |key, mem|
71
+ mem = "#{key}=\"#{ENV[key.to_s]}\" #{mem}" if ENV.key?(key.to_s)
72
+ mem
73
+ end
74
+ file.puts message
75
+ end
76
+ $stdout.puts `cd #{REPOSITORY_PATH} && git commit -F #{path_to_commit_message}`
77
+ ensure
78
+ begin
79
+ File.unlink(path_to_commit_message)
80
+ rescue true
81
+ # If it doesn't exist don't worry
82
+ end
83
+ end
84
+ end
@@ -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 'hesburgh/lib/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "hesburgh-lib"
8
+ spec.version = Hesburgh::Lib::VERSION
9
+ spec.authors = ["Jeremy Friesen"]
10
+ spec.email = ["jeremy.n.friesen@gmail.com"]
11
+ spec.summary = %q{A toolbox of code that may be reusable.}
12
+ spec.description = %q{A toolbox of code that may be reusable.}
13
+ spec.homepage = "https://github.com/ndlib/hesburgh-lib"
14
+ spec.license = "APACHE2"
15
+
16
+ spec.files = `git ls-files -z -- bin/* lib/* LICENSE README.md hesburgh-lib.gemspec`.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.7"
22
+ spec.add_development_dependency "rspec", "~> 3.0"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency "rspec-given", "~> 3.5"
25
+ spec.add_development_dependency "rubocop", "~> 0.27"
26
+ spec.add_development_dependency "activesupport", ">= 3.0"
27
+ end
@@ -0,0 +1,78 @@
1
+ require 'active_support/concern'
2
+ require 'active_support/core_ext/class/attribute'
3
+ require 'active_support/core_ext/string/inflections'
4
+
5
+ module Hesburgh
6
+ module Lib
7
+ # Exposes a way for connecting a set of Runners into your application.
8
+ # A runner allows you to tease out Action level logic into its own custom
9
+ # class.
10
+ #
11
+ # @see Hesburgh::Lib::Runner
12
+ module ControllerWithRunner
13
+ extend ActiveSupport::Concern
14
+
15
+ included do
16
+ # Because yardoc's scope imperative does not appear to work, I'm pushing the
17
+ # comments into the class definition
18
+ class << self
19
+ # @!attribute [rw] runner_container
20
+ # So you can specify where you will be finding an action's Runner
21
+ # class.
22
+ #
23
+ # @see #run
24
+ end
25
+ class_attribute :runner_container
26
+ end
27
+
28
+ # So you can more easily decouple the controller's command behavior and
29
+ # response behavior.
30
+ #
31
+ # @example
32
+ # def index
33
+ # run(specific_params) do |on|
34
+ # on.success { |collection|
35
+ # @collection = collection
36
+ # respond_with(@collection)
37
+ # }
38
+ # end
39
+ # end
40
+ #
41
+ # @see .runner_container for customization
42
+ def run(*args, &block)
43
+ runner.run(self, *args, &block)
44
+ end
45
+
46
+ # A query to lookup the appropriate Runner class
47
+ def runner(runner_name = nil)
48
+ return @runner if @runner # For Dependency Injection
49
+ runner_name = action_name.classify unless runner_name
50
+ if runner_container.const_defined?(runner_name)
51
+ runner_container.const_get(runner_name)
52
+ else
53
+ fail RunnerNotFoundError, container: runner_container, name: runner_name
54
+ end
55
+ end
56
+
57
+ # Exposed for purposes of Dependency Injection.
58
+ def runner=(object)
59
+ fail(ImproperRunnerError, runner: object, method_name: :run) unless object.respond_to?(:run)
60
+ @runner = object
61
+ end
62
+
63
+ # Raised when a Runner is not found
64
+ class RunnerNotFoundError < RuntimeError # :nodoc:
65
+ def initialize(options = {})
66
+ super("Unable to find #{options.fetch(:name)} in #{options.fetch(:container)}")
67
+ end
68
+ end
69
+
70
+ # Raised when a Runner is not found
71
+ class ImproperRunnerError < RuntimeError # :nodoc:
72
+ def initialize(options = {})
73
+ super("Expected #{options.fetch(:runner)} to respond_to #{options.fetch(:method_name)}")
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,67 @@
1
+ module Hesburgh
2
+ module Lib
3
+ # A class to assist in circumventing the seething underlayer of potential
4
+ # runners and cut quick to the working with the callbacks.
5
+ #
6
+ # @example
7
+ #
8
+ # context = []
9
+ # runner = MockRunner.new(context: context, run_with: :input, yields: :yielded_value, callback_name: :success)
10
+ # runner.run(:input) do |on|
11
+ # on.success {|output| context << output }
12
+ # end
13
+ # context == [:yielded_value]
14
+ # => true
15
+ #
16
+ # @see Hesrbugh::Lib::Runner
17
+ # @see Hesrbugh::Lib::NamedCallbacks
18
+ class MockRunner
19
+ # Raised when the actual :run_with parameter is different than the
20
+ # expected
21
+ class RunWithMismatchError < RuntimeError
22
+ def initialize(actual: nil, expected: nil)
23
+ super("RunWith Mismatch Error:\nActual: #{actual.inspect}\nExpected: #{expected.inspect}\n")
24
+ end
25
+ end
26
+
27
+ def initialize(options = {})
28
+ @yields = options.fetch(:yields)
29
+ @callback_name = options.fetch(:callback_name)
30
+ @run_with = __wrap__(options.fetch(:run_with))
31
+
32
+ # Because the context may automatically be getting assigned by the
33
+ # controller.
34
+ @run_with.unshift(options[:context]) if options.key?(:context)
35
+ end
36
+
37
+ def run(*args)
38
+ if @run_with == args
39
+ if block_given?
40
+ return yield(self)
41
+ else
42
+ return @callback_name, *@yields
43
+ end
44
+ else
45
+ fail RunWithMismatchError, actual: args, expected: @run_with
46
+ end
47
+ end
48
+
49
+ def method_missing(method_name, &_block)
50
+ super unless @callback_name.to_s == method_name.to_s
51
+ return @callback_name, *yield(@yields)
52
+ end
53
+
54
+ private
55
+
56
+ def __wrap__(object)
57
+ if object.nil?
58
+ []
59
+ elsif object.respond_to?(:to_ary)
60
+ object.to_ary || [object]
61
+ else
62
+ [object]
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,24 @@
1
+ module Hesburgh
2
+ module Lib
3
+ # Responsible for registering blocks used for callbacks.
4
+ class NamedCallbacks
5
+ def initialize
6
+ @callbacks = {}
7
+ end
8
+
9
+ def method_missing(callback_name, *_args, &block)
10
+ @callbacks[callback_name] = block
11
+ end
12
+
13
+ def respond_to_missing?(callback_name)
14
+ @callbacks[callback_name]
15
+ end
16
+
17
+ def call(callback_name, *args)
18
+ callback_name = callback_name.to_sym
19
+ callback = @callbacks[callback_name]
20
+ callback ? callback.call(*args) : true
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,50 @@
1
+ module Hesburgh
2
+ module Lib
3
+ # A Runner is responsible for performing the guts of what might traditionally
4
+ # be a controller's action.
5
+ #
6
+ # It exists for two reasons, though this is not considered exhaustive:
7
+ # * Controllers are extremely over-worked (parameter negotiation,
8
+ # authentication, authorization, marshalling an object, user messages via
9
+ # flash, and http response determination)
10
+ # * The inner method content of a controller's action is subject to change
11
+ # especially as other implementors look to change the behavior.
12
+ #
13
+ # So, the Runner provides a seem in the code in which you can more readily
14
+ # make changes to the "inner method" of a route. In some ways, I see this as
15
+ # a separation of state change and response; a somewhat analogous separation
16
+ # to the Command/Query separation principle.
17
+ #
18
+ # @see Hesrbugh::Lib::MockRunner
19
+ class Runner
20
+ def self.run(context, *args, &block)
21
+ new(context, &block).run(*args)
22
+ end
23
+
24
+ attr_reader :context
25
+ protected :context
26
+
27
+ def initialize(context, callbacks: nil)
28
+ @callbacks = callbacks || default_callbacks
29
+ @context = context
30
+ yield(@callbacks) if block_given?
31
+ end
32
+
33
+ def callback(name, *args)
34
+ @callbacks.call(name, *args)
35
+ return name, *args
36
+ end
37
+
38
+ def run(*_args)
39
+ fail NotImplementedError, ("You must define #{self.class}#run")
40
+ end
41
+
42
+ private
43
+
44
+ def default_callbacks
45
+ require 'hesburgh/lib/named_callbacks'
46
+ NamedCallbacks.new
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,5 @@
1
+ module Hesburgh
2
+ module Lib
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,8 @@
1
+ require "hesburgh/lib/version"
2
+
3
+ module Hesburgh
4
+ # The namespaced container for a toolbox of code that may be reusable.
5
+ module Lib
6
+ # Your code goes here...
7
+ end
8
+ end
metadata ADDED
@@ -0,0 +1,139 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hesburgh-lib
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jeremy Friesen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-03-09 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.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec-given
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.5'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.5'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.27'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.27'
83
+ - !ruby/object:Gem::Dependency
84
+ name: activesupport
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
97
+ description: A toolbox of code that may be reusable.
98
+ email:
99
+ - jeremy.n.friesen@gmail.com
100
+ executables:
101
+ - update-dependency
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - LICENSE
106
+ - README.md
107
+ - bin/update-dependency
108
+ - hesburgh-lib.gemspec
109
+ - lib/hesburgh/lib.rb
110
+ - lib/hesburgh/lib/controller_with_runner.rb
111
+ - lib/hesburgh/lib/mock_runner.rb
112
+ - lib/hesburgh/lib/named_callbacks.rb
113
+ - lib/hesburgh/lib/runner.rb
114
+ - lib/hesburgh/lib/version.rb
115
+ homepage: https://github.com/ndlib/hesburgh-lib
116
+ licenses:
117
+ - APACHE2
118
+ metadata: {}
119
+ post_install_message:
120
+ rdoc_options: []
121
+ require_paths:
122
+ - lib
123
+ required_ruby_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ required_rubygems_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ requirements: []
134
+ rubyforge_project:
135
+ rubygems_version: 2.4.7
136
+ signing_key:
137
+ specification_version: 4
138
+ summary: A toolbox of code that may be reusable.
139
+ test_files: []