qo 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.yardopts +3 -0
- data/README.md +35 -2
- data/Rakefile +65 -13
- data/docs/Qo.html +165 -0
- data/docs/Qo/Exceptions.html +160 -0
- data/docs/Qo/Exceptions/MultipleMatchersProvided.html +257 -0
- data/docs/Qo/Exceptions/NoMatchersProvided.html +257 -0
- data/docs/Qo/Exceptions/NotAllGuardMatchersProvided.html +260 -0
- data/docs/Qo/Helpers.html +382 -0
- data/docs/Qo/Matchers.html +169 -0
- data/docs/Qo/Matchers/ArrayMatcher.html +459 -0
- data/docs/Qo/Matchers/BaseMatcher.html +493 -0
- data/docs/Qo/Matchers/GuardBlockMatcher.html +471 -0
- data/docs/Qo/Matchers/HashMatcher.html +445 -0
- data/docs/Qo/Matchers/PatternMatch.html +551 -0
- data/docs/Qo/PublicApi.html +867 -0
- data/docs/_index.html +258 -0
- data/docs/class_list.html +51 -0
- data/docs/css/common.css +1 -0
- data/docs/css/full_list.css +58 -0
- data/docs/css/style.css +499 -0
- data/docs/file.README.html +701 -0
- data/docs/file_list.html +56 -0
- data/docs/frames.html +17 -0
- data/docs/img/qo_logo.png +0 -0
- data/docs/index.html +701 -0
- data/docs/js/app.js +248 -0
- data/docs/js/full_list.js +216 -0
- data/docs/js/jquery.js +4 -0
- data/docs/method_list.html +227 -0
- data/docs/top-level-namespace.html +110 -0
- data/img/whoa_lemur.png +0 -0
- data/lib/qo/exceptions.rb +8 -4
- data/lib/qo/matchers/array_matcher.rb +34 -12
- data/lib/qo/matchers/base_matcher.rb +26 -11
- data/lib/qo/matchers/guard_block_matcher.rb +17 -3
- data/lib/qo/matchers/hash_matcher.rb +32 -23
- data/lib/qo/matchers/pattern_match.rb +2 -1
- data/lib/qo/public_api.rb +6 -5
- data/lib/qo/version.rb +1 -1
- data/performance_report.txt +73 -24
- data/qo.gemspec +2 -0
- metadata +61 -3
data/docs/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/docs/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>
|
Binary file
|
data/docs/index.html
ADDED
@@ -0,0 +1,701 @@
|
|
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>Qo</h1>
|
61
|
+
|
62
|
+
<p><a href="https://travis-ci.org/baweaver/qo"><img src="https://travis-ci.org/baweaver/qo.svg?branch=master" alt="Build Status"></a>
|
63
|
+
<a href="https://codeclimate.com/github/baweaver/qo/maintainability"><img src="https://api.codeclimate.com/v1/badges/186e9cbb7003842acaf0/maintainability" alt="Maintainability"></a>
|
64
|
+
<a href="https://badge.fury.io/rb/qo"><img src="https://badge.fury.io/rb/qo.svg" alt="Gem Version"></a></p>
|
65
|
+
|
66
|
+
<p>Short for Query Object, my play at Ruby pattern matching and fluent querying</p>
|
67
|
+
|
68
|
+
<p><img src="img/qo_logo.png" alt="Qo Lemur logo"></p>
|
69
|
+
|
70
|
+
<h2>How does it work?</h2>
|
71
|
+
|
72
|
+
<p>Mostly by using Ruby language features like <code>to_proc</code> and <code>===</code>.</p>
|
73
|
+
|
74
|
+
<p>There's an article explaining most of the base mechanics behind Qo:</p>
|
75
|
+
|
76
|
+
<p><a href="https://medium.com/@baweaver/for-want-of-pattern-matching-in-ruby-the-creation-of-qo-c3b267109b25">For Want of Pattern Matching in Ruby - The Creation of Qo</a></p>
|
77
|
+
|
78
|
+
<p>Most of it, though, utilizes Triple Equals. If you're not familiar with what all you can do with it in Ruby, I would encourage you to read this article as well:</p>
|
79
|
+
|
80
|
+
<p><a href="https://medium.com/rubyinside/triple-equals-black-magic-d934936a6379">Triple Equals Black Magic</a></p>
|
81
|
+
|
82
|
+
<p>The original inspiration was from a chat I'd had with a few other Rubyists about pattern matching, which led to this experiment:</p>
|
83
|
+
|
84
|
+
<p><a href="https://gist.github.com/baweaver/611389c41c9005d025fb8e55448bf5f5">Having fun with M and Q</a></p>
|
85
|
+
|
86
|
+
<p>Fast forward a few months and I kind of wanted to make it real, so here it is. Introducing Qo!</p>
|
87
|
+
|
88
|
+
<h2>Usage</h2>
|
89
|
+
|
90
|
+
<h3>Quick Start</h3>
|
91
|
+
|
92
|
+
<p>Qo is used for pattern matching in Ruby. All Qo matchers respond to <code>===</code> and <code>to_proc</code> meaning they can be used with <code>case</code> and Enumerable functions alike:</p>
|
93
|
+
|
94
|
+
<pre class="code ruby"><code class="ruby"><span class='kw'>case</span> <span class='lbracket'>[</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Foo</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='int'>42</span><span class='rbracket'>]</span>
|
95
|
+
<span class='kw'>when</span> <span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='symbol'>:*</span><span class='comma'>,</span> <span class='int'>42</span><span class='rbracket'>]</span> <span class='kw'>then</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Truly the one answer</span><span class='tstring_end'>'</span></span>
|
96
|
+
<span class='kw'>else</span> <span class='kw'>nil</span>
|
97
|
+
<span class='kw'>end</span>
|
98
|
+
|
99
|
+
<span class='comment'># Run a select like an AR query, getting the age attribute against a range
|
100
|
+
</span><span class='id identifier rubyid_people'>people</span><span class='period'>.</span><span class='id identifier rubyid_select'>select</span><span class='lparen'>(</span><span class='op'>&</span><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='label'>age:</span> <span class='int'>18</span><span class='op'>..</span><span class='int'>30</span><span class='rbracket'>]</span><span class='rparen'>)</span>
|
101
|
+
|
102
|
+
<span class='comment'># How about some "right-hand assignment" pattern matching
|
103
|
+
</span><span class='id identifier rubyid_name_longer_than_three'>name_longer_than_three</span> <span class='op'>=</span> <span class='tlambda'>-></span> <span class='id identifier rubyid_person'>person</span> <span class='tlambeg'>{</span> <span class='id identifier rubyid_person'>person</span><span class='period'>.</span><span class='id identifier rubyid_name'>name</span><span class='period'>.</span><span class='id identifier rubyid_size'>size</span> <span class='op'>></span> <span class='int'>3</span> <span class='rbrace'>}</span>
|
104
|
+
<span class='id identifier rubyid_people_with_truncated_names'>people_with_truncated_names</span> <span class='op'>=</span> <span class='id identifier rubyid_people'>people</span><span class='period'>.</span><span class='id identifier rubyid_map'>map</span><span class='lparen'>(</span><span class='op'>&</span><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_match'><span class='object_link'><a href="Qo/PublicApi.html#match-instance_method" title="Qo::PublicApi#match (method)">match</a></span></span><span class='lparen'>(</span>
|
105
|
+
<span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_m'>m</span><span class='lparen'>(</span><span class='id identifier rubyid_name_longer_than_three'>name_longer_than_three</span><span class='rparen'>)</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_person'>person</span><span class='op'>|</span> <span class='const'>Person</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span><span class='lparen'>(</span><span class='id identifier rubyid_person'>person</span><span class='period'>.</span><span class='id identifier rubyid_name'>name</span><span class='lbracket'>[</span><span class='int'>0</span><span class='op'>..</span><span class='int'>2</span><span class='rbracket'>]</span><span class='comma'>,</span> <span class='id identifier rubyid_person'>person</span><span class='period'>.</span><span class='id identifier rubyid_age'>age</span><span class='rparen'>)</span> <span class='rbrace'>}</span><span class='comma'>,</span>
|
106
|
+
<span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_m'>m</span><span class='lparen'>(</span><span class='symbol'>:*</span><span class='rparen'>)</span> <span class='comment'># Identity function, catch-all
|
107
|
+
</span><span class='rparen'>)</span><span class='rparen'>)</span>
|
108
|
+
|
109
|
+
<span class='comment'># And standalone like a case:
|
110
|
+
</span><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_match'><span class='object_link'><a href="Qo/PublicApi.html#match-instance_method" title="Qo::PublicApi#match (method)">match</a></span></span><span class='lparen'>(</span><span class='id identifier rubyid_people'>people</span><span class='period'>.</span><span class='id identifier rubyid_first'>first</span><span class='comma'>,</span>
|
111
|
+
<span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_m'>m</span><span class='lparen'>(</span><span class='label'>age:</span> <span class='int'>10</span><span class='op'>..</span><span class='int'>19</span><span class='rparen'>)</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_person'>person</span><span class='op'>|</span> <span class='tstring'><span class='tstring_beg'>"</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_person'>person</span><span class='period'>.</span><span class='id identifier rubyid_name'>name</span><span class='embexpr_end'>}</span><span class='tstring_content'> is a teen that's </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_person'>person</span><span class='period'>.</span><span class='id identifier rubyid_age'>age</span><span class='embexpr_end'>}</span><span class='tstring_content'> years old</span><span class='tstring_end'>"</span></span> <span class='rbrace'>}</span><span class='comma'>,</span>
|
112
|
+
<span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_m'>m</span><span class='lparen'>(</span><span class='symbol'>:*</span><span class='rparen'>)</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_person'>person</span><span class='op'>|</span> <span class='tstring'><span class='tstring_beg'>"</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_person'>person</span><span class='period'>.</span><span class='id identifier rubyid_name'>name</span><span class='embexpr_end'>}</span><span class='tstring_content'> is </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_person'>person</span><span class='period'>.</span><span class='id identifier rubyid_age'>age</span><span class='embexpr_end'>}</span><span class='tstring_content'> years old</span><span class='tstring_end'>"</span></span> <span class='rbrace'>}</span>
|
113
|
+
<span class='rparen'>)</span>
|
114
|
+
</code></pre>
|
115
|
+
|
116
|
+
<p>Get a lot more expressiveness in your queries and transformations. Read on for the full details.</p>
|
117
|
+
|
118
|
+
<h3>Qo'isms</h3>
|
119
|
+
|
120
|
+
<p>Qo supports three main types of queries: <code>and</code>, <code>or</code>, and <code>not</code>.</p>
|
121
|
+
|
122
|
+
<p>Most examples are written in terms of <code>and</code> and its alias <code>[]</code>. <code>[]</code> is mostly used for portable syntax:</p>
|
123
|
+
|
124
|
+
<pre class="code ruby"><code class="ruby"><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>Rob</span><span class='regexp_end'>/</span></span><span class='comma'>,</span> <span class='int'>22</span><span class='rbracket'>]</span>
|
125
|
+
|
126
|
+
<span class='comment'># ...is functionally the same as an and query, which uses `all?` to match
|
127
|
+
</span><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_and'><span class='object_link'><a href="Qo/PublicApi.html#and-instance_method" title="Qo::PublicApi#and (method)">and</a></span></span><span class='lparen'>(</span><span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>Rob</span><span class='regexp_end'>/</span></span><span class='comma'>,</span> <span class='int'>22</span><span class='rparen'>)</span>
|
128
|
+
|
129
|
+
<span class='comment'># This is shorthand for
|
130
|
+
</span><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Qo/Matchers.html" title="Qo::Matchers (module)">Matchers</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Qo/Matchers/BaseMatcher.html" title="Qo::Matchers::BaseMatcher (class)">BaseMatcher</a></span></span><span class='period'>.</span><span class='id identifier rubyid_new'><span class='object_link'><a href="Qo/Matchers/BaseMatcher.html#initialize-instance_method" title="Qo::Matchers::BaseMatcher#initialize (method)">new</a></span></span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>and</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>Rob</span><span class='regexp_end'>/</span></span><span class='comma'>,</span> <span class='int'>22</span><span class='rparen'>)</span>
|
131
|
+
|
132
|
+
<span class='comment'># An `or` matcher uses the same shorthand as `and` but uses `any?` behind the scenes instead:
|
133
|
+
</span><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_or'><span class='object_link'><a href="Qo/PublicApi.html#or-instance_method" title="Qo::PublicApi#or (method)">or</a></span></span><span class='lparen'>(</span><span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>Rob</span><span class='regexp_end'>/</span></span><span class='comma'>,</span> <span class='int'>22</span><span class='rparen'>)</span>
|
134
|
+
|
135
|
+
<span class='comment'># Same with not, except it uses `none?`
|
136
|
+
</span><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_not'><span class='object_link'><a href="Qo/PublicApi.html#not-instance_method" title="Qo::PublicApi#not (method)">not</a></span></span><span class='lparen'>(</span><span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>Rob</span><span class='regexp_end'>/</span></span><span class='comma'>,</span> <span class='int'>22</span><span class='rparen'>)</span>
|
137
|
+
</code></pre>
|
138
|
+
|
139
|
+
<p>Qo has a few Qo'isms, mainly based around triple equals in Ruby. See the above articles for tutorials on that count.</p>
|
140
|
+
|
141
|
+
<p>We will assume the following data:</p>
|
142
|
+
|
143
|
+
<pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_people_arrays'>people_arrays</span> <span class='op'>=</span> <span class='lbracket'>[</span>
|
144
|
+
<span class='lbracket'>[</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Robert</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='int'>22</span><span class='rbracket'>]</span><span class='comma'>,</span>
|
145
|
+
<span class='lbracket'>[</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Roberta</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='int'>22</span><span class='rbracket'>]</span><span class='comma'>,</span>
|
146
|
+
<span class='lbracket'>[</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Foo</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='int'>42</span><span class='rbracket'>]</span><span class='comma'>,</span>
|
147
|
+
<span class='lbracket'>[</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Bar</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='int'>18</span><span class='rbracket'>]</span>
|
148
|
+
<span class='rbracket'>]</span>
|
149
|
+
|
150
|
+
<span class='id identifier rubyid_people_objects'>people_objects</span> <span class='op'>=</span> <span class='lbracket'>[</span>
|
151
|
+
<span class='const'>Person</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Robert</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='int'>22</span><span class='rparen'>)</span><span class='comma'>,</span>
|
152
|
+
<span class='const'>Person</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Roberta</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='int'>22</span><span class='rparen'>)</span><span class='comma'>,</span>
|
153
|
+
<span class='const'>Person</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Foo</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='int'>42</span><span class='rparen'>)</span><span class='comma'>,</span>
|
154
|
+
<span class='const'>Person</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Bar</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='int'>17</span><span class='rparen'>)</span><span class='comma'>,</span>
|
155
|
+
<span class='rbracket'>]</span>
|
156
|
+
</code></pre>
|
157
|
+
|
158
|
+
<h3>1 - Wildcard Matching</h3>
|
159
|
+
|
160
|
+
<p>Qo has a concept of a Wildcard, <code>:*</code>, which will match against any value</p>
|
161
|
+
|
162
|
+
<pre class="code ruby"><code class="ruby"><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='symbol'>:*</span><span class='comma'>,</span> <span class='symbol'>:*</span><span class='rbracket'>]</span> <span class='op'>===</span> <span class='lbracket'>[</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Robert</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='int'>22</span><span class='rbracket'>]</span> <span class='comment'># true
|
163
|
+
</span></code></pre>
|
164
|
+
|
165
|
+
<p>A single wildcard will match anything, and can frequently be used as an always true:</p>
|
166
|
+
|
167
|
+
<pre class="code ruby"><code class="ruby"><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='symbol'>:*</span><span class='rbracket'>]</span> <span class='op'>===</span> <span class='symbol'>:literally_anything_here</span>
|
168
|
+
</code></pre>
|
169
|
+
|
170
|
+
<h3>2 - Array Matching</h3>
|
171
|
+
|
172
|
+
<p>The first way a Qo matcher can be defined is by using <code>*varargs</code>:</p>
|
173
|
+
|
174
|
+
<pre class="code ruby"><code class="ruby"><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Qo/Matchers.html" title="Qo::Matchers (module)">Matchers</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Qo/Matchers/BaseMatcher.html" title="Qo::Matchers::BaseMatcher (class)">BaseMatcher</a></span></span><span class='lparen'>(</span><span class='id identifier rubyid_type'>type</span><span class='comma'>,</span> <span class='op'>*</span><span class='id identifier rubyid_varargs'>varargs</span><span class='comma'>,</span> <span class='op'>**</span><span class='id identifier rubyid_kwargs'>kwargs</span><span class='rparen'>)</span>
|
175
|
+
</code></pre>
|
176
|
+
|
177
|
+
<p>This gives us the <code>and</code> matcher shorthand for array matchers.</p>
|
178
|
+
|
179
|
+
<h4>2.1 - Array matched against an Array</h4>
|
180
|
+
|
181
|
+
<p>When an Array matcher is run against an Array, it will compare elements by index in the following priority:</p>
|
182
|
+
|
183
|
+
<ol>
|
184
|
+
<li>Was a wildcard provided?</li>
|
185
|
+
<li>Does it case match (<code>===</code>)?</li>
|
186
|
+
<li>Does it have a predicate method by that name that matches?</li>
|
187
|
+
</ol>
|
188
|
+
|
189
|
+
<p>This functionality is left biased and permissive, meaning that if the right side of the argument is longer it will ignore those items in the match. If it's shorter? Not so much.</p>
|
190
|
+
|
191
|
+
<h5>2.1.1 - Wildcard provided</h5>
|
192
|
+
|
193
|
+
<pre class="code ruby"><code class="ruby"><span class='comment'># Standalone
|
194
|
+
</span>
|
195
|
+
<span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='symbol'>:*</span><span class='comma'>,</span> <span class='symbol'>:*</span><span class='rbracket'>]</span> <span class='op'>===</span> <span class='lbracket'>[</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Robert</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='int'>22</span><span class='rbracket'>]</span>
|
196
|
+
<span class='comment'># => true
|
197
|
+
</span>
|
198
|
+
<span class='comment'># Case statement
|
199
|
+
</span>
|
200
|
+
<span class='kw'>case</span> <span class='lbracket'>[</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Roberta</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='int'>22</span><span class='rbracket'>]</span>
|
201
|
+
<span class='kw'>when</span> <span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='symbol'>:*</span><span class='comma'>,</span> <span class='symbol'>:*</span><span class='rbracket'>]</span> <span class='kw'>then</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>it matched</span><span class='tstring_end'>'</span></span>
|
202
|
+
<span class='kw'>else</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>will not ever be reached</span><span class='tstring_end'>'</span></span>
|
203
|
+
<span class='kw'>end</span>
|
204
|
+
<span class='comment'># => 'it matched'
|
205
|
+
</span>
|
206
|
+
<span class='comment'># Select
|
207
|
+
</span>
|
208
|
+
<span class='id identifier rubyid_people_arrays'>people_arrays</span><span class='period'>.</span><span class='id identifier rubyid_select'>select</span><span class='lparen'>(</span><span class='op'>&</span><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='symbol'>:*</span><span class='comma'>,</span> <span class='symbol'>:*</span><span class='rbracket'>]</span><span class='rparen'>)</span>
|
209
|
+
<span class='comment'># => [['Robert', 22], ['Roberta', 22], ['Foo', 42], ['Bar', 18]]
|
210
|
+
</span></code></pre>
|
211
|
+
|
212
|
+
<h5>2.1.2 - Case Match present</h5>
|
213
|
+
|
214
|
+
<p>We've seen some case matching so far with <code>Range</code> and <code>Regex</code>:</p>
|
215
|
+
|
216
|
+
<pre class="code ruby"><code class="ruby"><span class='comment'># Standalone
|
217
|
+
</span>
|
218
|
+
<span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>Rob</span><span class='regexp_end'>/</span></span><span class='comma'>,</span> <span class='symbol'>:*</span><span class='rbracket'>]</span> <span class='op'>===</span> <span class='lbracket'>[</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Robert</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='int'>22</span><span class='rbracket'>]</span>
|
219
|
+
<span class='comment'># => true
|
220
|
+
</span>
|
221
|
+
<span class='comment'># Case statement
|
222
|
+
</span>
|
223
|
+
<span class='kw'>case</span> <span class='lbracket'>[</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Roberta</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='int'>22</span><span class='rbracket'>]</span>
|
224
|
+
<span class='kw'>when</span> <span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='symbol'>:*</span><span class='comma'>,</span> <span class='int'>0</span><span class='op'>..</span><span class='int'>9</span><span class='rbracket'>]</span> <span class='kw'>then</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>child</span><span class='tstring_end'>'</span></span>
|
225
|
+
<span class='kw'>when</span> <span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='symbol'>:*</span><span class='comma'>,</span> <span class='int'>10</span><span class='op'>..</span><span class='int'>19</span><span class='rbracket'>]</span> <span class='kw'>then</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>teen</span><span class='tstring_end'>'</span></span>
|
226
|
+
<span class='kw'>when</span> <span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='symbol'>:*</span><span class='comma'>,</span> <span class='int'>20</span><span class='op'>..</span><span class='int'>99</span><span class='rbracket'>]</span> <span class='kw'>then</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>adult</span><span class='tstring_end'>'</span></span>
|
227
|
+
<span class='kw'>else</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>not sure</span><span class='tstring_end'>'</span></span>
|
228
|
+
<span class='kw'>end</span>
|
229
|
+
<span class='comment'># => 'adult'
|
230
|
+
</span>
|
231
|
+
<span class='comment'># Select
|
232
|
+
</span>
|
233
|
+
<span class='id identifier rubyid_people_arrays'>people_arrays</span><span class='period'>.</span><span class='id identifier rubyid_select'>select</span><span class='lparen'>(</span><span class='op'>&</span><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='symbol'>:*</span><span class='comma'>,</span> <span class='int'>10</span><span class='op'>..</span><span class='int'>19</span><span class='rbracket'>]</span><span class='rparen'>)</span>
|
234
|
+
<span class='comment'># => [['Bar', 18]]
|
235
|
+
</span></code></pre>
|
236
|
+
|
237
|
+
<h5>2.1.3 - Predicate Method matched</h5>
|
238
|
+
|
239
|
+
<p>If no wildcard or case match is found, it will attempt to see if a predicate method by the same name exists, call it, and check the result:</p>
|
240
|
+
|
241
|
+
<pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_dirty_values'>dirty_values</span> <span class='op'>=</span> <span class='lbracket'>[</span><span class='kw'>nil</span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='kw'>true</span><span class='rbracket'>]</span>
|
242
|
+
|
243
|
+
<span class='comment'># Standalone
|
244
|
+
</span>
|
245
|
+
<span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='symbol'>:nil?</span><span class='rbracket'>]</span> <span class='op'>===</span> <span class='lbracket'>[</span><span class='kw'>nil</span><span class='rbracket'>]</span>
|
246
|
+
<span class='comment'># => true, though you could also just use Qo[nil]
|
247
|
+
</span>
|
248
|
+
<span class='comment'># Case statement
|
249
|
+
</span>
|
250
|
+
<span class='kw'>case</span> <span class='lbracket'>[</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Roberta</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='kw'>nil</span><span class='rbracket'>]</span>
|
251
|
+
<span class='kw'>when</span> <span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='symbol'>:*</span><span class='comma'>,</span> <span class='symbol'>:nil?</span><span class='rbracket'>]</span> <span class='kw'>then</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>no age</span><span class='tstring_end'>'</span></span>
|
252
|
+
<span class='kw'>else</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>not sure</span><span class='tstring_end'>'</span></span>
|
253
|
+
<span class='kw'>end</span>
|
254
|
+
<span class='comment'># => 'no age'
|
255
|
+
</span>
|
256
|
+
<span class='comment'># Select
|
257
|
+
</span>
|
258
|
+
<span class='id identifier rubyid_people_arrays'>people_arrays</span><span class='period'>.</span><span class='id identifier rubyid_select'>select</span><span class='lparen'>(</span><span class='op'>&</span><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='symbol'>:*</span><span class='comma'>,</span> <span class='symbol'>:even?</span><span class='rbracket'>]</span><span class='rparen'>)</span>
|
259
|
+
<span class='comment'># => [["Robert", 22], ["Roberta", 22], ["Foo", 42], ["Bar", 18]]
|
260
|
+
</span></code></pre>
|
261
|
+
|
262
|
+
<h4>2.2 - Array matched against an Object</h4>
|
263
|
+
|
264
|
+
<p>When an Array matcher is matched against anything other than an Array it will follow the priority:</p>
|
265
|
+
|
266
|
+
<ol>
|
267
|
+
<li>Was a wildcard provided?</li>
|
268
|
+
<li>Does it case match (<code>===</code>)?</li>
|
269
|
+
<li>Does it have a predicate method by that name that matches?</li>
|
270
|
+
</ol>
|
271
|
+
|
272
|
+
<p>Every argument provided will be run against the target object.</p>
|
273
|
+
|
274
|
+
<h5>2.2.1 - Wildcard provided</h5>
|
275
|
+
|
276
|
+
<p>A wildcard in an Array to Object match is functionally an always true, but can be used as such:</p>
|
277
|
+
|
278
|
+
<pre class="code ruby"><code class="ruby"><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='symbol'>:*</span><span class='rbracket'>]</span> <span class='op'>===</span> <span class='symbol'>:literally_anything_here</span>
|
279
|
+
</code></pre>
|
280
|
+
|
281
|
+
<h5>2.2.2 - Case Match present</h5>
|
282
|
+
|
283
|
+
<pre class="code ruby"><code class="ruby"><span class='comment'># Standalone
|
284
|
+
</span>
|
285
|
+
<span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='const'>Integer</span><span class='comma'>,</span> <span class='int'>15</span><span class='op'>..</span><span class='int'>25</span><span class='rbracket'>]</span> <span class='op'>===</span> <span class='int'>20</span>
|
286
|
+
<span class='comment'># => true
|
287
|
+
</span>
|
288
|
+
<span class='comment'># Case statement - functionally indistinguishable from a regular case statement
|
289
|
+
</span>
|
290
|
+
<span class='comment'># Select
|
291
|
+
</span>
|
292
|
+
<span class='lbracket'>[</span><span class='kw'>nil</span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='int'>10</span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>string</span><span class='tstring_end'>'</span></span><span class='rbracket'>]</span><span class='period'>.</span><span class='id identifier rubyid_select'>select</span><span class='lparen'>(</span><span class='op'>&</span><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_or'><span class='object_link'><a href="Qo/PublicApi.html#or-instance_method" title="Qo::PublicApi#or (method)">or</a></span></span><span class='lparen'>(</span><span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>str</span><span class='regexp_end'>/</span></span><span class='comma'>,</span> <span class='int'>10</span><span class='op'>..</span><span class='int'>20</span><span class='rparen'>)</span><span class='rparen'>)</span>
|
293
|
+
<span class='comment'># => [10, "string"]
|
294
|
+
</span></code></pre>
|
295
|
+
|
296
|
+
<h5>2.2.3 - Predicate Method matched</h5>
|
297
|
+
|
298
|
+
<p>Now this is where some of the fun starts in</p>
|
299
|
+
|
300
|
+
<pre class="code ruby"><code class="ruby"><span class='comment'># Standalone
|
301
|
+
</span>
|
302
|
+
<span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_or'><span class='object_link'><a href="Qo/PublicApi.html#or-instance_method" title="Qo::PublicApi#or (method)">or</a></span></span><span class='lparen'>(</span><span class='symbol'>:nil?</span><span class='comma'>,</span> <span class='symbol'>:empty?</span><span class='rparen'>)</span> <span class='op'>===</span> <span class='kw'>nil</span>
|
303
|
+
<span class='comment'># => true
|
304
|
+
</span><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_not'><span class='object_link'><a href="Qo/PublicApi.html#not-instance_method" title="Qo::PublicApi#not (method)">not</a></span></span><span class='lparen'>(</span><span class='symbol'>:nil?</span><span class='comma'>,</span> <span class='symbol'>:empty?</span><span class='rparen'>)</span> <span class='op'>===</span> <span class='kw'>nil</span>
|
305
|
+
<span class='comment'># => false
|
306
|
+
</span>
|
307
|
+
<span class='comment'># Case statement
|
308
|
+
</span>
|
309
|
+
<span class='kw'>case</span> <span class='int'>42</span>
|
310
|
+
<span class='kw'>when</span> <span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='const'>Integer</span><span class='comma'>,</span> <span class='symbol'>:even?</span><span class='comma'>,</span> <span class='int'>40</span><span class='op'>..</span><span class='int'>50</span><span class='rbracket'>]</span> <span class='kw'>then</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>oddly specific number criteria</span><span class='tstring_end'>'</span></span>
|
311
|
+
<span class='kw'>else</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>nope</span><span class='tstring_end'>'</span></span>
|
312
|
+
<span class='kw'>end</span>
|
313
|
+
<span class='comment'># => "oddly specific number criteria"
|
314
|
+
</span>
|
315
|
+
<span class='comment'># Reject
|
316
|
+
</span>
|
317
|
+
<span class='lbracket'>[</span><span class='kw'>nil</span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='int'>10</span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>string</span><span class='tstring_end'>'</span></span><span class='rbracket'>]</span><span class='period'>.</span><span class='id identifier rubyid_reject'>reject</span><span class='lparen'>(</span><span class='op'>&</span><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_or'><span class='object_link'><a href="Qo/PublicApi.html#or-instance_method" title="Qo::PublicApi#or (method)">or</a></span></span><span class='lparen'>(</span><span class='symbol'>:nil?</span><span class='comma'>,</span> <span class='symbol'>:empty?</span><span class='rparen'>)</span><span class='rparen'>)</span>
|
318
|
+
<span class='comment'># => [10, "string"]
|
319
|
+
</span></code></pre>
|
320
|
+
|
321
|
+
<h3>3 - Hash Matching</h3>
|
322
|
+
|
323
|
+
<h4>3.1 - Hash matched against a Hash</h4>
|
324
|
+
|
325
|
+
<ol>
|
326
|
+
<li>Does the key exist on the other hash?</li>
|
327
|
+
<li>Are the match value and match target hashes?</li>
|
328
|
+
<li>Was a wildcard value provided?</li>
|
329
|
+
<li>Does the target object's value case match against the match value?</li>
|
330
|
+
<li>Does the target object's value predicate match against the match value?</li>
|
331
|
+
<li>What about the String version of the match key? Abort if it can't coerce.</li>
|
332
|
+
</ol>
|
333
|
+
|
334
|
+
<h5>3.1.1 - Key present</h5>
|
335
|
+
|
336
|
+
<p>Checks to see if the key is even present on the other object, false if not.</p>
|
337
|
+
|
338
|
+
<h5>3.1.2 - Match value and target are hashes</h5>
|
339
|
+
|
340
|
+
<p>If both the match value (<code>match_key: matcher</code>) and the match target are hashes, Qo will begin a recursive descent starting at the match key until it finds a matcher to try out:</p>
|
341
|
+
|
342
|
+
<pre class="code ruby"><code class="ruby"><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='label'>a:</span> <span class='lbrace'>{</span><span class='label'>b:</span> <span class='lbrace'>{</span><span class='label'>c:</span> <span class='int'>5</span><span class='op'>..</span><span class='int'>15</span><span class='rbrace'>}</span><span class='rbrace'>}</span><span class='rbracket'>]</span> <span class='op'>===</span> <span class='lbrace'>{</span><span class='label'>a:</span> <span class='lbrace'>{</span><span class='label'>b:</span> <span class='lbrace'>{</span><span class='label'>c:</span> <span class='int'>10</span><span class='rbrace'>}</span><span class='rbrace'>}</span><span class='rbrace'>}</span>
|
343
|
+
<span class='comment'># => true
|
344
|
+
</span>
|
345
|
+
<span class='comment'># Na, no fun. Deeper!
|
346
|
+
</span><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_and'><span class='object_link'><a href="Qo/PublicApi.html#and-instance_method" title="Qo::PublicApi#and (method)">and</a></span></span><span class='lparen'>(</span><span class='label'>a:</span> <span class='lbrace'>{</span>
|
347
|
+
<span class='label'>f:</span> <span class='int'>5</span><span class='op'>..</span><span class='int'>15</span><span class='comma'>,</span>
|
348
|
+
<span class='label'>b:</span> <span class='lbrace'>{</span>
|
349
|
+
<span class='label'>c:</span> <span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>foo</span><span class='regexp_end'>/</span></span><span class='comma'>,</span>
|
350
|
+
<span class='label'>d:</span> <span class='int'>10</span><span class='op'>..</span><span class='int'>30</span>
|
351
|
+
<span class='rbrace'>}</span>
|
352
|
+
<span class='rbrace'>}</span><span class='rparen'>)</span><span class='period'>.</span><span class='id identifier rubyid_call'>call</span><span class='lparen'>(</span><span class='label'>a:</span> <span class='lbrace'>{</span>
|
353
|
+
<span class='label'>f:</span> <span class='int'>10</span><span class='comma'>,</span>
|
354
|
+
<span class='label'>b:</span> <span class='lbrace'>{</span>
|
355
|
+
<span class='label'>c:</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>foobar</span><span class='tstring_end'>'</span></span><span class='comma'>,</span>
|
356
|
+
<span class='label'>d:</span> <span class='int'>20</span>
|
357
|
+
<span class='rbrace'>}</span>
|
358
|
+
<span class='rbrace'>}</span><span class='rparen'>)</span>
|
359
|
+
<span class='comment'># => true
|
360
|
+
</span>
|
361
|
+
<span class='comment'># It can get chaotic with `or` though. Anything anywhere in there matches and
|
362
|
+
</span><span class='comment'># it'll pass.
|
363
|
+
</span><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_or'><span class='object_link'><a href="Qo/PublicApi.html#or-instance_method" title="Qo::PublicApi#or (method)">or</a></span></span><span class='lparen'>(</span><span class='label'>a:</span> <span class='lbrace'>{</span>
|
364
|
+
<span class='label'>f:</span> <span class='kw'>false</span><span class='comma'>,</span>
|
365
|
+
<span class='label'>b:</span> <span class='lbrace'>{</span>
|
366
|
+
<span class='label'>c:</span> <span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>nope</span><span class='regexp_end'>/</span></span><span class='comma'>,</span>
|
367
|
+
<span class='label'>d:</span> <span class='int'>10</span><span class='op'>..</span><span class='int'>30</span>
|
368
|
+
<span class='rbrace'>}</span>
|
369
|
+
<span class='rbrace'>}</span><span class='rparen'>)</span><span class='period'>.</span><span class='id identifier rubyid_call'>call</span><span class='lparen'>(</span><span class='label'>a:</span> <span class='lbrace'>{</span>
|
370
|
+
<span class='label'>f:</span> <span class='int'>10</span><span class='comma'>,</span>
|
371
|
+
<span class='label'>b:</span> <span class='lbrace'>{</span>
|
372
|
+
<span class='label'>c:</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>foobar</span><span class='tstring_end'>'</span></span><span class='comma'>,</span>
|
373
|
+
<span class='label'>d:</span> <span class='int'>20</span>
|
374
|
+
<span class='rbrace'>}</span>
|
375
|
+
<span class='rbrace'>}</span><span class='rparen'>)</span>
|
376
|
+
</code></pre>
|
377
|
+
|
378
|
+
<h5>3.1.3 - Wildcard provided</h5>
|
379
|
+
|
380
|
+
<p>As with other wildcards, if the value matched against is a wildcard it'll always get through:</p>
|
381
|
+
|
382
|
+
<pre class="code ruby"><code class="ruby"><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='label'>name:</span> <span class='symbol'>:*</span><span class='rbracket'>]</span> <span class='op'>===</span> <span class='lbrace'>{</span><span class='label'>name:</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Foo</span><span class='tstring_end'>'</span></span><span class='rbrace'>}</span>
|
383
|
+
<span class='comment'># => true
|
384
|
+
</span></code></pre>
|
385
|
+
|
386
|
+
<h5>3.1.4 - Case match present</h5>
|
387
|
+
|
388
|
+
<p>If a case match is present for the key, it'll try and compare:</p>
|
389
|
+
|
390
|
+
<pre class="code ruby"><code class="ruby"><span class='comment'># Standalone
|
391
|
+
</span>
|
392
|
+
<span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='label'>name:</span> <span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>Foo</span><span class='regexp_end'>/</span></span><span class='rbracket'>]</span> <span class='op'>===</span> <span class='lbrace'>{</span><span class='label'>name:</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Foo</span><span class='tstring_end'>'</span></span><span class='rbrace'>}</span>
|
393
|
+
<span class='comment'># => true
|
394
|
+
</span>
|
395
|
+
<span class='comment'># Case statement
|
396
|
+
</span>
|
397
|
+
<span class='kw'>case</span> <span class='lbrace'>{</span><span class='label'>name:</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Foo</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='label'>age:</span> <span class='int'>42</span><span class='rbrace'>}</span>
|
398
|
+
<span class='kw'>when</span> <span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='label'>age:</span> <span class='int'>40</span><span class='op'>..</span><span class='int'>50</span><span class='rbracket'>]</span> <span class='kw'>then</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Gotcha!</span><span class='tstring_end'>'</span></span>
|
399
|
+
<span class='kw'>else</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>nope</span><span class='tstring_end'>'</span></span>
|
400
|
+
<span class='kw'>end</span>
|
401
|
+
<span class='comment'># => "Gotcha!"
|
402
|
+
</span>
|
403
|
+
<span class='comment'># Select
|
404
|
+
</span>
|
405
|
+
<span class='id identifier rubyid_people_hashes'>people_hashes</span> <span class='op'>=</span> <span class='id identifier rubyid_people_arrays'>people_arrays</span><span class='period'>.</span><span class='id identifier rubyid_map'>map</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_n'>n</span><span class='comma'>,</span> <span class='id identifier rubyid_a'>a</span><span class='op'>|</span> <span class='lbrace'>{</span><span class='label'>name:</span> <span class='id identifier rubyid_n'>n</span><span class='comma'>,</span> <span class='label'>age:</span> <span class='id identifier rubyid_a'>a</span><span class='rbrace'>}</span> <span class='rbrace'>}</span>
|
406
|
+
<span class='id identifier rubyid_people_hashes'>people_hashes</span><span class='period'>.</span><span class='id identifier rubyid_select'>select</span><span class='lparen'>(</span><span class='op'>&</span><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='label'>age:</span> <span class='int'>15</span><span class='op'>..</span><span class='int'>25</span><span class='rbracket'>]</span><span class='rparen'>)</span>
|
407
|
+
<span class='comment'># => [{:name=>"Robert", :age=>22}, {:name=>"Roberta", :age=>22}, {:name=>"Bar", :age=>18}]
|
408
|
+
</span></code></pre>
|
409
|
+
|
410
|
+
<h5>3.1.5 - Predicate match present</h5>
|
411
|
+
|
412
|
+
<p>Much like our array friend above, if a predicate style method is present see if it'll work</p>
|
413
|
+
|
414
|
+
<pre class="code ruby"><code class="ruby"><span class='comment'># Standalone
|
415
|
+
</span>
|
416
|
+
<span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='label'>name:</span> <span class='symbol'>:empty?</span><span class='rbracket'>]</span> <span class='op'>===</span> <span class='lbrace'>{</span><span class='label'>name:</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_end'>'</span></span><span class='rbrace'>}</span>
|
417
|
+
<span class='comment'># => true
|
418
|
+
</span>
|
419
|
+
<span class='comment'># Case statement
|
420
|
+
</span>
|
421
|
+
<span class='kw'>case</span> <span class='lbrace'>{</span><span class='label'>name:</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Foo</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='label'>age:</span> <span class='kw'>nil</span><span class='rbrace'>}</span>
|
422
|
+
<span class='kw'>when</span> <span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='label'>age:</span> <span class='symbol'>:nil?</span><span class='rbracket'>]</span> <span class='kw'>then</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>No age provided!</span><span class='tstring_end'>'</span></span>
|
423
|
+
<span class='kw'>else</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>nope</span><span class='tstring_end'>'</span></span>
|
424
|
+
<span class='kw'>end</span>
|
425
|
+
<span class='comment'># => "No age provided!"
|
426
|
+
</span>
|
427
|
+
<span class='comment'># Reject
|
428
|
+
</span>
|
429
|
+
<span class='id identifier rubyid_people_hashes'>people_hashes</span> <span class='op'>=</span> <span class='id identifier rubyid_people_arrays'>people_arrays</span><span class='period'>.</span><span class='id identifier rubyid_map'>map</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='lparen'>(</span><span class='id identifier rubyid_n'>n</span><span class='comma'>,</span><span class='id identifier rubyid_a'>a</span><span class='rparen'>)</span><span class='op'>|</span> <span class='lbrace'>{</span><span class='label'>name:</span> <span class='id identifier rubyid_n'>n</span><span class='comma'>,</span> <span class='label'>age:</span> <span class='id identifier rubyid_a'>a</span><span class='rbrace'>}</span> <span class='rbrace'>}</span> <span class='op'><<</span> <span class='lbrace'>{</span><span class='label'>name:</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Ghost</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='label'>age:</span> <span class='kw'>nil</span><span class='rbrace'>}</span>
|
430
|
+
<span class='id identifier rubyid_people_hashes'>people_hashes</span><span class='period'>.</span><span class='id identifier rubyid_reject'>reject</span><span class='lparen'>(</span><span class='op'>&</span><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='label'>age:</span> <span class='symbol'>:nil?</span><span class='rbracket'>]</span><span class='rparen'>)</span>
|
431
|
+
<span class='comment'># => [{:name=>"Robert", :age=>22}, {:name=>"Roberta", :age=>22}, {:name=>"Bar", :age=>18}]
|
432
|
+
</span></code></pre>
|
433
|
+
|
434
|
+
<p>Careful though, if the key doesn't exist that won't match. I'll have to consider this one later.</p>
|
435
|
+
|
436
|
+
<h5>3.1.6 - String variant present</h5>
|
437
|
+
|
438
|
+
<p>Coerces the key into a string if possible, and sees if that can provide a valid case match</p>
|
439
|
+
|
440
|
+
<h4>3.2 - Hash matched against an Object</h4>
|
441
|
+
|
442
|
+
<ol>
|
443
|
+
<li>Does the object respond to the match key?</li>
|
444
|
+
<li>Was a wildcard value provided?</li>
|
445
|
+
<li>Does the result of sending the match key as a method case match the provided value?</li>
|
446
|
+
<li>Does a predicate method exist for it?</li>
|
447
|
+
</ol>
|
448
|
+
|
449
|
+
<h5>3.2.1 - Responds to match key</h5>
|
450
|
+
|
451
|
+
<p>If it doesn't know how to deal with it, false out.</p>
|
452
|
+
|
453
|
+
<h5>3.2.2 - Wildcard provided</h5>
|
454
|
+
|
455
|
+
<p>Same as other wildcards, but if the object doesn't respond to the method you specify it'll have false'd out before it reaches here.</p>
|
456
|
+
|
457
|
+
<h5>3.2.3 - Case match present</h5>
|
458
|
+
|
459
|
+
<p>This is where we can get into some interesting code, much like the hash selections above</p>
|
460
|
+
|
461
|
+
<pre class="code ruby"><code class="ruby"><span class='comment'># Standalone
|
462
|
+
</span>
|
463
|
+
<span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='label'>name:</span> <span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>Rob</span><span class='regexp_end'>/</span></span><span class='rbracket'>]</span> <span class='op'>===</span> <span class='id identifier rubyid_people_objects'>people_objects</span><span class='period'>.</span><span class='id identifier rubyid_first'>first</span>
|
464
|
+
<span class='comment'># => true
|
465
|
+
</span>
|
466
|
+
<span class='comment'># Case statement
|
467
|
+
</span>
|
468
|
+
<span class='kw'>case</span> <span class='id identifier rubyid_people_objects'>people_objects</span><span class='period'>.</span><span class='id identifier rubyid_first'>first</span>
|
469
|
+
<span class='kw'>when</span> <span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='label'>name:</span> <span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>Rob</span><span class='regexp_end'>/</span></span><span class='rbracket'>]</span> <span class='kw'>then</span> <span class='tstring'><span class='tstring_beg'>"</span><span class='tstring_content'>It's Rob!</span><span class='tstring_end'>"</span></span>
|
470
|
+
<span class='kw'>else</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Na, not them</span><span class='tstring_end'>'</span></span>
|
471
|
+
<span class='kw'>end</span>
|
472
|
+
<span class='comment'># => "It's Rob!"
|
473
|
+
</span>
|
474
|
+
<span class='comment'># Select
|
475
|
+
</span>
|
476
|
+
<span class='id identifier rubyid_people_objects'>people_objects</span><span class='period'>.</span><span class='id identifier rubyid_select'>select</span><span class='lparen'>(</span><span class='op'>&</span><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='label'>name:</span> <span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>Rob</span><span class='regexp_end'>/</span></span><span class='rbracket'>]</span><span class='rparen'>)</span>
|
477
|
+
<span class='comment'># => [Person(Robert, 22), Person(Roberta, 22)]
|
478
|
+
</span></code></pre>
|
479
|
+
|
480
|
+
<h5>3.2.4 - Predicate match present</h5>
|
481
|
+
|
482
|
+
<pre class="code ruby"><code class="ruby"><span class='comment'># Standalone
|
483
|
+
</span>
|
484
|
+
<span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='label'>name:</span> <span class='symbol'>:empty?</span><span class='rbracket'>]</span> <span class='op'>===</span> <span class='const'>Person</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='int'>22</span><span class='rparen'>)</span>
|
485
|
+
<span class='comment'># => true
|
486
|
+
</span>
|
487
|
+
<span class='comment'># Case statement
|
488
|
+
</span>
|
489
|
+
<span class='kw'>case</span> <span class='const'>Person</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='kw'>nil</span><span class='rparen'>)</span>
|
490
|
+
<span class='kw'>when</span> <span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='label'>age:</span> <span class='symbol'>:nil?</span><span class='rbracket'>]</span> <span class='kw'>then</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>No age provided!</span><span class='tstring_end'>'</span></span>
|
491
|
+
<span class='kw'>else</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>nope</span><span class='tstring_end'>'</span></span>
|
492
|
+
<span class='kw'>end</span>
|
493
|
+
<span class='comment'># => "No age provided!"
|
494
|
+
</span>
|
495
|
+
<span class='comment'># Select
|
496
|
+
</span>
|
497
|
+
<span class='id identifier rubyid_people_hashes'>people_hashes</span><span class='period'>.</span><span class='id identifier rubyid_select'>select</span><span class='lparen'>(</span><span class='op'>&</span><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='label'>age:</span> <span class='symbol'>:nil?</span><span class='rbracket'>]</span><span class='rparen'>)</span>
|
498
|
+
<span class='comment'># => []
|
499
|
+
</span></code></pre>
|
500
|
+
|
501
|
+
<h3>4 - Right Hand Pattern Matching</h3>
|
502
|
+
|
503
|
+
<p>This is where I start going a bit off into the weeds. We're going to try and get RHA style pattern matching in Ruby.</p>
|
504
|
+
|
505
|
+
<pre class="code ruby"><code class="ruby"><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_match'><span class='object_link'><a href="Qo/PublicApi.html#match-instance_method" title="Qo::PublicApi#match (method)">match</a></span></span><span class='lparen'>(</span><span class='lbracket'>[</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Robert</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='int'>22</span><span class='rbracket'>]</span><span class='comma'>,</span>
|
506
|
+
<span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_m'>m</span><span class='lparen'>(</span><span class='symbol'>:*</span><span class='comma'>,</span> <span class='int'>20</span><span class='op'>..</span><span class='int'>99</span><span class='rparen'>)</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_n'>n</span><span class='comma'>,</span> <span class='id identifier rubyid_a'>a</span><span class='op'>|</span> <span class='tstring'><span class='tstring_beg'>"</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_n'>n</span><span class='embexpr_end'>}</span><span class='tstring_content'> is an adult that is </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_a'>a</span><span class='embexpr_end'>}</span><span class='tstring_content'> years old</span><span class='tstring_end'>"</span></span> <span class='rbrace'>}</span><span class='comma'>,</span>
|
507
|
+
<span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_m'>m</span><span class='lparen'>(</span><span class='symbol'>:*</span><span class='rparen'>)</span>
|
508
|
+
<span class='rparen'>)</span>
|
509
|
+
<span class='comment'># => "Robert is an adult that is 22 years old"
|
510
|
+
</span></code></pre>
|
511
|
+
|
512
|
+
<pre class="code ruby"><code class="ruby"><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_match'><span class='object_link'><a href="Qo/PublicApi.html#match-instance_method" title="Qo::PublicApi#match (method)">match</a></span></span><span class='lparen'>(</span><span class='id identifier rubyid_people_objects'>people_objects</span><span class='period'>.</span><span class='id identifier rubyid_first'>first</span><span class='comma'>,</span>
|
513
|
+
<span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_m'>m</span><span class='lparen'>(</span><span class='label'>name:</span> <span class='symbol'>:*</span><span class='comma'>,</span> <span class='label'>age:</span> <span class='int'>20</span><span class='op'>..</span><span class='int'>99</span><span class='rparen'>)</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_person'>person</span><span class='op'>|</span> <span class='tstring'><span class='tstring_beg'>"</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_person'>person</span><span class='period'>.</span><span class='id identifier rubyid_name'>name</span><span class='embexpr_end'>}</span><span class='tstring_content'> is an adult that is </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_person'>person</span><span class='period'>.</span><span class='id identifier rubyid_age'>age</span><span class='embexpr_end'>}</span><span class='tstring_content'> years old</span><span class='tstring_end'>"</span></span> <span class='rbrace'>}</span><span class='comma'>,</span>
|
514
|
+
<span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_m'>m</span><span class='lparen'>(</span><span class='symbol'>:*</span><span class='rparen'>)</span>
|
515
|
+
<span class='rparen'>)</span>
|
516
|
+
</code></pre>
|
517
|
+
|
518
|
+
<p>In this case it's trying to do a few things:</p>
|
519
|
+
|
520
|
+
<ol>
|
521
|
+
<li>Iterate over every matcher until it finds a match</li>
|
522
|
+
<li>Execute its block function</li>
|
523
|
+
</ol>
|
524
|
+
|
525
|
+
<p>If no block function is provided, it assumes an identity function (<code>-> v { v }</code>) instead. If no match is found, <code>nil</code> will be returned.</p>
|
526
|
+
|
527
|
+
<p>If an initial target is not furnished, the matcher will become a curried proc awaiting a target. In more simple terms it just wants a target to run against, so let's give it a few with map:</p>
|
528
|
+
|
529
|
+
<pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_name_longer_than_three'>name_longer_than_three</span> <span class='op'>=</span> <span class='tlambda'>-></span> <span class='id identifier rubyid_person'>person</span> <span class='tlambeg'>{</span> <span class='id identifier rubyid_person'>person</span><span class='period'>.</span><span class='id identifier rubyid_name'>name</span><span class='period'>.</span><span class='id identifier rubyid_size'>size</span> <span class='op'>></span> <span class='int'>3</span> <span class='rbrace'>}</span>
|
530
|
+
|
531
|
+
<span class='id identifier rubyid_people_objects'>people_objects</span><span class='period'>.</span><span class='id identifier rubyid_map'>map</span><span class='lparen'>(</span><span class='op'>&</span><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_match'><span class='object_link'><a href="Qo/PublicApi.html#match-instance_method" title="Qo::PublicApi#match (method)">match</a></span></span><span class='lparen'>(</span>
|
532
|
+
<span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_m'>m</span><span class='lparen'>(</span><span class='id identifier rubyid_name_longer_than_three'>name_longer_than_three</span><span class='rparen'>)</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_person'>person</span><span class='op'>|</span>
|
533
|
+
<span class='id identifier rubyid_person'>person</span><span class='period'>.</span><span class='id identifier rubyid_name'>name</span> <span class='op'>=</span> <span class='id identifier rubyid_person'>person</span><span class='period'>.</span><span class='id identifier rubyid_name'>name</span><span class='lbracket'>[</span><span class='int'>0</span><span class='op'>..</span><span class='int'>2</span><span class='rbracket'>]</span>
|
534
|
+
<span class='id identifier rubyid_person'>person</span>
|
535
|
+
<span class='rbrace'>}</span><span class='comma'>,</span>
|
536
|
+
<span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_m'>m</span><span class='lparen'>(</span><span class='symbol'>:*</span><span class='rparen'>)</span>
|
537
|
+
<span class='rparen'>)</span><span class='rparen'>)</span>
|
538
|
+
|
539
|
+
<span class='comment'># => [Person(age: 22, name: "Rob"), Person(age: 22, name: "Rob"), Person(age: 42, name: "Foo"), Person(age: 17, name: "Bar")]
|
540
|
+
</span></code></pre>
|
541
|
+
|
542
|
+
<p>So we just truncated everyone's name that was longer than three characters.</p>
|
543
|
+
|
544
|
+
<h3>6 - Helper functions</h3>
|
545
|
+
|
546
|
+
<p>There are a few functions added for convenience, and it should be noted that because all Qo matchers respond to <code>===</code> that they can be used as helpers as well.</p>
|
547
|
+
|
548
|
+
<h4>6.1 - Dig</h4>
|
549
|
+
|
550
|
+
<p>Dig is used to get in deep at a nested hash value. It takes a dot-path and a <code>===</code> respondent matcher:</p>
|
551
|
+
|
552
|
+
<pre class="code ruby"><code class="ruby"><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_dig'><span class='object_link'><a href="Qo/Helpers.html#dig-instance_method" title="Qo::Helpers#dig (method)">dig</a></span></span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>a.b.c</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_or'><span class='object_link'><a href="Qo/PublicApi.html#or-instance_method" title="Qo::PublicApi#or (method)">or</a></span></span><span class='lparen'>(</span><span class='int'>1</span><span class='op'>..</span><span class='int'>5</span><span class='comma'>,</span> <span class='int'>15</span><span class='op'>..</span><span class='int'>25</span><span class='rparen'>)</span><span class='rparen'>)</span> <span class='op'>===</span> <span class='lbrace'>{</span><span class='label'>a:</span> <span class='lbrace'>{</span><span class='label'>b:</span> <span class='lbrace'>{</span><span class='label'>c:</span> <span class='int'>1</span><span class='rbrace'>}</span><span class='rbrace'>}</span><span class='rbrace'>}</span>
|
553
|
+
<span class='comment'># => true
|
554
|
+
</span>
|
555
|
+
<span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_dig'><span class='object_link'><a href="Qo/Helpers.html#dig-instance_method" title="Qo::Helpers#dig (method)">dig</a></span></span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>a.b.c</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_or'><span class='object_link'><a href="Qo/PublicApi.html#or-instance_method" title="Qo::PublicApi#or (method)">or</a></span></span><span class='lparen'>(</span><span class='int'>1</span><span class='op'>..</span><span class='int'>5</span><span class='comma'>,</span> <span class='int'>15</span><span class='op'>..</span><span class='int'>25</span><span class='rparen'>)</span><span class='rparen'>)</span> <span class='op'>===</span> <span class='lbrace'>{</span><span class='label'>a:</span> <span class='lbrace'>{</span><span class='label'>b:</span> <span class='lbrace'>{</span><span class='label'>c:</span> <span class='int'>20</span><span class='rbrace'>}</span><span class='rbrace'>}</span><span class='rbrace'>}</span>
|
556
|
+
<span class='comment'># => true
|
557
|
+
</span></code></pre>
|
558
|
+
|
559
|
+
<p>To be fair that means anything that can respond to <code>===</code>, including classes and other such things.</p>
|
560
|
+
|
561
|
+
<h4>6.2 - Count By</h4>
|
562
|
+
|
563
|
+
<p>This ends up coming up a lot, especially around querying, so let's get a way to count by!</p>
|
564
|
+
|
565
|
+
<pre class="code ruby"><code class="ruby"><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_count_by'><span class='object_link'><a href="Qo/Helpers.html#count_by-instance_method" title="Qo::Helpers#count_by (method)">count_by</a></span></span><span class='lparen'>(</span><span class='lbracket'>[</span><span class='int'>1</span><span class='comma'>,</span><span class='int'>2</span><span class='comma'>,</span><span class='int'>3</span><span class='comma'>,</span><span class='int'>2</span><span class='comma'>,</span><span class='int'>2</span><span class='comma'>,</span><span class='int'>2</span><span class='comma'>,</span><span class='int'>1</span><span class='rbracket'>]</span><span class='rparen'>)</span>
|
566
|
+
|
567
|
+
<span class='comment'># => {
|
568
|
+
</span><span class='comment'># 1 => 2,
|
569
|
+
</span><span class='comment'># 2 => 4,
|
570
|
+
</span><span class='comment'># 3 => 1
|
571
|
+
</span><span class='comment'># }
|
572
|
+
</span>
|
573
|
+
<span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_count_by'><span class='object_link'><a href="Qo/Helpers.html#count_by-instance_method" title="Qo::Helpers#count_by (method)">count_by</a></span></span><span class='lparen'>(</span><span class='lbracket'>[</span><span class='int'>1</span><span class='comma'>,</span><span class='int'>2</span><span class='comma'>,</span><span class='int'>3</span><span class='comma'>,</span><span class='int'>2</span><span class='comma'>,</span><span class='int'>2</span><span class='comma'>,</span><span class='int'>2</span><span class='comma'>,</span><span class='int'>1</span><span class='rbracket'>]</span><span class='comma'>,</span> <span class='op'>&</span><span class='symbol'>:even?</span><span class='rparen'>)</span>
|
574
|
+
|
575
|
+
<span class='comment'># => {
|
576
|
+
</span><span class='comment'># false => 3,
|
577
|
+
</span><span class='comment'># true => 4
|
578
|
+
</span><span class='comment'># }
|
579
|
+
</span></code></pre>
|
580
|
+
|
581
|
+
<h3>5 - Hacky Fun Time</h3>
|
582
|
+
|
583
|
+
<p>These examples will grow over the next few weeks as I think of more fun things to do with Qo. PRs welcome if you find fun uses!</p>
|
584
|
+
|
585
|
+
<h4>5.1 - JSON</h4>
|
586
|
+
|
587
|
+
<blockquote>
|
588
|
+
<p>Note that Qo does not support deep querying of hashes (yet)</p>
|
589
|
+
</blockquote>
|
590
|
+
|
591
|
+
<h5>5.1.1 - JSON Placeholder</h5>
|
592
|
+
|
593
|
+
<p>Qo tries to be clever though, it assumes Symbol keys first and then String keys, so how about some JSON?:</p>
|
594
|
+
|
595
|
+
<pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_require'>require</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>json</span><span class='tstring_end'>'</span></span>
|
596
|
+
<span class='id identifier rubyid_require'>require</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>net/http</span><span class='tstring_end'>'</span></span>
|
597
|
+
|
598
|
+
<span class='id identifier rubyid_posts'>posts</span> <span class='op'>=</span> <span class='const'>JSON</span><span class='period'>.</span><span class='id identifier rubyid_parse'>parse</span><span class='lparen'>(</span>
|
599
|
+
<span class='const'>Net</span><span class='op'>::</span><span class='const'>HTTP</span><span class='period'>.</span><span class='id identifier rubyid_get'>get</span><span class='lparen'>(</span><span class='const'>URI</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>"</span><span class='tstring_content'>https://jsonplaceholder.typicode.com/posts</span><span class='tstring_end'>"</span></span><span class='rparen'>)</span><span class='rparen'>)</span><span class='comma'>,</span> <span class='label'>symbolize_names:</span> <span class='kw'>true</span>
|
600
|
+
<span class='rparen'>)</span>
|
601
|
+
|
602
|
+
<span class='id identifier rubyid_users'>users</span> <span class='op'>=</span> <span class='const'>JSON</span><span class='period'>.</span><span class='id identifier rubyid_parse'>parse</span><span class='lparen'>(</span>
|
603
|
+
<span class='const'>Net</span><span class='op'>::</span><span class='const'>HTTP</span><span class='period'>.</span><span class='id identifier rubyid_get'>get</span><span class='lparen'>(</span><span class='const'>URI</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>"</span><span class='tstring_content'>https://jsonplaceholder.typicode.com/users</span><span class='tstring_end'>"</span></span><span class='rparen'>)</span><span class='rparen'>)</span><span class='comma'>,</span> <span class='label'>symbolize_names:</span> <span class='kw'>true</span>
|
604
|
+
<span class='rparen'>)</span>
|
605
|
+
|
606
|
+
<span class='comment'># Get all posts where the userId is 1.
|
607
|
+
</span><span class='id identifier rubyid_posts'>posts</span><span class='period'>.</span><span class='id identifier rubyid_select'>select</span><span class='lparen'>(</span><span class='op'>&</span><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='lbracket'>[</span><span class='label'>userId:</span> <span class='int'>1</span><span class='rbracket'>]</span><span class='rparen'>)</span>
|
608
|
+
|
609
|
+
<span class='comment'># Get users named Nicholas or have two names and an address somewhere with a zipcode
|
610
|
+
</span><span class='comment'># that starts with 9 or 4.
|
611
|
+
</span><span class='comment'>#
|
612
|
+
</span><span class='comment'># Qo matchers return a `===` respondant object, remember, so we can totally nest them.
|
613
|
+
</span><span class='id identifier rubyid_users'>users</span><span class='period'>.</span><span class='id identifier rubyid_select'>select</span><span class='lparen'>(</span><span class='op'>&</span><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_and'><span class='object_link'><a href="Qo/PublicApi.html#and-instance_method" title="Qo::PublicApi#and (method)">and</a></span></span><span class='lparen'>(</span>
|
614
|
+
<span class='label'>name:</span> <span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_or'><span class='object_link'><a href="Qo/PublicApi.html#or-instance_method" title="Qo::PublicApi#or (method)">or</a></span></span><span class='lparen'>(</span><span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>^Nicholas</span><span class='regexp_end'>/</span></span><span class='comma'>,</span> <span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>^\w+ \w+$</span><span class='regexp_end'>/</span></span><span class='rparen'>)</span><span class='comma'>,</span>
|
615
|
+
<span class='label'>address:</span> <span class='lbrace'>{</span>
|
616
|
+
<span class='label'>zipcode:</span> <span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_or'><span class='object_link'><a href="Qo/PublicApi.html#or-instance_method" title="Qo::PublicApi#or (method)">or</a></span></span><span class='lparen'>(</span><span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>^9</span><span class='regexp_end'>/</span></span><span class='comma'>,</span> <span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>^4</span><span class='regexp_end'>/</span></span><span class='rparen'>)</span>
|
617
|
+
<span class='rbrace'>}</span>
|
618
|
+
<span class='rparen'>)</span><span class='rparen'>)</span>
|
619
|
+
|
620
|
+
<span class='comment'># We could even use dig to get at some of the same information. This and the above will
|
621
|
+
</span><span class='comment'># return the same results even.
|
622
|
+
</span><span class='id identifier rubyid_users'>users</span><span class='period'>.</span><span class='id identifier rubyid_select'>select</span><span class='lparen'>(</span><span class='op'>&</span><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_and'><span class='object_link'><a href="Qo/PublicApi.html#and-instance_method" title="Qo::PublicApi#and (method)">and</a></span></span><span class='lparen'>(</span>
|
623
|
+
<span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_dig'><span class='object_link'><a href="Qo/Helpers.html#dig-instance_method" title="Qo::Helpers#dig (method)">dig</a></span></span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>address.zipcode</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_or'><span class='object_link'><a href="Qo/PublicApi.html#or-instance_method" title="Qo::PublicApi#or (method)">or</a></span></span><span class='lparen'>(</span><span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>^9</span><span class='regexp_end'>/</span></span><span class='comma'>,</span> <span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>^4</span><span class='regexp_end'>/</span></span><span class='rparen'>)</span><span class='rparen'>)</span><span class='comma'>,</span>
|
624
|
+
<span class='label'>name:</span> <span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_or'><span class='object_link'><a href="Qo/PublicApi.html#or-instance_method" title="Qo::PublicApi#or (method)">or</a></span></span><span class='lparen'>(</span><span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>^Nicholas</span><span class='regexp_end'>/</span></span><span class='comma'>,</span> <span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>^\w+ \w+$</span><span class='regexp_end'>/</span></span><span class='rparen'>)</span>
|
625
|
+
<span class='rparen'>)</span><span class='rparen'>)</span>
|
626
|
+
</code></pre>
|
627
|
+
|
628
|
+
<p>Nifty!</p>
|
629
|
+
|
630
|
+
<h4>5.2 - Opsy Stuff</h4>
|
631
|
+
|
632
|
+
<h5>5.2.1 - NMap</h5>
|
633
|
+
|
634
|
+
<p>What about NMap for our Opsy friends? Well, simulated, but still fun.</p>
|
635
|
+
|
636
|
+
<pre class="code ruby"><code class="ruby">hosts = (`nmap -oG - -sP 192.168.1.* 10.0.0.* | grep Host`).lines.map { |v| v.split[1..2] }
|
637
|
+
=> [["192.168.1.1", "(Router)"], ["192.168.1.2", "(My Computer)"], ["10.0.0.1", "(Gateway)"]]
|
638
|
+
|
639
|
+
hosts.select(&Qo[IPAddr.new('192.168.1.1/8')])
|
640
|
+
=> [["192.168.1.1", "(Router)"], ["192.168.1.2", "(My Computer)"]]
|
641
|
+
</code></pre>
|
642
|
+
|
643
|
+
<h5>5.2.2 - <code>df</code></h5>
|
644
|
+
|
645
|
+
<p>The nice thing about Unix style commands is that they use headers, which means CSV can get a hold of them for some good formatting. It's also smart enough to deal with space separators that may vary in length:</p>
|
646
|
+
|
647
|
+
<pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_rows'>rows</span> <span class='op'>=</span> <span class='const'>CSV</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span><span class='lparen'>(</span><span class='backtick'>`</span><span class='tstring_content'>df -h</span><span class='tstring_end'>`</span></span><span class='comma'>,</span> <span class='label'>col_sep:</span> <span class='tstring'><span class='tstring_beg'>"</span><span class='tstring_content'> </span><span class='tstring_end'>"</span></span><span class='comma'>,</span> <span class='label'>headers:</span> <span class='kw'>true</span><span class='rparen'>)</span><span class='period'>.</span><span class='id identifier rubyid_read'>read</span><span class='period'>.</span><span class='id identifier rubyid_map'>map</span><span class='lparen'>(</span><span class='op'>&</span><span class='symbol'>:to_h</span><span class='rparen'>)</span>
|
648
|
+
|
649
|
+
<span class='id identifier rubyid_rows'>rows</span><span class='period'>.</span><span class='id identifier rubyid_map'>map</span><span class='lparen'>(</span><span class='op'>&</span><span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_match'><span class='object_link'><a href="Qo/PublicApi.html#match-instance_method" title="Qo::PublicApi#match (method)">match</a></span></span><span class='lparen'>(</span>
|
650
|
+
<span class='const'><span class='object_link'><a href="Qo.html" title="Qo (module)">Qo</a></span></span><span class='period'>.</span><span class='id identifier rubyid_m'>m</span><span class='lparen'>(</span><span class='label'>Avail:</span> <span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>Gi$</span><span class='regexp_end'>/</span></span><span class='rparen'>)</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_row'>row</span><span class='op'>|</span>
|
651
|
+
<span class='tstring'><span class='tstring_beg'>"</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_row'>row</span><span class='lbracket'>[</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Filesystem</span><span class='tstring_end'>'</span></span><span class='rbracket'>]</span><span class='embexpr_end'>}</span><span class='tstring_content'> mounted on </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_row'>row</span><span class='lbracket'>[</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Mounted</span><span class='tstring_end'>'</span></span><span class='rbracket'>]</span><span class='embexpr_end'>}</span><span class='tstring_content'> [</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_row'>row</span><span class='lbracket'>[</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Avail</span><span class='tstring_end'>'</span></span><span class='rbracket'>]</span><span class='embexpr_end'>}</span><span class='tstring_content'> / </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_row'>row</span><span class='lbracket'>[</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Size</span><span class='tstring_end'>'</span></span><span class='rbracket'>]</span><span class='embexpr_end'>}</span><span class='tstring_content'>]</span><span class='tstring_end'>"</span></span>
|
652
|
+
<span class='rbrace'>}</span>
|
653
|
+
<span class='rparen'>)</span><span class='rparen'>)</span><span class='period'>.</span><span class='id identifier rubyid_compact'>compact</span>
|
654
|
+
<span class='comment'># => ["/dev/***** mounted on / [186Gi / 466Gi]"]
|
655
|
+
</span></code></pre>
|
656
|
+
|
657
|
+
<h2>Installation</h2>
|
658
|
+
|
659
|
+
<p>Add this line to your application's Gemfile:</p>
|
660
|
+
|
661
|
+
<pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_gem'>gem</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>qo</span><span class='tstring_end'>'</span></span>
|
662
|
+
</code></pre>
|
663
|
+
|
664
|
+
<p>And then execute:</p>
|
665
|
+
|
666
|
+
<pre class="code ruby"><code class="ruby">$ bundle
|
667
|
+
</code></pre>
|
668
|
+
|
669
|
+
<p>Or install it yourself as:</p>
|
670
|
+
|
671
|
+
<pre class="code ruby"><code class="ruby">$ gem install qo
|
672
|
+
</code></pre>
|
673
|
+
|
674
|
+
<h2>Development</h2>
|
675
|
+
|
676
|
+
<p>After checking out the repo, run <code>bin/setup</code> to install dependencies. Then, run <code>rake spec</code> to run the tests. You can also run <code>bin/console</code> for an interactive prompt that will allow you to experiment.</p>
|
677
|
+
|
678
|
+
<p>To install this gem onto your local machine, run <code>bundle exec rake install</code>. To release a new version, update the version number in <code>version.rb</code>, and then run <code>bundle exec rake release</code>, which will create a git tag for the version, push git commits and tags, and push the <code>.gem</code> file to <a href="https://rubygems.org">rubygems.org</a>.</p>
|
679
|
+
|
680
|
+
<h2>Contributing</h2>
|
681
|
+
|
682
|
+
<p>Bug reports and pull requests are welcome on GitHub at <a href="https://github.com/baweaver/qo">https://github.com/baweaver/qo</a>. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the <a href="http://contributor-covenant.org">Contributor Covenant</a> code of conduct.</p>
|
683
|
+
|
684
|
+
<h2>License</h2>
|
685
|
+
|
686
|
+
<p>The gem is available as open source under the terms of the <a href="http://opensource.org/licenses/MIT">MIT License</a>.</p>
|
687
|
+
|
688
|
+
<h2>Code of Conduct</h2>
|
689
|
+
|
690
|
+
<p>Everyone interacting in the Qo project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the <a href="https://github.com/baweaver/qo/blob/master/CODE_OF_CONDUCT.md">code of conduct</a>.</p>
|
691
|
+
</div></div>
|
692
|
+
|
693
|
+
<div id="footer">
|
694
|
+
Generated on Sun Apr 15 20:29:44 2018 by
|
695
|
+
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
696
|
+
0.9.12 (ruby-2.4.4).
|
697
|
+
</div>
|
698
|
+
|
699
|
+
</div>
|
700
|
+
</body>
|
701
|
+
</html>
|