README.md in hash_math-0.0.1 vs README.md in hash_math-1.0.0.pre.alpha
- old
+ new
@@ -1,5 +1,239 @@
# HashMath
[](https://badge.fury.io/rb/hash_math) [](https://travis-ci.org/bluemarblepayroll/hash_math) [](https://codeclimate.com/github/bluemarblepayroll/hash_math/maintainability) [](https://codeclimate.com/github/bluemarblepayroll/hash_math/test_coverage) [](https://opensource.org/licenses/MIT)
-Under Construction.
+Ruby's Hash data structure is ubiquitous and highly flexible. This library contains common Hash patterns widely used within our code-base:
+
+* Matrix: build a hash up then expand into hash products
+* Record: define a list of keys and base value to use as a blueprint for hashes
+* Table: key-value pair two-dimensional array of hash builder
+
+See examples for more information on each data structure.
+
+## Installation
+
+To install through Rubygems:
+
+````bash
+gem install install hash_math
+````
+
+You can also add this to your Gemfile:
+
+````bash
+bundle add hash_math
+````
+
+## Examples
+
+### Matrix: The Hash Combination Calculator
+
+HashMath::Matrix is a key-value builder that outputs all the different hash combinations.
+
+Say we have this type of matrix:
+
+````ruby
+{
+ a: [1,2,3],
+ b: [4,5,6],
+ c: [7,8,9]
+}
+````
+
+We could code this as:
+
+````ruby
+matrix = HashMath::Matrix.new
+matrix.add_each(:a, [1,2,3])
+matrix.add_each(:b, [4,5,6])
+matrix.add_each(:c, [7,8,9])
+````
+
+Note: you can also call `Matrix#add` to only add a single value instead of add_each.
+
+and get the combinations by calling to_a:
+
+````ruby
+combinations = matrix.to_a
+````
+
+which would yield the following hashes:
+
+````ruby
+[
+ { a: 1, b: 4, c: 7 },
+ { a: 1, b: 4, c: 8 },
+ { a: 1, b: 4, c: 9 },
+ { a: 1, b: 5, c: 7 },
+ { a: 1, b: 5, c: 8 },
+ { a: 1, b: 5, c: 9 },
+ { a: 1, b: 6, c: 7 },
+ { a: 1, b: 6, c: 8 },
+ { a: 1, b: 6, c: 9 },
+
+ { a: 2, b: 4, c: 7 },
+ { a: 2, b: 4, c: 8 },
+ { a: 2, b: 4, c: 9 },
+ { a: 2, b: 5, c: 7 },
+ { a: 2, b: 5, c: 8 },
+ { a: 2, b: 5, c: 9 },
+ { a: 2, b: 6, c: 7 },
+ { a: 2, b: 6, c: 8 },
+ { a: 2, b: 6, c: 9 },
+
+ { a: 3, b: 4, c: 7 },
+ { a: 3, b: 4, c: 8 },
+ { a: 3, b: 4, c: 9 },
+ { a: 3, b: 5, c: 7 },
+ { a: 3, b: 5, c: 8 },
+ { a: 3, b: 5, c: 9 },
+ { a: 3, b: 6, c: 7 },
+ { a: 3, b: 6, c: 8 },
+ { a: 3, b: 6, c: 9 },
+]
+````
+
+Notes:
+
+* Matrix implements Ruby's Enumerable, which means you have the ability to iterate over each hash combination like you would any other Enumerable object.
+* Values can be arrays and it still works. For example, `#add` (singular form) will honor the array data type: `matrix.add(:a, [1,2,3])` is **not** the same as: `matrix.add_each(:a, [1,2,3])` but it **is** the same as: `matrix.add(:a, [[1,2,3]])`
+* Keys are type-sensitive and work just like Hash keys work.
+
+### Record: The Hash Prototype
+
+HashMath::Record generates a prototype hash and ensures all derived hashes conform to its shape.
+
+Say we have a person hash, for example:
+
+````ruby
+{
+ id: 1,
+ name: 'Matt',
+ location: 'Chicago'
+}
+````
+
+we could create a record modeling this:
+
+````ruby
+record = HashMath::Record.new(%i[id name location], 'UNKNOWN')
+````
+
+Then, we could shape all other hashes using it to ensure each key is populated. If a key is not populated, the base value will be used ('UNKNOWN' in our case.) For example:
+
+````ruby
+records = [
+ record.make(id: 1, name: 'Matt', location: 'Chicago', dob: nil),
+ record.make(id: 2, age: 24),
+ record.make(id: 3, location: 'Los Angeles')
+]
+````
+
+Note: The keys `dob` and `age` appeared in the input but will be ignored as they do not conform to the Record. You could make this strict and raise an error by calling `#make!` instead of `#make`.
+
+our `records` would now equate to:
+
+````ruby
+[
+ { id: 1, name: 'Matt', location: 'Chicago' },
+ { id: 2, name: 'UNKNOWN', location: 'UNKNOWN' },
+ { id: 3, name: 'UNKNOWN', location: 'Los Angeles' },
+]
+````
+
+Notes:
+
+* keys are type-sensitive and works just like Hash keys work.
+
+### Table: The Double Hash (Hash of Hashes)
+
+HashMath::Table builds on top of HashMath::Record. It constructs a table data-structure using a key-value pair builder method: `#add(row_id, field_id, key, value)`. It ultimately outputs an array of Row objects where each Row object has a row_id and fields (field_id => value) hash. The value proposition here is you can iterate over a key-value pair and construct each row any way you wish.
+
+Building on our Record example above:
+
+````ruby
+record = HashMath::Record.new(%i[name location], 'UNKNOWN')
+
+table = HashMath::Table.new(record)
+ .add(1, :name, 'Matt')
+ .add(1, :location, 'Chicago')
+ .add(2, :name, 'Nick')
+ .add(3, :location, 'Los Angeles')
+ .add(2, :name 'Nicholas') # notice the secondary call to "2, :name"
+
+rows = table.to_a
+````
+
+which would set our variable `rows` to:
+
+````ruby
+[
+ HashMath::Row.new(1, { name: 'Matt', location: 'Chicago' }),
+ HashMath::Row.new(2, { name: 'Nicholas', location: 'UNKNOWN' }),
+ HashMath::Row.new(3, { name: 'UNKNOWN', location: 'Los Angeles' })
+]
+````
+
+Notes:
+
+* `#add` will throw a KeyOutOfBoundsError if the key is not found.
+* key is type-sensitive and works just like Hash keys work.
+
+## Contributing
+
+### Development Environment Configuration
+
+Basic steps to take to get this repository compiling:
+
+1. Install [Ruby](https://www.ruby-lang.org/en/documentation/installation/) (check hash_math.gemspec for versions supported)
+2. Install bundler (gem install bundler)
+3. Clone the repository (git clone git@github.com:bluemarblepayroll/hash_math.git)
+4. Navigate to the root folder (cd hash_math)
+5. Install dependencies (bundle)
+
+### Running Tests
+
+To execute the test suite and code-coverage tool, run:
+
+````bash
+bundle exec rspec spec --format documentation
+````
+
+Alternatively, you can have Guard watch for changes:
+
+````bash
+bundle exec guard
+````
+
+Also, do not forget to run Rubocop:
+
+````bash
+bundle exec rubocop
+````
+
+or run all three in one command:
+
+````bash
+bundle exec rake
+````
+
+### Publishing
+
+Note: ensure you have proper authorization before trying to publish new versions.
+
+After code changes have successfully gone through the Pull Request review process then the following steps should be followed for publishing new versions:
+
+1. Merge Pull Request into master
+2. Update `lib/hash_math/version.rb` using [semantic versioning](https://semver.org/)
+3. Install dependencies: `bundle`
+4. Update `CHANGELOG.md` with release notes
+5. Commit & push master to remote and ensure CI builds master successfully
+6. Run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
+
+## Code of Conduct
+
+Everyone interacting in this codebase, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/bluemarblepayroll/hash_math/blob/master/CODE_OF_CONDUCT.md).
+
+## License
+
+This project is MIT Licensed.