repository-support 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d697e19788520158f868c0deeaadb25da7d12ea3001cca38f3efc6b0c8fe7bf0
4
+ data.tar.gz: 37116b8077c2e96418351ddc3fa87058b1ca8d1846039e74fb1a86ba444518c6
5
+ SHA512:
6
+ metadata.gz: fba43d8df0a90410ae0d78c1afff9ca525c2f674aaaffb215db11eb365efb99f944323f7cb97846c1102f5c3c1153e2e3af11667bafe2563d43436534512448e
7
+ data.tar.gz: e70d253855608257ab9b4bcf354d70421ae35c8cc163e04ad902f7856817664f0780bf7ad7a37d9a475fbca0eb78279ac376ab944e42669c6aae0919b1cba1c1
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
@@ -0,0 +1 @@
1
+ ./tmp/gemset
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,24 @@
1
+
2
+ AllCops:
3
+ TargetRubyVersion: 2.5
4
+
5
+ Metrics/BlockLength:
6
+ Max: 300
7
+ Include:
8
+ - 'spec/**/*_spec.rb'
9
+
10
+ Metrics/ModuleLength:
11
+ Max: 300
12
+ Include:
13
+ - 'spec/**/*_spec.rb'
14
+
15
+ Style/CommentedKeyword:
16
+ Enabled: false
17
+
18
+ # This silences 'Missing top-level class documentation comment.', which we
19
+ # particularly want to do on (initially-)generated files.
20
+ Style/Documentation:
21
+ Enabled: false
22
+ Include:
23
+ - 'apps/**/*.rb'
24
+ - 'lib/**/*.rb'
@@ -0,0 +1 @@
1
+ 2.5.0
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.5
4
+ - 2.2.1
5
+ - jruby-9.0.0.0.pre1
6
+ # - rbx
7
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in repository-support.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Jeff Dickey
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,204 @@
1
+ <h1>Repository::Support</h1>
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/repository-support.svg)](http://badge.fury.io/rb/repository-support)
4
+ [![Code Climate](https://codeclimate.com/github/jdickey/repository-support/badges/gpa.svg)](https://codeclimate.com/github/jdickey/repository-support)
5
+ [ ![Codeship Status for jdickey/repository-support](https://codeship.com/projects/224d6180-997e-0132-c9c3-165733f17d49/status?branch=master)](https://codeship.com/projects/63652)
6
+ [![security](https://hakiri.io/github/jdickey/repository-support/master.svg)](https://hakiri.io/github/jdickey/repository-support/master)
7
+ [![Dependency Status](https://gemnasium.com/jdickey/repository-support.svg)](https://gemnasium.com/jdickey/repository-support)
8
+
9
+ <h2>Contents</h2>
10
+
11
+ - [Overview](#overview)
12
+ - [IMPORTANT LEGACY NOTICE](#important-legacy-notice)
13
+ - [Installation](#installation)
14
+ - [Usage](#usage)
15
+ * [`StoreResult`](#storeresult)
16
+ + [`StoreResult::Success`](#storeresultsuccess)
17
+ + [`StoreResult::Failure`](#storeresultfailure)
18
+ * [`ErrorFactory`](#errorfactory)
19
+ * [`TestAttributeContainer`](#testattributecontainer)
20
+ * [A Note on Parameters](#a-note-on-parameters)
21
+ - [Contributing](#contributing)
22
+ - [Version History](#version-history)
23
+ - [Legal](#legal)
24
+
25
+ ## Overview
26
+
27
+ This Gem provides several support classes and modules for
28
+ [`Repository::Base`](https://github.com/jdickey/repository-base) and its
29
+ user-created subclasses, which implement the Repository layer of a typical Data
30
+ Mapper pattern architecture.
31
+
32
+ These classes and modules are:
33
+
34
+ * `ErrorFactory` provides a single class method, `.create` which, when supplied with an `ActiveModel::Errors`-quacking object as a parameter, produces an Array of Hashes containing JSON-compatible error information;
35
+ * `ResultBuilder` is a Command-pattern class whose `#initialize` method takes one parameter and whose `#build` method evaluates that value. If it is truthy, then `#build` returns a `StoreResult::Success` (see below) with that value as its "paylaaod". If the value is falsy, then `#build` returns a `StoreResult#Failure`, yielding the value to a block that returns the payload for the `StoreResult`.
36
+ * `StoreResult` is a simple value object with three accessors for values passed in to the `#initialize` method: namely `#entity` (some value object); `#success` (a Boolean, aliased as `#success?`); and `#errors` an Array of error records as created by `ErrorFactory.create`. It has two subclasses: `StoreResult::Success` fills in a `StoreResult` using its single parameter (the entity) and defaults for the other fields; and `StoreResult::Failure`, which does likewise initialised with an array of error hashes.
37
+ * `TestAttributeContainer` is a module that, when used to extend a class, adds an `attributes` Hash property (reader and writer) to the extending class. While `attributes` is initially empty, it may be added to either by defining a single key, or by mass-assigning a Hash to `attributes`. Once an individual "attribute" is defined for a class instance, it can be read from or written to using a direct method on that instance. See the discussion in "Usage" below for more details.
38
+
39
+ ## IMPORTANT LEGACY NOTICE
40
+
41
+ **_NOTICE!_** This Gem was created to support a solo, ad-hoc, early learning experience in what is now known as Clean Architecture. It was part of our first attempt to build an alternative to the ActiveRecord/ActiveModel scheme native to Ruby on Rails.
42
+
43
+ As such, it has been superseded and far outshone by other, team efforts, notably [ROM](http://rom-rb.org/) as used with [Hanami](http://hanamirb.org/) and [Trailblazer](http://trailblazer.to/). You are *strongly advised* to examine these and other tools rather than to use this for *any* new development. The Gem is being republished as an 0.1.0 release purely for internal archaeologigical purposes.
44
+
45
+ ## Installation
46
+
47
+ Add this line to your application's Gemfile:
48
+
49
+ ```ruby
50
+ gem 'repository-support'
51
+ ```
52
+
53
+ And then execute:
54
+
55
+ $ bundle
56
+
57
+ Or install it yourself as:
58
+
59
+ $ gem install repository-support
60
+
61
+ ## Usage
62
+
63
+ ### `StoreResult`
64
+
65
+ `StoreReult` is used as the return value from all `Repository::Base` instance
66
+ methods (actions) *except* `#all`.
67
+
68
+ If the action implemented by the method was successful, it returns a
69
+ `StoreResult` where
70
+
71
+ * the `entity` attribute is an entity matching the state of the record persisted or accessed by the action;
72
+ * the `success` attribute (or `#success?` method) is `true`; and
73
+ * the `errors` attribute is an empty Array.
74
+
75
+ If the action was unsuccessful, the repository method returns a `StoreResult`
76
+ where
77
+
78
+ * the `entity` attribute is `nil`;
79
+ * the `success` attribute (or `#success?` method) is `false`; and
80
+ * the `errors` attribute contains one error Hash for each error preventing the action from succeeding.
81
+
82
+ #### `StoreResult::Success`
83
+
84
+ This subclass of `StoreResult` is a convenience for initialising a successful
85
+ `StoreResult`. Its `#initialize` method takes a single parameter, the entity to
86
+ be used in the result, with the other fields set as described above for a
87
+ successful result.
88
+
89
+ #### `StoreResult::Failure`
90
+
91
+ This subclass of `StoreResult` is a convenience for initialising an unsuccessful
92
+ `StoreResult`. Its `#initialize` method takes a single parameter, the Array of
93
+ error hashes to be used in the result, with the other fields set as described
94
+ above for an unsuccessful result.
95
+
96
+ ### `ErrorFactory`
97
+
98
+ This class has a single class method, `.create`. Given a parameter value that
99
+ quacks as an[`ActiveModel::Errors`](http://api.rubyonrails.org/classes/ActiveModel/Errors.html)
100
+ instance, it returns an Array where each item is a Hash derived from each error
101
+ reported by the parameter object, or an empty Array if there are no errors. Each
102
+ Hash in the Array has two fields:
103
+
104
+ 1. `field`, which contains the attribute passed to [`ActiveModel::Errors#add`](http://api.rubyonrails.org/classes/ActiveModel/Errors.html#method-i-add) *as a string*; and
105
+ 1. `message`, which contains the message as passed into the same `#add` call.
106
+
107
+ So, given an `ActiveModel::Errors` object that resulted from the following code:
108
+
109
+ ```ruby
110
+ errors = ActiveModel::Errors.new self
111
+ # ...
112
+ errors.add :frobulator, 'does not frob'
113
+ errors.add :frobulator, `is busted'
114
+ errors.add :foo, 'is :foo'
115
+ # ...
116
+ error_data = ErrorFactory.create errors
117
+ @logger.log error_data
118
+ ```
119
+
120
+ the value of `error_data` written to the log would be (formatted for clarity)
121
+
122
+ ```
123
+ [
124
+ {field: 'frobulator', message: 'does not frob'},
125
+ {field: 'frobulator', message: 'is busted'},
126
+ {field: 'foo', 'is :foo'}
127
+ ]
128
+ ```
129
+
130
+ Note that no guarantees are made for ordering, just as seems to be the case for
131
+ `ActiveModel::Errors`.
132
+
133
+ ### `TestAttributeContainer`
134
+
135
+ This module implements support for attributes in a way that can be thought of as "halfway between a [`Struct`](http://ruby-doc.org//core-2.1.5/Struct.html) and an [`OpenStruct`](http://ruby-doc.org/stdlib-2.1.5/libdoc/ostruct/rdoc/OpenStruct.html) or [`FancyOpenStruct`](https://github.com/tomchapin/fancy-open-struct/)."
136
+
137
+ By extending a class with the module and invoking the `init_empty_attribute_container` class method within that class, a Hash is added as the `attributes` attribute of each instance of that class. It can be assigned to directly; once having done so, individual "attributes" may be accessed *or modified* through a method call using the name of the attribute.
138
+
139
+ For example:
140
+
141
+ ```ruby
142
+ class Foo
143
+ extend Repository::Support::TestAttributeContainer
144
+
145
+ init_empty_attribute_container
146
+ end
147
+
148
+ # interactively
149
+ foo = Foo.new
150
+ # => #<Foo:0x007fd2b4b9da28>
151
+ foo.attributes
152
+ # => {}
153
+ foo.attributes = { foo: true, bar: 42 }
154
+ # => {:foo=>true, :bar=>42}
155
+ foo.foo
156
+ # => true
157
+ foo.foo = :whatever_you_want
158
+ # => :whatever_you_want
159
+ foo.attributes
160
+ # => {:foo=>:whatever_you_want, :bar=>42}
161
+ foo.quux
162
+ # => NoMethodError: undefined method `quux' # ...
163
+ foo.attributes[:quux] = 'hello'
164
+ # => "hello"
165
+ foo.quux
166
+ # => "hello"
167
+ ```
168
+
169
+ To create a new attribute after the container has been set up, assign to a new key in the `attributes` property Hash. As demonstrated above, the "attribute" can then be accessed or modified by using its name as a reader or writer method name. Without explicitly assigning to `attributes`, however, undefined methods raise errors as usual.
170
+
171
+ ### A Note on Parameters
172
+
173
+ All *public* methods having multiple arguments (including `#initialize`) in each
174
+ of the classes defined above use the keyword-argument specification introduced
175
+ in Ruby 2.0. By removing order dependency of arguments, inadvertent-reordering
176
+ errors are no longer a
177
+ [hunt-the-typo](http://en.wikipedia.org/wiki/Hunt_the_Wumpus)
178
+ exercise. This rule *does not* apply to single-parameter methods, nor to
179
+ `private` methods.
180
+
181
+ ## Contributing
182
+
183
+ 1. Fork it ( https://github.com/jdickey/repository-support/fork )
184
+ 1. Create your feature branch (`git checkout -b my-new-feature`)
185
+ 1. Ensure that your changes are completely covered by *passing* specs, and comply with the [Ruby Style Guide](https://github.com/bbatsov/ruby-style-guide) as enforced by [RuboCop](https://github.com/bbatsov/rubocop). To verify this, run `bundle exec rake`, noting and repairing any lapses in coverage or style violations;
186
+ 1. Commit your changes (`git commit -a`). Please *do not* use a single-line commit message (`git commit -am "some message"`). A good commit message notes what was changed and why in sufficient detail that a relative newcomer to the code can understand your reasoning and your code;
187
+ 1. Push to the branch (`git push origin my-new-feature`)
188
+ 1. Create a new Pull Request. Describe at some length the rationale for your new feature; your implementation strategy at a higher level than each individual commit message; anything future maintainers should be aware of; and so on. *If this is a modification to existing code, reference the open issue being addressed*.
189
+ 1. Don't be discouraged if the PR generates a discussion that leads to further refinement of your PR through additional commits. These should *generally* be discussed in comments on the PR itself; discussion in the Gitter room (see below) may also be useful;
190
+ 1. If you've comments, questions, or just want to talk through your ideas, don't hesitate to hang out in the `Repository::Base` [room on Gitter](https://gitter.im/jdickey/repository-base). Ask away!
191
+
192
+ ## Version History
193
+
194
+ | Version | Date | Notes |
195
+ | ------- | ---- | ----- |
196
+ | v0.1.0 | 2 February 2018 | Changed MRI supported version from 2.2.2 to 2.5.0; **published legacy notice** |
197
+ | v0.0.4 | 9 March 2015 | Added experimental, one-off JRuby 9000 support |
198
+ | v0.0.3 | 21 February 2015 | Completed initial feature development |
199
+ | v0.0.2 | 18 February 2015 | Internal; incremental feature development |
200
+ | v0.0.1 | 18 February 2015 | Internal; incremental feature development |
201
+
202
+ ## Legal
203
+
204
+ This document and the accompanying code are Copyright &copy; 2015-2018 by Jeff Dickey/Seven Sigma Agility, and are released under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,20 @@
1
+
2
+ require 'bundler/gem_tasks'
3
+ require 'rspec/core/rake_task'
4
+ require 'rubocop/rake_task'
5
+
6
+ RuboCop::RakeTask.new(:rubocop) do |task|
7
+ task.patterns = [
8
+ 'lib/**/*.rb',
9
+ 'spec/spec_helper.rb',
10
+ 'spec/**/*_spec.rb'
11
+ ]
12
+ task.formatters = ['simple', 'd']
13
+ task.fail_on_error = true
14
+ task.options << '--rails'
15
+ end
16
+
17
+ RSpec::Core::RakeTask.new :spec
18
+
19
+ task(:default).clear
20
+ task default: [:spec, :rubocop]
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'bundle' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "rubygems"
12
+
13
+ m = Module.new do
14
+ module_function
15
+
16
+ def invoked_as_script?
17
+ File.expand_path($0) == File.expand_path(__FILE__)
18
+ end
19
+
20
+ def env_var_version
21
+ ENV["BUNDLER_VERSION"]
22
+ end
23
+
24
+ def cli_arg_version
25
+ return unless invoked_as_script? # don't want to hijack other binstubs
26
+ return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
27
+ bundler_version = nil
28
+ update_index = nil
29
+ ARGV.each_with_index do |a, i|
30
+ if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
31
+ bundler_version = a
32
+ end
33
+ next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
34
+ bundler_version = $1 || ">= 0.a"
35
+ update_index = i
36
+ end
37
+ bundler_version
38
+ end
39
+
40
+ def gemfile
41
+ gemfile = ENV["BUNDLE_GEMFILE"]
42
+ return gemfile if gemfile && !gemfile.empty?
43
+
44
+ File.expand_path("../../Gemfile", __FILE__)
45
+ end
46
+
47
+ def lockfile
48
+ lockfile =
49
+ case File.basename(gemfile)
50
+ when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
51
+ else "#{gemfile}.lock"
52
+ end
53
+ File.expand_path(lockfile)
54
+ end
55
+
56
+ def lockfile_version
57
+ return unless File.file?(lockfile)
58
+ lockfile_contents = File.read(lockfile)
59
+ return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
60
+ Regexp.last_match(1)
61
+ end
62
+
63
+ def bundler_version
64
+ @bundler_version ||= begin
65
+ env_var_version || cli_arg_version ||
66
+ lockfile_version || "#{Gem::Requirement.default}.a"
67
+ end
68
+ end
69
+
70
+ def load_bundler!
71
+ ENV["BUNDLE_GEMFILE"] ||= gemfile
72
+
73
+ # must dup string for RG < 1.8 compatibility
74
+ activate_bundler(bundler_version.dup)
75
+ end
76
+
77
+ def activate_bundler(bundler_version)
78
+ if Gem::Version.correct?(bundler_version) && Gem::Version.new(bundler_version).release < Gem::Version.new("2.0")
79
+ bundler_version = "< 2"
80
+ end
81
+ gem_error = activation_error_handling do
82
+ gem "bundler", bundler_version
83
+ end
84
+ return if gem_error.nil?
85
+ require_error = activation_error_handling do
86
+ require "bundler/version"
87
+ end
88
+ return if require_error.nil? && Gem::Requirement.new(bundler_version).satisfied_by?(Gem::Version.new(Bundler::VERSION))
89
+ warn "Activating bundler (#{bundler_version}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_version}'`"
90
+ exit 42
91
+ end
92
+
93
+ def activation_error_handling
94
+ yield
95
+ nil
96
+ rescue StandardError, LoadError => e
97
+ e
98
+ end
99
+ end
100
+
101
+ m.load_bundler!
102
+
103
+ if m.invoked_as_script?
104
+ load Gem.bin_path("bundler", "bundle")
105
+ end
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'bundler' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('bundler', 'bundler')
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'htmldiff' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("diff-lcs", "htmldiff")