check_please 0.4.0 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +3 -1
- data/Gemfile.lock +1 -1
- data/README.md +301 -29
- data/Rakefile +50 -3
- data/bin/gh-md-toc +350 -0
- data/lib/check_please.rb +77 -25
- data/lib/check_please/cli.rb +1 -1
- data/lib/check_please/cli/parser.rb +1 -1
- data/lib/check_please/comparison.rb +176 -40
- data/lib/check_please/diffs.rb +4 -5
- data/lib/check_please/error.rb +24 -0
- data/lib/check_please/flag.rb +13 -3
- data/lib/check_please/path.rb +148 -13
- data/lib/check_please/path_segment.rb +88 -0
- data/lib/check_please/reification.rb +50 -0
- data/lib/check_please/version.rb +1 -1
- data/usage_examples.rb +24 -2
- metadata +5 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: d8c12644a3f83d1d263374a88b825a9f705f55d68582e90a50a3065ec2b0105e
         | 
| 4 | 
            +
              data.tar.gz: 3f5ddc8b0d9e5c02bc4845e5a4ac21d07b358f75639146f32c71143bc1e6d605
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: c95071934105bc8c8876287bf460a0466ecc996eab6356c64a994566824c95d2f24d6d446bc8bcc6d4d66b0a224023a4347839e75f5d8204860e9e2210e7e07d
         | 
| 7 | 
            +
              data.tar.gz: ebdbe6bdeafd3f71bf9461f5eccd73f20772043d9e84ab01fa91c0a1dcff054a21c74d718aa40cf0c89bed3219d36d1f46e89ce37ea6d27483bb268518bb7d59
         | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/Gemfile.lock
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -3,7 +3,36 @@ | |
| 3 3 | 
             
            Check for differences between two JSON documents, YAML documents, or Ruby data
         | 
| 4 4 | 
             
            structures parsed from either of those.
         | 
| 5 5 |  | 
| 6 | 
            -
             | 
| 6 | 
            +
            <!-- start of auto-generated TOC; see https://github.com/ekalinin/github-markdown-toc -->
         | 
| 7 | 
            +
            <!--ts-->
         | 
| 8 | 
            +
               * [check_please](#check_please)
         | 
| 9 | 
            +
               * [Installation](#installation)
         | 
| 10 | 
            +
               * [Terminology](#terminology)
         | 
| 11 | 
            +
               * [Usage](#usage)
         | 
| 12 | 
            +
                  * [From the Terminal / Command Line Interface (CLI)](#from-the-terminal--command-line-interface-cli)
         | 
| 13 | 
            +
                  * [From RSpec](#from-rspec)
         | 
| 14 | 
            +
                  * [From Ruby](#from-ruby)
         | 
| 15 | 
            +
                  * [Understanding the Output](#understanding-the-output)
         | 
| 16 | 
            +
                     * [Diff Types](#diff-types)
         | 
| 17 | 
            +
                     * [Paths](#paths)
         | 
| 18 | 
            +
                     * [Output Formats](#output-formats)
         | 
| 19 | 
            +
                  * [Flags](#flags)
         | 
| 20 | 
            +
                     * [Setting Flags in the CLI](#setting-flags-in-the-cli)
         | 
| 21 | 
            +
                     * [Setting Flags in Ruby](#setting-flags-in-ruby)
         | 
| 22 | 
            +
                     * [Repeatable Flags](#repeatable-flags)
         | 
| 23 | 
            +
                     * [Expanded Documentation for Specific Flags](#expanded-documentation-for-specific-flags)
         | 
| 24 | 
            +
                        * [Flag: match_by_key](#flag-match_by_key)
         | 
| 25 | 
            +
               * [TODO (maybe)](#todo-maybe)
         | 
| 26 | 
            +
               * [Development](#development)
         | 
| 27 | 
            +
               * [Contributing](#contributing)
         | 
| 28 | 
            +
               * [License](#license)
         | 
| 29 | 
            +
               * [Code of Conduct](#code-of-conduct)
         | 
| 30 | 
            +
             | 
| 31 | 
            +
             | 
| 32 | 
            +
            <!--te-->
         | 
| 33 | 
            +
            <!-- end of auto-generated TOC -->
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            # Installation
         | 
| 7 36 |  | 
| 8 37 | 
             
            Add this line to your application's Gemfile:
         | 
| 9 38 |  | 
| @@ -19,7 +48,7 @@ Or install it yourself as: | |
| 19 48 |  | 
| 20 49 | 
             
                $ gem install check_please
         | 
| 21 50 |  | 
| 22 | 
            -
             | 
| 51 | 
            +
            # Terminology
         | 
| 23 52 |  | 
| 24 53 | 
             
            I know, you just want to see how to use this thing.  Feel free to scroll down,
         | 
| 25 54 | 
             
            but be aware that CheckPlease uses a few words in a jargony way:
         | 
| @@ -35,9 +64,14 @@ but be aware that CheckPlease uses a few words in a jargony way: | |
| 35 64 | 
             
              **reference** and the **candidate**.  More on this in "Understanding the Output",
         | 
| 36 65 | 
             
              below.
         | 
| 37 66 |  | 
| 38 | 
            -
             | 
| 67 | 
            +
            Also, even though this gem was born from a need to compare JSON documents, I'll
         | 
| 68 | 
            +
            be talking about "hashes" instead of "objects", because I assume this will
         | 
| 69 | 
            +
            mostly be used by Ruby developers.  Feel free to substitute "object" wherever
         | 
| 70 | 
            +
            you see "hash" if that's easier for you.  :)
         | 
| 39 71 |  | 
| 40 | 
            -
             | 
| 72 | 
            +
            # Usage
         | 
| 73 | 
            +
             | 
| 74 | 
            +
            ## From the Terminal / Command Line Interface (CLI)
         | 
| 41 75 |  | 
| 42 76 | 
             
            Use the `bin/check_please` executable.  (To get started, run it with the '-h' flag.)
         | 
| 43 77 |  | 
| @@ -48,7 +82,7 @@ of giving it a second filename as the argument.  (This is especially useful if | |
| 48 82 | 
             
            you're copying an XHR response out of a web browser's dev tools and have a tool
         | 
| 49 83 | 
             
            like MacOS's `pbpaste` utility.)
         | 
| 50 84 |  | 
| 51 | 
            -
             | 
| 85 | 
            +
            ## From RSpec
         | 
| 52 86 |  | 
| 53 87 | 
             
            See [check_please_rspec_matcher](https://github.com/RealGeeks/check_please_rspec_matcher).
         | 
| 54 88 |  | 
| @@ -57,14 +91,19 @@ like to provide custom logic for diffing your own classes, you might be better | |
| 57 91 | 
             
            served by the [super_diff](https://github.com/mcmire/super_diff) gem.  Check it
         | 
| 58 92 | 
             
            out!
         | 
| 59 93 |  | 
| 60 | 
            -
             | 
| 94 | 
            +
            ## From Ruby
         | 
| 95 | 
            +
             | 
| 96 | 
            +
            See also: [./usage_examples.rb](usage_examples.rb).
         | 
| 61 97 |  | 
| 62 98 | 
             
            Create two strings, each containing a JSON or YAML document, and pass them to
         | 
| 63 99 | 
             
            `CheckPlease.render_diff`.  You'll get back a third string containing a report
         | 
| 64 | 
            -
            of all the differences CheckPlease found in the two JSON strings. | 
| 65 | 
            -
             | 
| 100 | 
            +
            of all the differences CheckPlease found in the two JSON strings.
         | 
| 101 | 
            +
             | 
| 102 | 
            +
            Or, if you'd like to inspect the diffs in your own way, use `CheckPlease.diff`
         | 
| 103 | 
            +
            instead.  You'll get back a `CheckPlease::Diffs` custom collection that
         | 
| 104 | 
            +
            contains `CheckPlease::Diff` instances.
         | 
| 66 105 |  | 
| 67 | 
            -
             | 
| 106 | 
            +
            ## Understanding the Output
         | 
| 68 107 |  | 
| 69 108 | 
             
            CheckPlease follows the Unix philosophy of "no news is good news".  If your
         | 
| 70 109 | 
             
            **candidate** matches your **reference**, you'll get an empty message.
         | 
| @@ -118,7 +157,7 @@ mismatch      | /meta/foo | spam       | foo | |
| 118 157 |  | 
| 119 158 | 
             
            Let's start with the leftmost column...
         | 
| 120 159 |  | 
| 121 | 
            -
             | 
| 160 | 
            +
            ### Diff Types
         | 
| 122 161 |  | 
| 123 162 | 
             
            The above example is intended to illustrate every possible type of diff that
         | 
| 124 163 | 
             
            CheckPlease defines:
         | 
| @@ -131,13 +170,14 @@ CheckPlease defines: | |
| 131 170 | 
             
              and it stops when it encounters a type mismatch in order to avoid producing a
         | 
| 132 171 | 
             
              lot of "garbage" diff output.)_
         | 
| 133 172 | 
             
            * **mismatch** means that both the **reference** and the **candidate** had a
         | 
| 134 | 
            -
              value at the given path, and neither value was an Array or a Hash | 
| 173 | 
            +
              value at the given path, and neither value was an Array or a Hash, and the
         | 
| 174 | 
            +
              two values were not equal.
         | 
| 135 175 | 
             
            * **extra** means that, inside an Array or a Hash, the **candidate** contained
         | 
| 136 | 
            -
               | 
| 176 | 
            +
              elements that were not found in the **reference**.
         | 
| 137 177 | 
             
            * **missing** is the opposite of **extra**:  inside an Array or a Hash, the
         | 
| 138 | 
            -
              **reference** contained  | 
| 178 | 
            +
              **reference** contained elements that were not found in the **candidate**.
         | 
| 139 179 |  | 
| 140 | 
            -
             | 
| 180 | 
            +
            ### Paths
         | 
| 141 181 |  | 
| 142 182 | 
             
            The second column contains a path expression.  This is extremely lo-fi:
         | 
| 143 183 |  | 
| @@ -152,32 +192,265 @@ _**Being primarily a Ruby developer, I'm quite ignorant of conventions in the | |
| 152 192 | 
             
            JS community; if there's an existing convention for paths, please open an
         | 
| 153 193 | 
             
            issue!**_
         | 
| 154 194 |  | 
| 155 | 
            -
             | 
| 195 | 
            +
            ### Output Formats
         | 
| 156 196 |  | 
| 157 197 | 
             
            CheckPlease produces tabular output by default.  (It leans heavily on the
         | 
| 158 198 | 
             
            amazing [table_print](http://tableprintgem.com) gem for this.)
         | 
| 159 199 |  | 
| 160 200 | 
             
            If you want to incorporate CheckPlease into some other toolchain, it can also
         | 
| 161 | 
            -
            print diffs as JSON to facilitate parsing.   | 
| 162 | 
            -
             | 
| 201 | 
            +
            print diffs as JSON to facilitate parsing.  How you do this depends on whether
         | 
| 202 | 
            +
            you're using CheckPlease from the command line or in Ruby, which is a good time
         | 
| 203 | 
            +
            to talk about...
         | 
| 204 | 
            +
             | 
| 205 | 
            +
            ## Flags
         | 
| 206 | 
            +
             | 
| 207 | 
            +
            CheckPlease has several flags that control its behavior.
         | 
| 208 | 
            +
             | 
| 209 | 
            +
            For quick help on which flags are available, as well as some terse help text,
         | 
| 210 | 
            +
            you can run the `check_please` executable with no arguments (or the `-h` or
         | 
| 211 | 
            +
            `--help` flags if that makes you feel better).
         | 
| 212 | 
            +
             | 
| 213 | 
            +
            While of course we aspire to keep this README up to date, it's probably best to
         | 
| 214 | 
            +
            believe things in the following priority order:
         | 
| 215 | 
            +
             | 
| 216 | 
            +
            * observed behavior
         | 
| 217 | 
            +
            * the code (start from `./lib/check_please.rb` and search for `Flags.define`,
         | 
| 218 | 
            +
              then trace through as needed)
         | 
| 219 | 
            +
            * the tests (`spec/check_please/flags_spec.rb` describes how the flags work;
         | 
| 220 | 
            +
            	from there, you'll have to search on the flag's name to see how it shows up
         | 
| 221 | 
            +
            	in code)
         | 
| 222 | 
            +
            * the output of `check_please --help`
         | 
| 223 | 
            +
            * this README :)
         | 
| 224 | 
            +
             | 
| 225 | 
            +
            All flags have exactly one "Ruby name" and one or more "CLI names".  When the
         | 
| 226 | 
            +
            CLI runs, it parses the values in `ARGV` (using Ruby's native `OptionParser`)
         | 
| 227 | 
            +
            and uses that information to build a `CheckPlease::Flags` instance.  After that
         | 
| 228 | 
            +
            point, a flag will be referred to within the CheckPlease code exclusively by
         | 
| 229 | 
            +
            its "Ruby name".
         | 
| 230 | 
            +
             | 
| 231 | 
            +
            For example, the flag that controls the format in which diffs are displayed has
         | 
| 232 | 
            +
            a Ruby name of `format`, and CLI names of `-f` and `--format`.
         | 
| 233 | 
            +
             | 
| 234 | 
            +
            ### Setting Flags in the CLI
         | 
| 235 | 
            +
             | 
| 236 | 
            +
            This should behave more or less as an experienced Unix CLI user might expect.
         | 
| 237 | 
            +
             | 
| 238 | 
            +
            As such, you can specify, e.g., that you want output in JSON format using
         | 
| 239 | 
            +
            either `--format json` or `-f json`.
         | 
| 240 | 
            +
             | 
| 241 | 
            +
            (I might expand this section some day.  In the meantime, if you are not yet an
         | 
| 242 | 
            +
            experienced Unix CLI user, feel free to ask for help!  You can either open an
         | 
| 243 | 
            +
            issue or look for emails in the `.gemspec` file...)
         | 
| 244 | 
            +
             | 
| 245 | 
            +
            ### Setting Flags in Ruby
         | 
| 246 | 
            +
             | 
| 247 | 
            +
            All external API entry points allow you to specify flags using their Ruby names
         | 
| 248 | 
            +
            in the idiomatic "options Hash at the end of the argument list" that should be
         | 
| 249 | 
            +
            familiar to most Rubyists.  (Again, I assume that, if you're using this tool, I
         | 
| 250 | 
            +
            don't need to explain this further, but feel free to ask for help if you need
         | 
| 251 | 
            +
            it.)
         | 
| 252 | 
            +
             | 
| 253 | 
            +
            (Internally, CheckPlease immediately converts that options hash into a
         | 
| 254 | 
            +
            `CheckPlease::Flags` object, but that should be considered an implementation
         | 
| 255 | 
            +
            detail unless you're interested in hacking on CheckPlease itself.)
         | 
| 256 | 
            +
             | 
| 257 | 
            +
            For example, to get back a String containing the diffs between two data
         | 
| 258 | 
            +
            structures in JSON format, you might do:
         | 
| 259 | 
            +
             | 
| 260 | 
            +
            ```
         | 
| 261 | 
            +
            reference = { "foo" => "wibble" }
         | 
| 262 | 
            +
            candidate = { "bar" => "wibble" }
         | 
| 263 | 
            +
            puts CheckPlease.render_diff(
         | 
| 264 | 
            +
              reference,
         | 
| 265 | 
            +
              candidate,
         | 
| 266 | 
            +
              format: :json # <--- flags
         | 
| 267 | 
            +
            )
         | 
| 268 | 
            +
            ```
         | 
| 269 | 
            +
             | 
| 270 | 
            +
            ### Repeatable Flags
         | 
| 271 | 
            +
             | 
| 272 | 
            +
            Several flags **may** be specified more than once when invoking the CLI.  I've
         | 
| 273 | 
            +
            tried to make both the CLI and the Ruby API follow their respective
         | 
| 274 | 
            +
            environment's conventions.
         | 
| 275 | 
            +
             | 
| 276 | 
            +
            For example, if you want to specify a path to ignore using the
         | 
| 277 | 
            +
            `--reject-paths` flag, you'd invoke the CLI like this:
         | 
| 278 | 
            +
             | 
| 279 | 
            +
            * `[bundle exec] check_please reference.json candidate.json --select-paths /foo`
         | 
| 280 | 
            +
             | 
| 281 | 
            +
            And if you want to specify more than one path, that would look like:
         | 
| 282 | 
            +
             | 
| 283 | 
            +
            * `[bundle exec] check_please reference.json candidate.json --select-paths /foo --select-paths /bar`
         | 
| 284 | 
            +
             | 
| 285 | 
            +
            In Ruby, you can specify this in the options hash as a single key with an Array
         | 
| 286 | 
            +
            value:
         | 
| 287 | 
            +
             | 
| 288 | 
            +
            * `CheckPlease.render_diff(reference, candidate, select_paths: [ "/foo", "/bar" ])`
         | 
| 289 | 
            +
             | 
| 290 | 
            +
            _(NOTE TO MAINTAINERS: internally, the way `CheckPlease::CLI::Parser` uses
         | 
| 291 | 
            +
            Ruby's `OptionParser` leads to some less than obvious behavior.  Search
         | 
| 292 | 
            +
            [./spec/check_please/flags_spec.rb](spec/check_please/flags_spec.rb) for the
         | 
| 293 | 
            +
            word "surprising" for details.)_
         | 
| 294 | 
            +
             | 
| 295 | 
            +
            ### Expanded Documentation for Specific Flags
         | 
| 296 | 
            +
             | 
| 297 | 
            +
            #### Flag: `match_by_key`
         | 
| 298 | 
            +
             | 
| 299 | 
            +
            > **I know this looks like a LOT of information, but it's really not that
         | 
| 300 | 
            +
            > bad!**  This feature just requires specific examples to describe, and talking
         | 
| 301 | 
            +
            > about it in English (rather than code) is hard.  Take a moment for some deep
         | 
| 302 | 
            +
            > breaths if you need it.  :)
         | 
| 303 | 
            +
             | 
| 304 | 
            +
            > _If you're comfortable reading RSpec and/or want to check out all the edge
         | 
| 305 | 
            +
            > cases, go look in `./spec/check_please/comparison_spec.rb` and check out the
         | 
| 306 | 
            +
            > `describe` block labeled `"comparing arrays by keys"`._
         | 
| 307 | 
            +
             | 
| 308 | 
            +
            The `match_by_key` flag allows you to match up arrays of hashes using the value
         | 
| 309 | 
            +
            of a single key that is treated as the identifier for each hash.
         | 
| 310 | 
            +
             | 
| 311 | 
            +
            There's a lot going on in that sentence, so let's unpack it a bit.
         | 
| 312 | 
            +
             | 
| 313 | 
            +
            Imagine you're comparing two documents that contain the same data, but in
         | 
| 314 | 
            +
            different orders.  To use a contrived example, let's say that both documents
         | 
| 315 | 
            +
            consist of a single array of two simple hashes, but the reference array and the
         | 
| 316 | 
            +
            candidate array are reversed:
         | 
| 317 | 
            +
             | 
| 318 | 
            +
            ```ruby
         | 
| 319 | 
            +
            # REFERENCE
         | 
| 320 | 
            +
            [ { "id" => 1, "foo" => "bar" },  { "id" => 2, "foo" => "spam" } ]
         | 
| 321 | 
            +
             | 
| 322 | 
            +
            # CANDIDATE
         | 
| 323 | 
            +
            [ { "id" => 2, "foo" => "spam" }, { "id" => 1, "foo" => "bar" }  ]
         | 
| 324 | 
            +
            ```
         | 
| 325 | 
            +
             | 
| 326 | 
            +
            By default, CheckPlease will match up array elements by their position in the
         | 
| 327 | 
            +
            array, resulting in a diff report like this:
         | 
| 328 | 
            +
             | 
| 329 | 
            +
            ```
         | 
| 330 | 
            +
            TYPE     | PATH   | REFERENCE | CANDIDATE
         | 
| 331 | 
            +
            ---------|--------|-----------|----------
         | 
| 332 | 
            +
            mismatch | /1/id  | 1         | 2
         | 
| 333 | 
            +
            mismatch | /1/foo | "bar"     | "bat"
         | 
| 334 | 
            +
            mismatch | /2/id  | 2         | 1
         | 
| 335 | 
            +
            mismatch | /2/foo | "bat"     | "bar"
         | 
| 336 | 
            +
            ```
         | 
| 337 | 
            +
             | 
| 338 | 
            +
            To solve this problem, CheckPlease adds a **key expression** to its (very
         | 
| 339 | 
            +
            simple) path syntax that lets you specify a **key** to use to match up elements
         | 
| 340 | 
            +
            in both lists, rather than simply comparing elements by position.
         | 
| 341 | 
            +
             | 
| 342 | 
            +
            Continuing with the above example, if we give `match_by_key` a value of
         | 
| 343 | 
            +
            `["/:id"]`, it will use the "id" value in both hashes (remember, A's `id` is
         | 
| 344 | 
            +
            `1` and B's `id` is `2`) to identify every element in both the reference array
         | 
| 345 | 
            +
            and the candidate array, and correctly match A and B, giving you an empty list
         | 
| 346 | 
            +
            of diffs.
         | 
| 347 | 
            +
             | 
| 348 | 
            +
            Please note that the CLI and Ruby implementations of these are a bit different
         | 
| 349 | 
            +
            (see "Setting Flags in the CLI" versus "Setting Flags in Ruby"), so if you're
         | 
| 350 | 
            +
            doing this from the command line, it'll look like: `--match-by-key /:id`
         | 
| 351 | 
            +
             | 
| 352 | 
            +
            Here, have another example.  If you want to specify a match_by_key expression
         | 
| 353 | 
            +
            below the root of the document, you can put the **key expression** further down
         | 
| 354 | 
            +
            the path: `/books/:isbn`
         | 
| 355 | 
            +
             | 
| 356 | 
            +
            This would correctly match up the following documents:
         | 
| 357 | 
            +
             | 
| 358 | 
            +
            ```ruby
         | 
| 359 | 
            +
            # REFERENCE
         | 
| 360 | 
            +
            {
         | 
| 361 | 
            +
              "books" => [
         | 
| 362 | 
            +
                { "isbn" => "12345", "title" => "Who Am I, Really?" },
         | 
| 363 | 
            +
                { "isbn" => "67890", "title" => "Who Are Any Of Us, Really?" },
         | 
| 364 | 
            +
              ]
         | 
| 365 | 
            +
            }
         | 
| 366 | 
            +
             | 
| 367 | 
            +
            # CANDIDATE
         | 
| 368 | 
            +
            {
         | 
| 369 | 
            +
              "books" => [
         | 
| 370 | 
            +
                { "isbn" => "67890", "title" => "Who Are Any Of Us, Really?" },
         | 
| 371 | 
            +
                { "isbn" => "12345", "title" => "Who Am I, Really?" },
         | 
| 372 | 
            +
              ]
         | 
| 373 | 
            +
            }
         | 
| 374 | 
            +
            ```
         | 
| 375 | 
            +
             | 
| 376 | 
            +
            Finally, if you have deeply nested data with arrays of hashes at multiple
         | 
| 377 | 
            +
            levels, you can specify more than one **key expression** in a single path,
         | 
| 378 | 
            +
            like: `/authors/:id/books/:isbn`
         | 
| 379 | 
            +
             | 
| 380 | 
            +
            This would correctly match up the following documents:
         | 
| 381 | 
            +
             | 
| 382 | 
            +
            ```ruby
         | 
| 383 | 
            +
            # REFERENCE
         | 
| 384 | 
            +
            {
         | 
| 385 | 
            +
              "authors" => [
         | 
| 386 | 
            +
                {
         | 
| 387 | 
            +
                  "id"    => 1,
         | 
| 388 | 
            +
                  "name"  => "Anne Onymous",
         | 
| 389 | 
            +
                  "books" => [
         | 
| 390 | 
            +
                    { "isbn" => "12345", "title" => "Who Am I, Really?" },
         | 
| 391 | 
            +
                    { "isbn" => "67890", "title" => "Who Are Any Of Us, Really?" },
         | 
| 392 | 
            +
                  ]
         | 
| 393 | 
            +
                },
         | 
| 394 | 
            +
              ]
         | 
| 395 | 
            +
            }
         | 
| 163 396 |  | 
| 164 | 
            -
             | 
| 397 | 
            +
            # CANDIDATE
         | 
| 398 | 
            +
            {
         | 
| 399 | 
            +
              "authors" => [
         | 
| 400 | 
            +
                {
         | 
| 401 | 
            +
                  "id"    => 1,
         | 
| 402 | 
            +
                  "name"  => "Anne Onymous",
         | 
| 403 | 
            +
                  "books" => [
         | 
| 404 | 
            +
                    { "isbn" => "67890", "title" => "Who Are Any Of Us, Really?" },
         | 
| 405 | 
            +
                    { "isbn" => "12345", "title" => "Who Am I, Really?" },
         | 
| 406 | 
            +
                  ]
         | 
| 407 | 
            +
                },
         | 
| 408 | 
            +
              ]
         | 
| 409 | 
            +
            }
         | 
| 410 | 
            +
            ```
         | 
| 165 411 |  | 
| 412 | 
            +
            Finally, if there are any diffs to report, CheckPlease uses a **key/value
         | 
| 413 | 
            +
            expression** to report mismatches.
         | 
| 414 | 
            +
             | 
| 415 | 
            +
            Using the last example above (the one with `/authors/:id/books/:isbn`), if the
         | 
| 416 | 
            +
            reference had Anne Onymous' book title as "Who Am I, Really?" and the candidate
         | 
| 417 | 
            +
            listed it as "Who The Heck Am I?", CheckPlease would show the mismatch using
         | 
| 418 | 
            +
            the following path expression: `/authors/id=1/books/isbn=12345`
         | 
| 419 | 
            +
             | 
| 420 | 
            +
            **This syntax is intended to be readable by humans first.**  If you need to
         | 
| 421 | 
            +
            build tooling that consumes it... well, I'm open to suggestions.  :)
         | 
| 422 | 
            +
             | 
| 423 | 
            +
            -----
         | 
| 424 | 
            +
             | 
| 425 | 
            +
            # TODO (maybe)
         | 
| 426 | 
            +
             | 
| 427 | 
            +
            * document flags for rspec matcher
         | 
| 166 428 | 
             
            * command line flags for :allthethings:!
         | 
| 429 | 
            +
              * change display width for table format
         | 
| 430 | 
            +
                (for example, "2020-07-16T19:42:41.312978" gets cut off)
         | 
| 167 431 | 
             
              * sort by path?
         | 
| 168 432 | 
             
            * detect timestamps and compare after parsing?
         | 
| 169 433 | 
             
              * ignore sub-second precision (option / CLI flag)?
         | 
| 170 434 | 
             
              * possibly support plugins for other folks to add custom coercions?
         | 
| 171 | 
            -
            * support expressions of specific paths to ignore
         | 
| 172 | 
            -
              * wildcards?  `#` for indexes, `**` to match one or more path segments?
         | 
| 173 | 
            -
                (This could get ugly fast.)
         | 
| 174 435 | 
             
            * display filters?  (e.g., { a: 1, b: 2 } ==> "Hash#3")
         | 
| 175 436 | 
             
              * shorter descriptions of values with different classes
         | 
| 176 437 | 
             
                (but maybe just the existing :type_mismatch diffs?)
         | 
| 177 438 | 
             
              * another "possibly support plugins" expansion point here
         | 
| 178 439 | 
             
            * more output formats, maybe?
         | 
| 440 | 
            +
            * [0xABAD1DEA] support wildcards in --select-paths and --reject-paths?
         | 
| 441 | 
            +
              * `#` for indexes, `**` to match one or more path segments?
         | 
| 442 | 
            +
                (This could get ugly fast.)
         | 
| 443 | 
            +
            * [0xABAD1DEA] look for a config file in ./.check_please_config or ~/.check_please_config,
         | 
| 444 | 
            +
              combine flags found there with those in ARGV in order of precedence:
         | 
| 445 | 
            +
              1) ARGV
         | 
| 446 | 
            +
              2) ./.check_please
         | 
| 447 | 
            +
              3) ~/.check_please
         | 
| 448 | 
            +
              * but this may not actually be worth the time and complexity to implement, so
         | 
| 449 | 
            +
                think about this first...
         | 
| 179 450 |  | 
| 180 | 
            -
             | 
| 451 | 
            +
            -----
         | 
| 452 | 
            +
             | 
| 453 | 
            +
            # Development
         | 
| 181 454 |  | 
| 182 455 | 
             
            After checking out the repo, run `bin/setup` to install dependencies. Then, run
         | 
| 183 456 | 
             
            `rake spec` to run the tests. You can also run `bin/console` for an interactive
         | 
| @@ -189,22 +462,21 @@ release a new version, update the version number in `version.rb`, and then run | |
| 189 462 | 
             
            git commits and tags, and push the `.gem` file to
         | 
| 190 463 | 
             
            [rubygems.org](https://rubygems.org).
         | 
| 191 464 |  | 
| 192 | 
            -
             | 
| 465 | 
            +
            # Contributing
         | 
| 193 466 |  | 
| 194 467 | 
             
            Bug reports and pull requests are welcome on GitHub at
         | 
| 195 | 
            -
            https://github.com/ | 
| 468 | 
            +
            https://github.com/RealGeeks/check_please. This project is intended to be a
         | 
| 196 469 | 
             
            safe, welcoming space for collaboration, and contributors are expected to
         | 
| 197 470 | 
             
            adhere to the [code of
         | 
| 198 | 
            -
            conduct](https://github.com/ | 
| 199 | 
            -
             | 
| 471 | 
            +
            conduct](https://github.com/RealGeeks/check_please/blob/master/CODE_OF_CONDUCT.md).
         | 
| 200 472 |  | 
| 201 | 
            -
             | 
| 473 | 
            +
            # License
         | 
| 202 474 |  | 
| 203 475 | 
             
            The gem is available as open source under the terms of the [MIT
         | 
| 204 476 | 
             
            License](https://opensource.org/licenses/MIT).
         | 
| 205 477 |  | 
| 206 | 
            -
             | 
| 478 | 
            +
            # Code of Conduct
         | 
| 207 479 |  | 
| 208 480 | 
             
            Everyone interacting in the CheckPlease project's codebases, issue trackers,
         | 
| 209 481 | 
             
            chat rooms and mailing lists is expected to follow the [code of
         | 
| 210 | 
            -
            conduct](https://github.com/ | 
| 482 | 
            +
            conduct](https://github.com/RealGeeks/check_please/blob/master/CODE_OF_CONDUCT.md).
         |