-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Qo 1.0.0 #23
Merged
Merged
Qo 1.0.0 #23
Changes from 9 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
0335b9a
Initial restructure for 1.0
baweaver bacdb51
Refine meta-api to use macro-like methods instead, faster and looks n…
baweaver 75c6c4e
Add meta-creation and formalize destructuring
baweaver 4a89f8d
add mixins and shorthand for creation of meta-matchers and branches
baweaver bdd92b5
documentation pass one
baweaver 325feab
more documentation and fix travis
baweaver e4d3c81
should about cover the first major documentation pass
baweaver ddb88b7
Add to the readme
baweaver ad78855
specs added
baweaver 5a9d6d5
fix minor items, change to 0.99.0 pre-move
baweaver ab6f467
deprecate helpers
baweaver ff9cb3d
dry-rb announcement
baweaver File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
sudo: false | ||
language: ruby | ||
rvm: | ||
- 2.3.7 | ||
- 2.4.4 | ||
- 2.5.1 | ||
- 2.5.3 | ||
- 2.6.1 | ||
before_install: gem install bundler -v 1.15.4 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -482,11 +482,11 @@ people_objects.map(&Qo.match { |m| | |
|
||
So we just truncated everyone's name that was longer than three characters. | ||
|
||
### 6 - Helper functions | ||
### 5 - Helper functions | ||
|
||
There are a few functions added for convenience, and it should be noted that because all Qo matchers respond to `===` that they can be used as helpers as well. | ||
|
||
#### 6.1 - Dig | ||
#### 5.1 - Dig | ||
|
||
Dig is used to get in deep at a nested hash value. It takes a dot-path and a `===` respondent matcher: | ||
|
||
|
@@ -500,7 +500,7 @@ Qo.dig('a.b.c', Qo.or(1..5, 15..25)) === {a: {b: {c: 20}}} | |
|
||
To be fair that means anything that can respond to `===`, including classes and other such things. | ||
|
||
#### 6.2 - Count By | ||
#### 5.2 - Count By | ||
|
||
This ends up coming up a lot, especially around querying, so let's get a way to count by! | ||
|
||
|
@@ -523,15 +523,95 @@ Qo.count_by([1,2,3,2,2,2,1], &:even?) | |
|
||
This feature may be added to Ruby 2.6+: https://bugs.ruby-lang.org/issues/11076 | ||
|
||
### 5 - Hacky Fun Time | ||
### 6 - Custom Pattern Matchers | ||
|
||
With the release of Qo 1.0.0 we introduced the idea of custom branches and pattern matchers for more advanced | ||
users of the library. | ||
|
||
Consider a Monadic type like `Some` and `None`: | ||
|
||
```ruby | ||
# Technically Some and None don't exist yet, so we have to "cheat" instead | ||
# of just saying `Some` for the precondition | ||
# | ||
# We start by defining two branches that match against a Some type and a None | ||
# type, extracting the value on match before yielding to their associated | ||
# functions | ||
SomeBranch = Qo.create_branch( | ||
name: 'some', | ||
precondition: -> v { v.is_a?(Some) }, | ||
extractor: :value | ||
) | ||
|
||
NoneBranch = Qo.create_branch( | ||
name: 'none', | ||
precondition: -> v { v.is_a?(None) }, | ||
extractor: :value | ||
) | ||
|
||
# Now we create a new pattern matching class with those branches. Note that | ||
# there's nothing stopping you from making as many branches as you want, | ||
# except that it may get confusing after a while. | ||
SomePatternMatch = Qo.create_pattern_match(branches: [ | ||
SomeBranch, | ||
NoneBranch | ||
]) | ||
|
||
class Some | ||
# There's also a provided mixin that gives an `unfold` method that | ||
# works exactly like a pattern match without having to use it explicitly | ||
include SomePatternMatch.mixin | ||
|
||
attr_reader :value | ||
|
||
def initialize(value) @value = value end | ||
def self.[](value) new(value) end | ||
|
||
def fmap(&fn) | ||
new_value = fn.call(value) | ||
new_value ? Some[new_value] : None[value] | ||
end | ||
end | ||
|
||
class None | ||
include SomePatternMatch.mixin | ||
|
||
attr_reader :value | ||
|
||
def initialize(value) @value = value end | ||
def self.[](value) new(value) end | ||
|
||
def fmap(&fn) None[value] end | ||
end | ||
|
||
# So now we can pattern match with `some` and `none` branches using the `unfold` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace |
||
# method that was mixed into both types. | ||
Some[1] | ||
.fmap { |v| v * 2 } | ||
.unfold { |m| | ||
m.some { |v| v + 100 } | ||
m.none { "OHNO!" } | ||
} | ||
=> 102 | ||
|
||
Some[1] | ||
.fmap { |v| nil } | ||
.unfold { |m| | ||
m.some { |v| v + 100 } | ||
m.none { "OHNO!" } | ||
} | ||
=> "OHNO!" | ||
``` | ||
|
||
### 7 - Hacky Fun Time | ||
|
||
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! | ||
|
||
#### 5.1 - JSON and HTTP | ||
#### 7.1 - JSON and HTTP | ||
|
||
> Note that Qo does not support deep querying of hashes (yet) | ||
|
||
##### 5.1.1 - JSON Placeholder | ||
##### 7.1.1 - JSON Placeholder | ||
|
||
Qo tries to be clever though, it assumes Symbol keys first and then String keys, so how about some JSON?: | ||
|
||
|
@@ -602,9 +682,26 @@ m.when(Net::HTTPSuccess, body: /Qo/) | |
You could put as many checks as you want in there, or use different Qo matchers | ||
nested to get even further in. | ||
|
||
#### 5.2 - Opsy Stuff | ||
Now if we wanted to add more power and create an HTTP matcher: | ||
|
||
```ruby | ||
HTTP_Matcher = Qo.create_pattern_match(branches: [ | ||
Qo.create_branch(name: 'success', precondition: Net::HTTPSuccess), | ||
Qo.create_branch(name: 'error', precondition: Net::HTTPError), | ||
Qo::Braches::ElseBranch | ||
]) | ||
|
||
def get_url(url) | ||
Net::HTTP.get_response(URI(url)).then(&HTTP_Matcher.match { |m| | ||
m.success { |response| response.body.size }, | ||
m.else { |response| raise response.message } | ||
}) | ||
end | ||
``` | ||
|
||
#### 7.2 - Opsy Stuff | ||
|
||
##### 5.2.1 - NMap | ||
##### 7.2.1 - NMap | ||
|
||
What about NMap for our Opsy friends? Well, simulated, but still fun. | ||
|
||
|
@@ -616,7 +713,7 @@ hosts.select(&Qo[IPAddr.new('192.168.1.1/8')]) | |
=> [["192.168.1.1", "(Router)"], ["192.168.1.2", "(My Computer)"]] | ||
``` | ||
|
||
##### 5.2.2 - `df` | ||
##### 7.2.2 - `df` | ||
|
||
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: | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2.4.5 is current I think.