repository-support 0.1.1 → 0.1.3
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 +4 -4
- data/.gitignore +0 -1
- data/Rakefile +12 -0
- data/bin/kramdown +29 -0
- data/bin/setup +2 -1
- data/bin/yard +29 -0
- data/bin/yardoc +29 -0
- data/bin/yri +29 -0
- data/doc/Repository.html +128 -0
- data/doc/Repository/Support.html +140 -0
- data/doc/Repository/Support/ErrorFactory.html +205 -0
- data/doc/Repository/Support/ResultBuilder.html +274 -0
- data/doc/Repository/Support/StoreResult.html +464 -0
- data/doc/Repository/Support/StoreResult/Failure.html +227 -0
- data/doc/Repository/Support/StoreResult/Success.html +227 -0
- data/doc/Repository/Support/TestAttributeContainer.html +282 -0
- data/doc/_index.html +188 -0
- data/doc/class_list.html +51 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +58 -0
- data/doc/css/style.css +499 -0
- data/doc/file.README.html +323 -0
- data/doc/file_list.html +56 -0
- data/doc/frames.html +17 -0
- data/doc/index.html +323 -0
- data/doc/js/app.js +248 -0
- data/doc/js/full_list.js +216 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +131 -0
- data/doc/top-level-namespace.html +110 -0
- data/lib/repository/support/version.rb +1 -1
- data/repository-support.gemspec +4 -2
- metadata +58 -4
@@ -0,0 +1,323 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset="UTF-8">
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6
|
+
<title>
|
7
|
+
File: README
|
8
|
+
|
9
|
+
— Documentation by YARD 0.9.12
|
10
|
+
|
11
|
+
</title>
|
12
|
+
|
13
|
+
<link rel="stylesheet" href="css/style.css" type="text/css" charset="utf-8" />
|
14
|
+
|
15
|
+
<link rel="stylesheet" href="css/common.css" type="text/css" charset="utf-8" />
|
16
|
+
|
17
|
+
<script type="text/javascript" charset="utf-8">
|
18
|
+
pathId = "README";
|
19
|
+
relpath = '';
|
20
|
+
</script>
|
21
|
+
|
22
|
+
|
23
|
+
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
24
|
+
|
25
|
+
<script type="text/javascript" charset="utf-8" src="js/app.js"></script>
|
26
|
+
|
27
|
+
|
28
|
+
</head>
|
29
|
+
<body>
|
30
|
+
<div class="nav_wrap">
|
31
|
+
<iframe id="nav" src="file_list.html?1"></iframe>
|
32
|
+
<div id="resizer"></div>
|
33
|
+
</div>
|
34
|
+
|
35
|
+
<div id="main" tabindex="-1">
|
36
|
+
<div id="header">
|
37
|
+
<div id="menu">
|
38
|
+
|
39
|
+
<a href="_index.html">Index</a> »
|
40
|
+
<span class="title">File: README</span>
|
41
|
+
|
42
|
+
</div>
|
43
|
+
|
44
|
+
<div id="search">
|
45
|
+
|
46
|
+
<a class="full_list_link" id="class_list_link"
|
47
|
+
href="class_list.html">
|
48
|
+
|
49
|
+
<svg width="24" height="24">
|
50
|
+
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
51
|
+
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
52
|
+
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
53
|
+
</svg>
|
54
|
+
</a>
|
55
|
+
|
56
|
+
</div>
|
57
|
+
<div class="clear"></div>
|
58
|
+
</div>
|
59
|
+
|
60
|
+
<div id="content"><div id='filecontents'><h1>Repository::Support</h1>
|
61
|
+
|
62
|
+
<p><a href="http://badge.fury.io/rb/repository-support"><img src="https://badge.fury.io/rb/repository-support.svg" alt="Gem Version" /></a>
|
63
|
+
<a href="https://codeclimate.com/github/jdickey/repository-support"><img src="https://codeclimate.com/github/jdickey/repository-support/badges/gpa.svg" alt="Code Climate" /></a>
|
64
|
+
<a href="https://codeship.com/projects/63652"> <img src="https://codeship.com/projects/224d6180-997e-0132-c9c3-165733f17d49/status?branch=master" alt="Codeship Status for jdickey/repository-support" /></a>
|
65
|
+
<a href="https://hakiri.io/github/jdickey/repository-support/master"><img src="https://hakiri.io/github/jdickey/repository-support/master.svg" alt="security" /></a>
|
66
|
+
<a href="https://gemnasium.com/jdickey/repository-support"><img src="https://gemnasium.com/jdickey/repository-support.svg" alt="Dependency Status" /></a></p>
|
67
|
+
|
68
|
+
<h2>Contents</h2>
|
69
|
+
|
70
|
+
<ul>
|
71
|
+
<li><a href="#overview">Overview</a></li>
|
72
|
+
<li><a href="#important-legacy-notice">IMPORTANT LEGACY NOTICE</a></li>
|
73
|
+
<li><a href="#installation">Installation</a></li>
|
74
|
+
<li><a href="#usage">Usage</a>
|
75
|
+
<ul>
|
76
|
+
<li><a href="#storeresult"><code>StoreResult</code></a>
|
77
|
+
<ul>
|
78
|
+
<li><a href="#storeresultsuccess"><code>StoreResult::Success</code></a></li>
|
79
|
+
<li><a href="#storeresultfailure"><code>StoreResult::Failure</code></a></li>
|
80
|
+
</ul>
|
81
|
+
</li>
|
82
|
+
<li><a href="#errorfactory"><code>ErrorFactory</code></a></li>
|
83
|
+
<li><a href="#testattributecontainer"><code>TestAttributeContainer</code></a></li>
|
84
|
+
<li><a href="#a-note-on-parameters">A Note on Parameters</a></li>
|
85
|
+
</ul>
|
86
|
+
</li>
|
87
|
+
<li><a href="#contributing">Contributing</a></li>
|
88
|
+
<li><a href="#version-history">Version History</a></li>
|
89
|
+
<li><a href="#legal">Legal</a></li>
|
90
|
+
</ul>
|
91
|
+
|
92
|
+
<h2 id="overview">Overview</h2>
|
93
|
+
|
94
|
+
<p>This Gem provides several support classes and modules for
|
95
|
+
<a href="https://github.com/jdickey/repository-base"><code>Repository::Base</code></a> and its
|
96
|
+
user-created subclasses, which implement the Repository layer of a typical Data
|
97
|
+
Mapper pattern architecture.</p>
|
98
|
+
|
99
|
+
<p>These classes and modules are:</p>
|
100
|
+
|
101
|
+
<ul>
|
102
|
+
<li><code>ErrorFactory</code> provides a single class method, <code>.create</code> which, when supplied with an <code>ActiveModel::Errors</code>-quacking object as a parameter, produces an Array of Hashes containing JSON-compatible error information;</li>
|
103
|
+
<li><code>ResultBuilder</code> is a Command-pattern class whose <code>#initialize</code> method takes one parameter and whose <code>#build</code> method evaluates that value. If it is truthy, then <code>#build</code> returns a <code>StoreResult::Success</code> (see below) with that value as its “paylaaod”. If the value is falsy, then <code>#build</code> returns a <code>StoreResult#Failure</code>, yielding the value to a block that returns the payload for the <code>StoreResult</code>.</li>
|
104
|
+
<li><code>StoreResult</code> is a simple value object with three accessors for values passed in to the <code>#initialize</code> method: namely <code>#entity</code> (some value object); <code>#success</code> (a Boolean, aliased as <code>#success?</code>); and <code>#errors</code> an Array of error records as created by <code>ErrorFactory.create</code>. It has two subclasses: <code>StoreResult::Success</code> fills in a <code>StoreResult</code> using its single parameter (the entity) and defaults for the other fields; and <code>StoreResult::Failure</code>, which does likewise initialised with an array of error hashes.</li>
|
105
|
+
<li><code>TestAttributeContainer</code> is a module that, when used to extend a class, adds an <code>attributes</code> Hash property (reader and writer) to the extending class. While <code>attributes</code> is initially empty, it may be added to either by defining a single key, or by mass-assigning a Hash to <code>attributes</code>. 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.</li>
|
106
|
+
</ul>
|
107
|
+
|
108
|
+
<h2 id="important-legacy-notice">IMPORTANT LEGACY NOTICE</h2>
|
109
|
+
|
110
|
+
<p><strong><em>NOTICE!</em></strong> 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.</p>
|
111
|
+
|
112
|
+
<p>As such, it has been superseded and far outshone by other, team efforts, notably <a href="http://rom-rb.org/">ROM</a> as used with <a href="http://hanamirb.org/">Hanami</a> and <a href="http://trailblazer.to/">Trailblazer</a>. You are <em>strongly advised</em> to examine these and other tools rather than to use this for <em>any</em> new development. The Gem is being republished as an 0.1.0 release purely for internal archaeologigical purposes.</p>
|
113
|
+
|
114
|
+
<h2 id="installation">Installation</h2>
|
115
|
+
|
116
|
+
<p>Add this line to your application’s Gemfile:</p>
|
117
|
+
|
118
|
+
<p><code>ruby
|
119
|
+
gem 'repository-support'
|
120
|
+
</code></p>
|
121
|
+
|
122
|
+
<p>And then execute:</p>
|
123
|
+
|
124
|
+
<pre class="code ruby"><code class="ruby">$ bundle
|
125
|
+
</code></pre>
|
126
|
+
|
127
|
+
<p>Or install it yourself as:</p>
|
128
|
+
|
129
|
+
<pre class="code ruby"><code class="ruby">$ gem install repository-support
|
130
|
+
</code></pre>
|
131
|
+
|
132
|
+
<h2 id="usage">Usage</h2>
|
133
|
+
|
134
|
+
<h3 id="storeresult"><code>StoreResult</code></h3>
|
135
|
+
|
136
|
+
<p><code>StoreReult</code> is used as the return value from all <code>Repository::Base</code> instance
|
137
|
+
methods (actions) <em>except</em> <code>#all</code>.</p>
|
138
|
+
|
139
|
+
<p>If the action implemented by the method was successful, it returns a
|
140
|
+
<code>StoreResult</code> where</p>
|
141
|
+
|
142
|
+
<ul>
|
143
|
+
<li>the <code>entity</code> attribute is an entity matching the state of the record persisted or accessed by the action;</li>
|
144
|
+
<li>the <code>success</code> attribute (or <code>#success?</code> method) is <code>true</code>; and</li>
|
145
|
+
<li>the <code>errors</code> attribute is an empty Array.</li>
|
146
|
+
</ul>
|
147
|
+
|
148
|
+
<p>If the action was unsuccessful, the repository method returns a <code>StoreResult</code>
|
149
|
+
where</p>
|
150
|
+
|
151
|
+
<ul>
|
152
|
+
<li>the <code>entity</code> attribute is <code>nil</code>;</li>
|
153
|
+
<li>the <code>success</code> attribute (or <code>#success?</code> method) is <code>false</code>; and</li>
|
154
|
+
<li>the <code>errors</code> attribute contains one error Hash for each error preventing the action from succeeding.</li>
|
155
|
+
</ul>
|
156
|
+
|
157
|
+
<h4 id="storeresultsuccess"><code>StoreResult::Success</code></h4>
|
158
|
+
|
159
|
+
<p>This subclass of <code>StoreResult</code> is a convenience for initialising a successful
|
160
|
+
<code>StoreResult</code>. Its <code>#initialize</code> method takes a single parameter, the entity to
|
161
|
+
be used in the result, with the other fields set as described above for a
|
162
|
+
successful result.</p>
|
163
|
+
|
164
|
+
<h4 id="storeresultfailure"><code>StoreResult::Failure</code></h4>
|
165
|
+
|
166
|
+
<p>This subclass of <code>StoreResult</code> is a convenience for initialising an unsuccessful
|
167
|
+
<code>StoreResult</code>. Its <code>#initialize</code> method takes a single parameter, the Array of
|
168
|
+
error hashes to be used in the result, with the other fields set as described
|
169
|
+
above for an unsuccessful result.</p>
|
170
|
+
|
171
|
+
<h3 id="errorfactory"><code>ErrorFactory</code></h3>
|
172
|
+
|
173
|
+
<p>This class has a single class method, <code>.create</code>. Given a parameter value that
|
174
|
+
quacks as an<a href="http://api.rubyonrails.org/classes/ActiveModel/Errors.html"><code>ActiveModel::Errors</code></a>
|
175
|
+
instance, it returns an Array where each item is a Hash derived from each error
|
176
|
+
reported by the parameter object, or an empty Array if there are no errors. Each
|
177
|
+
Hash in the Array has two fields:</p>
|
178
|
+
|
179
|
+
<ol>
|
180
|
+
<li><code>field</code>, which contains the attribute passed to <a href="http://api.rubyonrails.org/classes/ActiveModel/Errors.html#method-i-add"><code>ActiveModel::Errors#add</code></a> <em>as a string</em>; and</li>
|
181
|
+
<li><code>message</code>, which contains the message as passed into the same <code>#add</code> call.</li>
|
182
|
+
</ol>
|
183
|
+
|
184
|
+
<p>So, given an <code>ActiveModel::Errors</code> object that resulted from the following code:</p>
|
185
|
+
|
186
|
+
<p><code>ruby
|
187
|
+
errors = ActiveModel::Errors.new self
|
188
|
+
# ...
|
189
|
+
errors.add :frobulator, 'does not frob'
|
190
|
+
errors.add :frobulator, `is busted'
|
191
|
+
errors.add :foo, 'is :foo'
|
192
|
+
# ...
|
193
|
+
error_data = ErrorFactory.create errors
|
194
|
+
@logger.log error_data
|
195
|
+
</code></p>
|
196
|
+
|
197
|
+
<p>the value of <code>error_data</code> written to the log would be (formatted for clarity)</p>
|
198
|
+
|
199
|
+
<p><code>
|
200
|
+
[
|
201
|
+
{field: 'frobulator', message: 'does not frob'},
|
202
|
+
{field: 'frobulator', message: 'is busted'},
|
203
|
+
{field: 'foo', 'is :foo'}
|
204
|
+
]
|
205
|
+
</code></p>
|
206
|
+
|
207
|
+
<p>Note that no guarantees are made for ordering, just as seems to be the case for
|
208
|
+
<code>ActiveModel::Errors</code>.</p>
|
209
|
+
|
210
|
+
<h3 id="testattributecontainer"><code>TestAttributeContainer</code></h3>
|
211
|
+
|
212
|
+
<p>This module implements support for attributes in a way that can be thought of as “halfway between a <a href="http://ruby-doc.org//core-2.1.5/Struct.html"><code>Struct</code></a> and an <a href="http://ruby-doc.org/stdlib-2.1.5/libdoc/ostruct/rdoc/OpenStruct.html"><code>OpenStruct</code></a> or <a href="https://github.com/tomchapin/fancy-open-struct/"><code>FancyOpenStruct</code></a>.”</p>
|
213
|
+
|
214
|
+
<p>By extending a class with the module and invoking the <code>init_empty_attribute_container</code> class method within that class, a Hash is added as the <code>attributes</code> attribute of each instance of that class. It can be assigned to directly; once having done so, individual “attributes” may be accessed <em>or modified</em> through a method call using the name of the attribute.</p>
|
215
|
+
|
216
|
+
<p>For example:</p>
|
217
|
+
|
218
|
+
<p>```ruby
|
219
|
+
class Foo
|
220
|
+
extend Repository::Support::TestAttributeContainer</p>
|
221
|
+
|
222
|
+
<p>init_empty_attribute_container
|
223
|
+
end</p>
|
224
|
+
|
225
|
+
<h1 id="interactively">interactively</h1>
|
226
|
+
<p>foo = Foo.new
|
227
|
+
# => #<Foo:0x007fd2b4b9da28>
|
228
|
+
foo.attributes
|
229
|
+
# => {}
|
230
|
+
foo.attributes = { foo: true, bar: 42 }
|
231
|
+
# => :bar=>42
|
232
|
+
foo.foo
|
233
|
+
# => true
|
234
|
+
foo.foo = :whatever_you_want
|
235
|
+
# => :whatever_you_want
|
236
|
+
foo.attributes
|
237
|
+
# => :bar=>42
|
238
|
+
foo.quux
|
239
|
+
# => NoMethodError: undefined method `quux' # ...
|
240
|
+
foo.attributes[:quux] = 'hello'
|
241
|
+
# => "hello"
|
242
|
+
foo.quux
|
243
|
+
# => "hello"
|
244
|
+
```</Foo:0x007fd2b4b9da28></p>
|
245
|
+
|
246
|
+
<p>To create a new attribute after the container has been set up, assign to a new key in the <code>attributes</code> 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 <code>attributes</code>, however, undefined methods raise errors as usual.</p>
|
247
|
+
|
248
|
+
<h3 id="a-note-on-parameters">A Note on Parameters</h3>
|
249
|
+
|
250
|
+
<p>All <em>public</em> methods having multiple arguments (including <code>#initialize</code>) in each
|
251
|
+
of the classes defined above use the keyword-argument specification introduced
|
252
|
+
in Ruby 2.0. By removing order dependency of arguments, inadvertent-reordering
|
253
|
+
errors are no longer a
|
254
|
+
<a href="http://en.wikipedia.org/wiki/Hunt_the_Wumpus">hunt-the-typo</a>
|
255
|
+
exercise. This rule <em>does not</em> apply to single-parameter methods, nor to
|
256
|
+
<code>private</code> methods.</p>
|
257
|
+
|
258
|
+
<h2 id="contributing">Contributing</h2>
|
259
|
+
|
260
|
+
<ol>
|
261
|
+
<li>Fork it ( https://github.com/jdickey/repository-support/fork )</li>
|
262
|
+
<li>Create your feature branch (<code>git checkout -b my-new-feature</code>)</li>
|
263
|
+
<li>Ensure that your changes are completely covered by <em>passing</em> specs, and comply with the <a href="https://github.com/bbatsov/ruby-style-guide">Ruby Style Guide</a> as enforced by <a href="https://github.com/bbatsov/rubocop">RuboCop</a>. To verify this, run <code>bundle exec rake</code>, noting and repairing any lapses in coverage or style violations;</li>
|
264
|
+
<li>Commit your changes (<code>git commit -a</code>). Please <em>do not</em> use a single-line commit message (<code>git commit -am "some message"</code>). 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;</li>
|
265
|
+
<li>Push to the branch (<code>git push origin my-new-feature</code>)</li>
|
266
|
+
<li>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. <em>If this is a modification to existing code, reference the open issue being addressed</em>.</li>
|
267
|
+
<li>Don’t be discouraged if the PR generates a discussion that leads to further refinement of your PR through additional commits. These should <em>generally</em> be discussed in comments on the PR itself; discussion in the Gitter room (see below) may also be useful;</li>
|
268
|
+
<li>If you’ve comments, questions, or just want to talk through your ideas, don’t hesitate to hang out in the <code>Repository::Base</code> <a href="https://gitter.im/jdickey/repository-base">room on Gitter</a>. Ask away!</li>
|
269
|
+
</ol>
|
270
|
+
|
271
|
+
<h2 id="version-history">Version History</h2>
|
272
|
+
|
273
|
+
<table>
|
274
|
+
<thead>
|
275
|
+
<tr>
|
276
|
+
<th>Version</th>
|
277
|
+
<th>Date</th>
|
278
|
+
<th>Notes</th>
|
279
|
+
</tr>
|
280
|
+
</thead>
|
281
|
+
<tbody>
|
282
|
+
<tr>
|
283
|
+
<td>v0.1.0</td>
|
284
|
+
<td>2 February 2018</td>
|
285
|
+
<td>Changed MRI supported version from 2.2.2 to 2.5.0; <strong>published legacy notice</strong></td>
|
286
|
+
</tr>
|
287
|
+
<tr>
|
288
|
+
<td>v0.0.4</td>
|
289
|
+
<td>9 March 2015</td>
|
290
|
+
<td>Added experimental, one-off JRuby 9000 support</td>
|
291
|
+
</tr>
|
292
|
+
<tr>
|
293
|
+
<td>v0.0.3</td>
|
294
|
+
<td>21 February 2015</td>
|
295
|
+
<td>Completed initial feature development</td>
|
296
|
+
</tr>
|
297
|
+
<tr>
|
298
|
+
<td>v0.0.2</td>
|
299
|
+
<td>18 February 2015</td>
|
300
|
+
<td>Internal; incremental feature development</td>
|
301
|
+
</tr>
|
302
|
+
<tr>
|
303
|
+
<td>v0.0.1</td>
|
304
|
+
<td>18 February 2015</td>
|
305
|
+
<td>Internal; incremental feature development</td>
|
306
|
+
</tr>
|
307
|
+
</tbody>
|
308
|
+
</table>
|
309
|
+
|
310
|
+
<h2 id="legal">Legal</h2>
|
311
|
+
|
312
|
+
<p>This document and the accompanying code are Copyright © 2015-2018 by Jeff Dickey/Seven Sigma Agility, and are released under the terms of the <a href="https://opensource.org/licenses/MIT">MIT License</a>.</p>
|
313
|
+
</div></div>
|
314
|
+
|
315
|
+
<div id="footer">
|
316
|
+
Generated on Sun Feb 4 17:26:37 2018 by
|
317
|
+
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
318
|
+
0.9.12 (ruby-2.5.0).
|
319
|
+
</div>
|
320
|
+
|
321
|
+
</div>
|
322
|
+
</body>
|
323
|
+
</html>
|
data/doc/file_list.html
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
5
|
+
<meta charset="utf-8" />
|
6
|
+
|
7
|
+
<link rel="stylesheet" href="css/full_list.css" type="text/css" media="screen" charset="utf-8" />
|
8
|
+
|
9
|
+
<link rel="stylesheet" href="css/common.css" type="text/css" media="screen" charset="utf-8" />
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
14
|
+
|
15
|
+
<script type="text/javascript" charset="utf-8" src="js/full_list.js"></script>
|
16
|
+
|
17
|
+
|
18
|
+
<title>File List</title>
|
19
|
+
<base id="base_target" target="_parent" />
|
20
|
+
</head>
|
21
|
+
<body>
|
22
|
+
<div id="content">
|
23
|
+
<div class="fixed_header">
|
24
|
+
<h1 id="full_list_header">File List</h1>
|
25
|
+
<div id="full_list_nav">
|
26
|
+
|
27
|
+
<span><a target="_self" href="class_list.html">
|
28
|
+
Classes
|
29
|
+
</a></span>
|
30
|
+
|
31
|
+
<span><a target="_self" href="method_list.html">
|
32
|
+
Methods
|
33
|
+
</a></span>
|
34
|
+
|
35
|
+
<span><a target="_self" href="file_list.html">
|
36
|
+
Files
|
37
|
+
</a></span>
|
38
|
+
|
39
|
+
</div>
|
40
|
+
|
41
|
+
<div id="search">Search: <input type="text" /></div>
|
42
|
+
</div>
|
43
|
+
|
44
|
+
<ul id="full_list" class="file">
|
45
|
+
|
46
|
+
|
47
|
+
<li id="object_README" class="odd">
|
48
|
+
<div class="item"><span class="object_link"><a href="index.html" title="README">README</a></span></div>
|
49
|
+
</li>
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
</ul>
|
54
|
+
</div>
|
55
|
+
</body>
|
56
|
+
</html>
|
data/doc/frames.html
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<title>Documentation by YARD 0.9.12</title>
|
6
|
+
</head>
|
7
|
+
<script type="text/javascript" charset="utf-8">
|
8
|
+
var match = unescape(window.location.hash).match(/^#!(.+)/);
|
9
|
+
var name = match ? match[1] : 'index.html';
|
10
|
+
name = name.replace(/^(\w+):\/\//, '').replace(/^\/\//, '');
|
11
|
+
window.top.location = name;
|
12
|
+
</script>
|
13
|
+
<noscript>
|
14
|
+
<h1>Oops!</h1>
|
15
|
+
<h2>YARD requires JavaScript!</h2>
|
16
|
+
</noscript>
|
17
|
+
</html>
|
data/doc/index.html
ADDED
@@ -0,0 +1,323 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset="UTF-8">
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6
|
+
<title>
|
7
|
+
File: README
|
8
|
+
|
9
|
+
— Documentation by YARD 0.9.12
|
10
|
+
|
11
|
+
</title>
|
12
|
+
|
13
|
+
<link rel="stylesheet" href="css/style.css" type="text/css" charset="utf-8" />
|
14
|
+
|
15
|
+
<link rel="stylesheet" href="css/common.css" type="text/css" charset="utf-8" />
|
16
|
+
|
17
|
+
<script type="text/javascript" charset="utf-8">
|
18
|
+
pathId = "README";
|
19
|
+
relpath = '';
|
20
|
+
</script>
|
21
|
+
|
22
|
+
|
23
|
+
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
24
|
+
|
25
|
+
<script type="text/javascript" charset="utf-8" src="js/app.js"></script>
|
26
|
+
|
27
|
+
|
28
|
+
</head>
|
29
|
+
<body>
|
30
|
+
<div class="nav_wrap">
|
31
|
+
<iframe id="nav" src="class_list.html?1"></iframe>
|
32
|
+
<div id="resizer"></div>
|
33
|
+
</div>
|
34
|
+
|
35
|
+
<div id="main" tabindex="-1">
|
36
|
+
<div id="header">
|
37
|
+
<div id="menu">
|
38
|
+
|
39
|
+
<a href="_index.html">Index</a> »
|
40
|
+
<span class="title">File: README</span>
|
41
|
+
|
42
|
+
</div>
|
43
|
+
|
44
|
+
<div id="search">
|
45
|
+
|
46
|
+
<a class="full_list_link" id="class_list_link"
|
47
|
+
href="class_list.html">
|
48
|
+
|
49
|
+
<svg width="24" height="24">
|
50
|
+
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
51
|
+
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
52
|
+
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
53
|
+
</svg>
|
54
|
+
</a>
|
55
|
+
|
56
|
+
</div>
|
57
|
+
<div class="clear"></div>
|
58
|
+
</div>
|
59
|
+
|
60
|
+
<div id="content"><div id='filecontents'><h1>Repository::Support</h1>
|
61
|
+
|
62
|
+
<p><a href="http://badge.fury.io/rb/repository-support"><img src="https://badge.fury.io/rb/repository-support.svg" alt="Gem Version" /></a>
|
63
|
+
<a href="https://codeclimate.com/github/jdickey/repository-support"><img src="https://codeclimate.com/github/jdickey/repository-support/badges/gpa.svg" alt="Code Climate" /></a>
|
64
|
+
<a href="https://codeship.com/projects/63652"> <img src="https://codeship.com/projects/224d6180-997e-0132-c9c3-165733f17d49/status?branch=master" alt="Codeship Status for jdickey/repository-support" /></a>
|
65
|
+
<a href="https://hakiri.io/github/jdickey/repository-support/master"><img src="https://hakiri.io/github/jdickey/repository-support/master.svg" alt="security" /></a>
|
66
|
+
<a href="https://gemnasium.com/jdickey/repository-support"><img src="https://gemnasium.com/jdickey/repository-support.svg" alt="Dependency Status" /></a></p>
|
67
|
+
|
68
|
+
<h2>Contents</h2>
|
69
|
+
|
70
|
+
<ul>
|
71
|
+
<li><a href="#overview">Overview</a></li>
|
72
|
+
<li><a href="#important-legacy-notice">IMPORTANT LEGACY NOTICE</a></li>
|
73
|
+
<li><a href="#installation">Installation</a></li>
|
74
|
+
<li><a href="#usage">Usage</a>
|
75
|
+
<ul>
|
76
|
+
<li><a href="#storeresult"><code>StoreResult</code></a>
|
77
|
+
<ul>
|
78
|
+
<li><a href="#storeresultsuccess"><code>StoreResult::Success</code></a></li>
|
79
|
+
<li><a href="#storeresultfailure"><code>StoreResult::Failure</code></a></li>
|
80
|
+
</ul>
|
81
|
+
</li>
|
82
|
+
<li><a href="#errorfactory"><code>ErrorFactory</code></a></li>
|
83
|
+
<li><a href="#testattributecontainer"><code>TestAttributeContainer</code></a></li>
|
84
|
+
<li><a href="#a-note-on-parameters">A Note on Parameters</a></li>
|
85
|
+
</ul>
|
86
|
+
</li>
|
87
|
+
<li><a href="#contributing">Contributing</a></li>
|
88
|
+
<li><a href="#version-history">Version History</a></li>
|
89
|
+
<li><a href="#legal">Legal</a></li>
|
90
|
+
</ul>
|
91
|
+
|
92
|
+
<h2 id="overview">Overview</h2>
|
93
|
+
|
94
|
+
<p>This Gem provides several support classes and modules for
|
95
|
+
<a href="https://github.com/jdickey/repository-base"><code>Repository::Base</code></a> and its
|
96
|
+
user-created subclasses, which implement the Repository layer of a typical Data
|
97
|
+
Mapper pattern architecture.</p>
|
98
|
+
|
99
|
+
<p>These classes and modules are:</p>
|
100
|
+
|
101
|
+
<ul>
|
102
|
+
<li><code>ErrorFactory</code> provides a single class method, <code>.create</code> which, when supplied with an <code>ActiveModel::Errors</code>-quacking object as a parameter, produces an Array of Hashes containing JSON-compatible error information;</li>
|
103
|
+
<li><code>ResultBuilder</code> is a Command-pattern class whose <code>#initialize</code> method takes one parameter and whose <code>#build</code> method evaluates that value. If it is truthy, then <code>#build</code> returns a <code>StoreResult::Success</code> (see below) with that value as its “paylaaod”. If the value is falsy, then <code>#build</code> returns a <code>StoreResult#Failure</code>, yielding the value to a block that returns the payload for the <code>StoreResult</code>.</li>
|
104
|
+
<li><code>StoreResult</code> is a simple value object with three accessors for values passed in to the <code>#initialize</code> method: namely <code>#entity</code> (some value object); <code>#success</code> (a Boolean, aliased as <code>#success?</code>); and <code>#errors</code> an Array of error records as created by <code>ErrorFactory.create</code>. It has two subclasses: <code>StoreResult::Success</code> fills in a <code>StoreResult</code> using its single parameter (the entity) and defaults for the other fields; and <code>StoreResult::Failure</code>, which does likewise initialised with an array of error hashes.</li>
|
105
|
+
<li><code>TestAttributeContainer</code> is a module that, when used to extend a class, adds an <code>attributes</code> Hash property (reader and writer) to the extending class. While <code>attributes</code> is initially empty, it may be added to either by defining a single key, or by mass-assigning a Hash to <code>attributes</code>. 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.</li>
|
106
|
+
</ul>
|
107
|
+
|
108
|
+
<h2 id="important-legacy-notice">IMPORTANT LEGACY NOTICE</h2>
|
109
|
+
|
110
|
+
<p><strong><em>NOTICE!</em></strong> 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.</p>
|
111
|
+
|
112
|
+
<p>As such, it has been superseded and far outshone by other, team efforts, notably <a href="http://rom-rb.org/">ROM</a> as used with <a href="http://hanamirb.org/">Hanami</a> and <a href="http://trailblazer.to/">Trailblazer</a>. You are <em>strongly advised</em> to examine these and other tools rather than to use this for <em>any</em> new development. The Gem is being republished as an 0.1.0 release purely for internal archaeologigical purposes.</p>
|
113
|
+
|
114
|
+
<h2 id="installation">Installation</h2>
|
115
|
+
|
116
|
+
<p>Add this line to your application’s Gemfile:</p>
|
117
|
+
|
118
|
+
<p><code>ruby
|
119
|
+
gem 'repository-support'
|
120
|
+
</code></p>
|
121
|
+
|
122
|
+
<p>And then execute:</p>
|
123
|
+
|
124
|
+
<pre class="code ruby"><code class="ruby">$ bundle
|
125
|
+
</code></pre>
|
126
|
+
|
127
|
+
<p>Or install it yourself as:</p>
|
128
|
+
|
129
|
+
<pre class="code ruby"><code class="ruby">$ gem install repository-support
|
130
|
+
</code></pre>
|
131
|
+
|
132
|
+
<h2 id="usage">Usage</h2>
|
133
|
+
|
134
|
+
<h3 id="storeresult"><code>StoreResult</code></h3>
|
135
|
+
|
136
|
+
<p><code>StoreReult</code> is used as the return value from all <code>Repository::Base</code> instance
|
137
|
+
methods (actions) <em>except</em> <code>#all</code>.</p>
|
138
|
+
|
139
|
+
<p>If the action implemented by the method was successful, it returns a
|
140
|
+
<code>StoreResult</code> where</p>
|
141
|
+
|
142
|
+
<ul>
|
143
|
+
<li>the <code>entity</code> attribute is an entity matching the state of the record persisted or accessed by the action;</li>
|
144
|
+
<li>the <code>success</code> attribute (or <code>#success?</code> method) is <code>true</code>; and</li>
|
145
|
+
<li>the <code>errors</code> attribute is an empty Array.</li>
|
146
|
+
</ul>
|
147
|
+
|
148
|
+
<p>If the action was unsuccessful, the repository method returns a <code>StoreResult</code>
|
149
|
+
where</p>
|
150
|
+
|
151
|
+
<ul>
|
152
|
+
<li>the <code>entity</code> attribute is <code>nil</code>;</li>
|
153
|
+
<li>the <code>success</code> attribute (or <code>#success?</code> method) is <code>false</code>; and</li>
|
154
|
+
<li>the <code>errors</code> attribute contains one error Hash for each error preventing the action from succeeding.</li>
|
155
|
+
</ul>
|
156
|
+
|
157
|
+
<h4 id="storeresultsuccess"><code>StoreResult::Success</code></h4>
|
158
|
+
|
159
|
+
<p>This subclass of <code>StoreResult</code> is a convenience for initialising a successful
|
160
|
+
<code>StoreResult</code>. Its <code>#initialize</code> method takes a single parameter, the entity to
|
161
|
+
be used in the result, with the other fields set as described above for a
|
162
|
+
successful result.</p>
|
163
|
+
|
164
|
+
<h4 id="storeresultfailure"><code>StoreResult::Failure</code></h4>
|
165
|
+
|
166
|
+
<p>This subclass of <code>StoreResult</code> is a convenience for initialising an unsuccessful
|
167
|
+
<code>StoreResult</code>. Its <code>#initialize</code> method takes a single parameter, the Array of
|
168
|
+
error hashes to be used in the result, with the other fields set as described
|
169
|
+
above for an unsuccessful result.</p>
|
170
|
+
|
171
|
+
<h3 id="errorfactory"><code>ErrorFactory</code></h3>
|
172
|
+
|
173
|
+
<p>This class has a single class method, <code>.create</code>. Given a parameter value that
|
174
|
+
quacks as an<a href="http://api.rubyonrails.org/classes/ActiveModel/Errors.html"><code>ActiveModel::Errors</code></a>
|
175
|
+
instance, it returns an Array where each item is a Hash derived from each error
|
176
|
+
reported by the parameter object, or an empty Array if there are no errors. Each
|
177
|
+
Hash in the Array has two fields:</p>
|
178
|
+
|
179
|
+
<ol>
|
180
|
+
<li><code>field</code>, which contains the attribute passed to <a href="http://api.rubyonrails.org/classes/ActiveModel/Errors.html#method-i-add"><code>ActiveModel::Errors#add</code></a> <em>as a string</em>; and</li>
|
181
|
+
<li><code>message</code>, which contains the message as passed into the same <code>#add</code> call.</li>
|
182
|
+
</ol>
|
183
|
+
|
184
|
+
<p>So, given an <code>ActiveModel::Errors</code> object that resulted from the following code:</p>
|
185
|
+
|
186
|
+
<p><code>ruby
|
187
|
+
errors = ActiveModel::Errors.new self
|
188
|
+
# ...
|
189
|
+
errors.add :frobulator, 'does not frob'
|
190
|
+
errors.add :frobulator, `is busted'
|
191
|
+
errors.add :foo, 'is :foo'
|
192
|
+
# ...
|
193
|
+
error_data = ErrorFactory.create errors
|
194
|
+
@logger.log error_data
|
195
|
+
</code></p>
|
196
|
+
|
197
|
+
<p>the value of <code>error_data</code> written to the log would be (formatted for clarity)</p>
|
198
|
+
|
199
|
+
<p><code>
|
200
|
+
[
|
201
|
+
{field: 'frobulator', message: 'does not frob'},
|
202
|
+
{field: 'frobulator', message: 'is busted'},
|
203
|
+
{field: 'foo', 'is :foo'}
|
204
|
+
]
|
205
|
+
</code></p>
|
206
|
+
|
207
|
+
<p>Note that no guarantees are made for ordering, just as seems to be the case for
|
208
|
+
<code>ActiveModel::Errors</code>.</p>
|
209
|
+
|
210
|
+
<h3 id="testattributecontainer"><code>TestAttributeContainer</code></h3>
|
211
|
+
|
212
|
+
<p>This module implements support for attributes in a way that can be thought of as “halfway between a <a href="http://ruby-doc.org//core-2.1.5/Struct.html"><code>Struct</code></a> and an <a href="http://ruby-doc.org/stdlib-2.1.5/libdoc/ostruct/rdoc/OpenStruct.html"><code>OpenStruct</code></a> or <a href="https://github.com/tomchapin/fancy-open-struct/"><code>FancyOpenStruct</code></a>.”</p>
|
213
|
+
|
214
|
+
<p>By extending a class with the module and invoking the <code>init_empty_attribute_container</code> class method within that class, a Hash is added as the <code>attributes</code> attribute of each instance of that class. It can be assigned to directly; once having done so, individual “attributes” may be accessed <em>or modified</em> through a method call using the name of the attribute.</p>
|
215
|
+
|
216
|
+
<p>For example:</p>
|
217
|
+
|
218
|
+
<p>```ruby
|
219
|
+
class Foo
|
220
|
+
extend Repository::Support::TestAttributeContainer</p>
|
221
|
+
|
222
|
+
<p>init_empty_attribute_container
|
223
|
+
end</p>
|
224
|
+
|
225
|
+
<h1 id="interactively">interactively</h1>
|
226
|
+
<p>foo = Foo.new
|
227
|
+
# => #<Foo:0x007fd2b4b9da28>
|
228
|
+
foo.attributes
|
229
|
+
# => {}
|
230
|
+
foo.attributes = { foo: true, bar: 42 }
|
231
|
+
# => :bar=>42
|
232
|
+
foo.foo
|
233
|
+
# => true
|
234
|
+
foo.foo = :whatever_you_want
|
235
|
+
# => :whatever_you_want
|
236
|
+
foo.attributes
|
237
|
+
# => :bar=>42
|
238
|
+
foo.quux
|
239
|
+
# => NoMethodError: undefined method `quux' # ...
|
240
|
+
foo.attributes[:quux] = 'hello'
|
241
|
+
# => "hello"
|
242
|
+
foo.quux
|
243
|
+
# => "hello"
|
244
|
+
```</Foo:0x007fd2b4b9da28></p>
|
245
|
+
|
246
|
+
<p>To create a new attribute after the container has been set up, assign to a new key in the <code>attributes</code> 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 <code>attributes</code>, however, undefined methods raise errors as usual.</p>
|
247
|
+
|
248
|
+
<h3 id="a-note-on-parameters">A Note on Parameters</h3>
|
249
|
+
|
250
|
+
<p>All <em>public</em> methods having multiple arguments (including <code>#initialize</code>) in each
|
251
|
+
of the classes defined above use the keyword-argument specification introduced
|
252
|
+
in Ruby 2.0. By removing order dependency of arguments, inadvertent-reordering
|
253
|
+
errors are no longer a
|
254
|
+
<a href="http://en.wikipedia.org/wiki/Hunt_the_Wumpus">hunt-the-typo</a>
|
255
|
+
exercise. This rule <em>does not</em> apply to single-parameter methods, nor to
|
256
|
+
<code>private</code> methods.</p>
|
257
|
+
|
258
|
+
<h2 id="contributing">Contributing</h2>
|
259
|
+
|
260
|
+
<ol>
|
261
|
+
<li>Fork it ( https://github.com/jdickey/repository-support/fork )</li>
|
262
|
+
<li>Create your feature branch (<code>git checkout -b my-new-feature</code>)</li>
|
263
|
+
<li>Ensure that your changes are completely covered by <em>passing</em> specs, and comply with the <a href="https://github.com/bbatsov/ruby-style-guide">Ruby Style Guide</a> as enforced by <a href="https://github.com/bbatsov/rubocop">RuboCop</a>. To verify this, run <code>bundle exec rake</code>, noting and repairing any lapses in coverage or style violations;</li>
|
264
|
+
<li>Commit your changes (<code>git commit -a</code>). Please <em>do not</em> use a single-line commit message (<code>git commit -am "some message"</code>). 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;</li>
|
265
|
+
<li>Push to the branch (<code>git push origin my-new-feature</code>)</li>
|
266
|
+
<li>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. <em>If this is a modification to existing code, reference the open issue being addressed</em>.</li>
|
267
|
+
<li>Don’t be discouraged if the PR generates a discussion that leads to further refinement of your PR through additional commits. These should <em>generally</em> be discussed in comments on the PR itself; discussion in the Gitter room (see below) may also be useful;</li>
|
268
|
+
<li>If you’ve comments, questions, or just want to talk through your ideas, don’t hesitate to hang out in the <code>Repository::Base</code> <a href="https://gitter.im/jdickey/repository-base">room on Gitter</a>. Ask away!</li>
|
269
|
+
</ol>
|
270
|
+
|
271
|
+
<h2 id="version-history">Version History</h2>
|
272
|
+
|
273
|
+
<table>
|
274
|
+
<thead>
|
275
|
+
<tr>
|
276
|
+
<th>Version</th>
|
277
|
+
<th>Date</th>
|
278
|
+
<th>Notes</th>
|
279
|
+
</tr>
|
280
|
+
</thead>
|
281
|
+
<tbody>
|
282
|
+
<tr>
|
283
|
+
<td>v0.1.0</td>
|
284
|
+
<td>2 February 2018</td>
|
285
|
+
<td>Changed MRI supported version from 2.2.2 to 2.5.0; <strong>published legacy notice</strong></td>
|
286
|
+
</tr>
|
287
|
+
<tr>
|
288
|
+
<td>v0.0.4</td>
|
289
|
+
<td>9 March 2015</td>
|
290
|
+
<td>Added experimental, one-off JRuby 9000 support</td>
|
291
|
+
</tr>
|
292
|
+
<tr>
|
293
|
+
<td>v0.0.3</td>
|
294
|
+
<td>21 February 2015</td>
|
295
|
+
<td>Completed initial feature development</td>
|
296
|
+
</tr>
|
297
|
+
<tr>
|
298
|
+
<td>v0.0.2</td>
|
299
|
+
<td>18 February 2015</td>
|
300
|
+
<td>Internal; incremental feature development</td>
|
301
|
+
</tr>
|
302
|
+
<tr>
|
303
|
+
<td>v0.0.1</td>
|
304
|
+
<td>18 February 2015</td>
|
305
|
+
<td>Internal; incremental feature development</td>
|
306
|
+
</tr>
|
307
|
+
</tbody>
|
308
|
+
</table>
|
309
|
+
|
310
|
+
<h2 id="legal">Legal</h2>
|
311
|
+
|
312
|
+
<p>This document and the accompanying code are Copyright © 2015-2018 by Jeff Dickey/Seven Sigma Agility, and are released under the terms of the <a href="https://opensource.org/licenses/MIT">MIT License</a>.</p>
|
313
|
+
</div></div>
|
314
|
+
|
315
|
+
<div id="footer">
|
316
|
+
Generated on Sun Feb 4 17:26:37 2018 by
|
317
|
+
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
318
|
+
0.9.12 (ruby-2.5.0).
|
319
|
+
</div>
|
320
|
+
|
321
|
+
</div>
|
322
|
+
</body>
|
323
|
+
</html>
|