nested_objects 0.1.16
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 +7 -0
- data/.commitlintrc.yml +37 -0
- data/.husky/commit-msg +1 -0
- data/.markdownlint.yml +26 -0
- data/.release-please-manifest.json +3 -0
- data/.rspec +3 -0
- data/.rubocop.yml +18 -0
- data/.yamllint.yml +12 -0
- data/.yardopts +8 -0
- data/CHANGELOG.md +10 -0
- data/CONTRIBUTING.md +191 -0
- data/LICENSE.txt +21 -0
- data/README.md +73 -0
- data/Rakefile +78 -0
- data/lib/nested_objects/mixin.rb +31 -0
- data/lib/nested_objects/version.rb +6 -0
- data/lib/nested_objects.rb +207 -0
- data/package.json +11 -0
- data/pre-commit +26 -0
- data/release-please-config.json +36 -0
- metadata +244 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1e46cbbe94fd34a0e69804d0ce6e1a6d3228fa5ff656db4e050c9d29c0e592fc
|
4
|
+
data.tar.gz: 0adb30d3a7ead3749df4f863efaabd2dbc8bb20332ff5e7b1d131bc86dbeb267
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 69ce1523d3959da5f968dc197d1d2375afbdf25be62c5faea10c9cb911edc637733f9172e326e0b0be8b77e24b2880625ee3f8cc659dcc15098417e366ec22e2
|
7
|
+
data.tar.gz: af925766a658fdef76b2ca260e9bdf6322afd737a35e16e56974e2ab7a1769d868fc7b0ec6c0b42d6358bd32c82e86774ecf3f16288da484dab16a8789182411
|
data/.commitlintrc.yml
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
---
|
2
|
+
extends: '@commitlint/config-conventional'
|
3
|
+
|
4
|
+
rules:
|
5
|
+
# See: https://commitlint.js.org/reference/rules.html
|
6
|
+
#
|
7
|
+
# Rules are made up by a name and a configuration array. The configuration
|
8
|
+
# array contains:
|
9
|
+
#
|
10
|
+
# * Severity [0..2]: 0 disable rule, 1 warning if violated, or 2 error if
|
11
|
+
# violated
|
12
|
+
# * Applicability [always|never]: never inverts the rule
|
13
|
+
# * Value: value to use for this rule (if applicable)
|
14
|
+
#
|
15
|
+
# Run `npx commitlint --print-config` to see the current setting for all
|
16
|
+
# rules.
|
17
|
+
#
|
18
|
+
header-max-length: [2, always, 100] # Header can not exceed 100 chars
|
19
|
+
|
20
|
+
type-case: [2, always, lower-case] # Type must be lower case
|
21
|
+
type-empty: [2, never] # Type must not be empty
|
22
|
+
|
23
|
+
# Supported conventional commit types
|
24
|
+
type-enum: [2, always, [build, ci, chore, docs, feat, fix, perf, refactor, revert, style, test]]
|
25
|
+
|
26
|
+
scope-case: [2, always, lower-case] # Scope must be lower case
|
27
|
+
|
28
|
+
# Error if subject is one of these cases (encourages lower-case)
|
29
|
+
subject-case: [2, never, [sentence-case, start-case, pascal-case, upper-case]]
|
30
|
+
subject-empty: [2, never] # Subject must not be empty
|
31
|
+
subject-full-stop: [2, never, "."] # Subject must not end with a period
|
32
|
+
|
33
|
+
body-leading-blank: [2, always] # Body must have a blank line before it
|
34
|
+
body-max-line-length: [2, always, 100] # Body lines can not exceed 100 chars
|
35
|
+
|
36
|
+
footer-leading-blank: [2, always] # Footer must have a blank line before it
|
37
|
+
footer-max-line-length: [2, always, 100] # Footer lines can not exceed 100 chars
|
data/.husky/commit-msg
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
npx --no-install commitlint --edit "$1"
|
data/.markdownlint.yml
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
---
|
2
|
+
default: true
|
3
|
+
|
4
|
+
# Unordered list indentation
|
5
|
+
MD007: { indent: 2 }
|
6
|
+
|
7
|
+
# Line length
|
8
|
+
MD013: { line_length: 90, tables: false, code_blocks: false }
|
9
|
+
|
10
|
+
# Heading duplication is allowed for non-sibling headings
|
11
|
+
MD024: { siblings_only: true }
|
12
|
+
|
13
|
+
# Do not allow the specified trailing punctuation in a header
|
14
|
+
MD026: { punctuation: ".,;:" }
|
15
|
+
|
16
|
+
# Order list items must have a prefix that increases in numerical order
|
17
|
+
MD029: { style: "ordered" }
|
18
|
+
|
19
|
+
# Lists do not need to be surrounded by blank lines
|
20
|
+
MD032: false
|
21
|
+
|
22
|
+
# Allow raw HTML in Markdown
|
23
|
+
MD033: false
|
24
|
+
|
25
|
+
# Allow emphasis to be used instead of a heading
|
26
|
+
MD036: false
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
---
|
2
|
+
inherit_gem:
|
3
|
+
main_branch_shared_rubocop_config: config/rubocop.yml
|
4
|
+
|
5
|
+
Metrics/MethodLength:
|
6
|
+
Exclude:
|
7
|
+
- "spec/spec_helper.rb"
|
8
|
+
- "spec/**/*_spec.rb"
|
9
|
+
|
10
|
+
Metrics/AbcSize:
|
11
|
+
Exclude:
|
12
|
+
- "spec/spec_helper.rb"
|
13
|
+
- "spec/**/*_spec.rb"
|
14
|
+
|
15
|
+
AllCops:
|
16
|
+
# Pin this project to Ruby 3.1 in case the shared config above is
|
17
|
+
# upgraded to 3.2 or later.
|
18
|
+
TargetRubyVersion: 3.1
|
data/.yamllint.yml
ADDED
data/.yardopts
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## [0.1.16](https://github.com/main-branch/nested_objects/compare/v0.1.15...v0.1.16) (2025-04-27)
|
4
|
+
|
5
|
+
|
6
|
+
### Features
|
7
|
+
|
8
|
+
* Initial version of NestedObjects ([515fc47](https://github.com/main-branch/nested_objects/commit/515fc4793ab7ad66dcf3beeff94a011978bff57f))
|
9
|
+
|
10
|
+
## Change Log
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,191 @@
|
|
1
|
+
# Contributing to nested_objects
|
2
|
+
|
3
|
+
Thank you for your interest in contributing to the nested_objects project!
|
4
|
+
|
5
|
+
This document gives the guidelines for contributing to this project.
|
6
|
+
These guidelines may not fit every situation. When contributing use your best
|
7
|
+
judgement.
|
8
|
+
|
9
|
+
Propose changes to these guidelines with a pull request.
|
10
|
+
|
11
|
+
## How to contribute to nested_objects
|
12
|
+
|
13
|
+
You can contribute in two ways:
|
14
|
+
|
15
|
+
1. [Report an issue or make a feature request](#how-to-report-an-issue-or-make-a-feature-request)
|
16
|
+
2. [Submit a code or documentation change](#how-to-submit-a-code-or-documentation-change)
|
17
|
+
|
18
|
+
## How to report an issue or make a feature request
|
19
|
+
|
20
|
+
nested_objects utilizes [GitHub Issues](https://help.github.com/en/github/managing-your-work-on-github/about-issues)
|
21
|
+
for issue tracking and feature requests.
|
22
|
+
|
23
|
+
Report an issue or feature request by [creating a nested_objects Github issue](https://github.com/main-branch/nested_objects/issues/new).
|
24
|
+
Fill in the template to describe the issue or feature request the best you can.
|
25
|
+
|
26
|
+
## How to submit a code or documentation change
|
27
|
+
|
28
|
+
There is three step process for code or documentation changes:
|
29
|
+
|
30
|
+
1. [Commit your changes to a fork of nested_objects](#commit-changes-to-a-fork-of-nested_objects)
|
31
|
+
2. [Create a pull request](#create-a-pull-request)
|
32
|
+
3. [Get your pull request reviewed](#get-your-pull-request-reviewed)
|
33
|
+
|
34
|
+
### Commit changes to a fork of nested_objects
|
35
|
+
|
36
|
+
Make your changes in a fork of the nested_objects repository.
|
37
|
+
|
38
|
+
#### Conventional commits
|
39
|
+
|
40
|
+
All commits to this repository MUST follow [the conventional commits
|
41
|
+
specification](https://www.conventionalcommits.org/en/v1.0.0/#specification). This is
|
42
|
+
so that release versions can automatically be generated based on the commit messages.
|
43
|
+
The Continuous Integration workflow will fail if a commit message is not in this
|
44
|
+
format.
|
45
|
+
|
46
|
+
The format for a conventional commit message is:
|
47
|
+
|
48
|
+
```Text
|
49
|
+
<commit-type>[optional scope]: <description>
|
50
|
+
|
51
|
+
[optional body]
|
52
|
+
|
53
|
+
[optional footer(s)]
|
54
|
+
```
|
55
|
+
|
56
|
+
Where commit type is one of:
|
57
|
+
|
58
|
+
* `feat:` A new feature for the end-user.
|
59
|
+
* `fix:` A bug fix for the end-user.
|
60
|
+
* `build:` Changes that affect the build system or external dependencies (e.g.,
|
61
|
+
changes to npm, webpack, Docker configurations).
|
62
|
+
* `chore:` Routine tasks, maintenance, or changes that don't modify source code or
|
63
|
+
test files (e.g., updating dependencies, configuring linters).
|
64
|
+
* `docs:` Changes to documentation only (e.g., updating README, guides, or extensive
|
65
|
+
code comments).
|
66
|
+
* `style:` Changes that do not affect the meaning or logic of the code (e.g.,
|
67
|
+
white-space, formatting, fixing linter warnings, missing semi-colons).
|
68
|
+
* `refactor:` A code change that neither fixes a bug nor adds a feature, but improves
|
69
|
+
the code structure, readability, or organization without changing its external
|
70
|
+
behavior.
|
71
|
+
* `perf:` A code change that improves performance.
|
72
|
+
* `test:` Adding missing tests or correcting existing tests; changes to the test
|
73
|
+
environment or configuration.
|
74
|
+
|
75
|
+
Backward incompatible changes (aka breaking changes) should append a `!` after the
|
76
|
+
commit type or add the footer `BREAKING CHANGE:` as shown in the following examples:
|
77
|
+
|
78
|
+
```Text
|
79
|
+
fix!: change the interface to match the requirements
|
80
|
+
```
|
81
|
+
|
82
|
+
```Text
|
83
|
+
fix: change the interface to match the requirements
|
84
|
+
|
85
|
+
BREAKING CHANGE: users will need to add additional, non-default option
|
86
|
+
```
|
87
|
+
|
88
|
+
These commit messages will have the following impact on the release version number:
|
89
|
+
|
90
|
+
* Breaking changes (of any commit type) will bump the major version component
|
91
|
+
* `feat:` commits will bump the minor version component
|
92
|
+
* `fix:` commits will bump the patch version component
|
93
|
+
|
94
|
+
Any other commit types (that are not breaking changes) will not trigger a release.
|
95
|
+
|
96
|
+
### Create a pull request
|
97
|
+
|
98
|
+
See [this article](https://help.github.com/articles/about-pull-requests/) if you
|
99
|
+
are not familiar with GitHub Pull Requests.
|
100
|
+
|
101
|
+
Follow the instructions in the pull request template.
|
102
|
+
|
103
|
+
### Get your pull request reviewed
|
104
|
+
|
105
|
+
Code review takes place in a GitHub pull request using the
|
106
|
+
[the Github pull request review feature](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-request-reviews).
|
107
|
+
|
108
|
+
Once your pull request is ready for review, request a review from at least one of the
|
109
|
+
[code owners](https://github.com/orgs/main-branch/teams/nested_objects-codeowners/members).
|
110
|
+
|
111
|
+
During the review process, you may need to make additional commits which would
|
112
|
+
need to be squashed. It may also be necessary to rebase to main again if other
|
113
|
+
changes are merged before your PR.
|
114
|
+
|
115
|
+
At least one approval is required from a project maintainer before your pull
|
116
|
+
request can be merged. The maintainer is responsible for ensuring that the pull
|
117
|
+
request meets [the project's coding standards](#coding-standards).
|
118
|
+
|
119
|
+
## Coding standards
|
120
|
+
|
121
|
+
All pull requests must meet these requirements:
|
122
|
+
|
123
|
+
### Rebase Merge Strategy
|
124
|
+
|
125
|
+
Our project requires a linear commit history, which is achieved by using a
|
126
|
+
rebase strategy to enable fast-forward merges for all Pull Requests (PRs).
|
127
|
+
|
128
|
+
* **Goal:** To integrate PRs without creating extra merge commits, ensuring a clean
|
129
|
+
and linear project history. This requires the PR branch to be eligible for a
|
130
|
+
[fast-forward
|
131
|
+
merge](https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging).
|
132
|
+
* **Commit History:** Before merging, clean up your PR's commit history. Squash
|
133
|
+
related changes into logical commits using interactive rebase (`git rebase -i`).
|
134
|
+
Aim for a minimal number of meaningful commits that represent distinct steps or
|
135
|
+
features.
|
136
|
+
* **Enable Fast-Forward:** To ensure a fast-forward merge is possible, you must
|
137
|
+
rebase your feature branch onto the latest version of the target branch (e.g.,
|
138
|
+
`main`) *before* the PR is merged.
|
139
|
+
* Example commands (assuming your remote is `origin` and the target branch is
|
140
|
+
`main`):
|
141
|
+
|
142
|
+
```bash
|
143
|
+
# Fetch the latest changes from the remote
|
144
|
+
git fetch origin
|
145
|
+
|
146
|
+
# Rebase your current branch onto the latest main branch
|
147
|
+
git rebase origin/main
|
148
|
+
```
|
149
|
+
|
150
|
+
* You may need to resolve conflicts during the rebase process. After successfully
|
151
|
+
rebasing, you'll likely need to force-push your branch (`git push
|
152
|
+
--force-with-lease`).
|
153
|
+
|
154
|
+
* You may need to rebase again if other PRs are merged to main.
|
155
|
+
|
156
|
+
### Unit tests
|
157
|
+
|
158
|
+
- All changes must be accompanied by new or modified RSpec unit tests
|
159
|
+
- The entire test suite must pass when `bundle exec rake spec` is run from the
|
160
|
+
project's local working tree
|
161
|
+
- The unit test suite must maintain 100% code coverage to pass
|
162
|
+
|
163
|
+
### Documentation
|
164
|
+
|
165
|
+
- New and updated public methods must have [YARD](https://yardoc.org/)
|
166
|
+
documentation added to them
|
167
|
+
- [The YARD Cheatsheet](https://gist.github.com/thelastinuit/5984665e6ab69d3c0a413a03602c45be)
|
168
|
+
is a good reference
|
169
|
+
- New and updated public facing features should be documented in the project's
|
170
|
+
[README.md](README.md)
|
171
|
+
- All documentation must pass `yardstick` documentation analysis
|
172
|
+
- The documentation suite must maintain 100% documentation to pass
|
173
|
+
|
174
|
+
### Continuous Integration
|
175
|
+
|
176
|
+
- All tests must pass in the project's [Travis CI](https://travis-ci.org/main-branch/nested_objects)
|
177
|
+
build before the pull request will be merged.
|
178
|
+
- You can simulate what happens in the Travis CI build by running `bundle exec rake` in
|
179
|
+
the projects root directory.
|
180
|
+
|
181
|
+
### Other Design Guidelines
|
182
|
+
|
183
|
+
- Use keyword args with defaults instead of an opts hash
|
184
|
+
|
185
|
+
## Licensing
|
186
|
+
|
187
|
+
nested_objects uses [the MIT license](https://choosealicense.com/licenses/mit/) as
|
188
|
+
declared in the [LICENSE](LICENSE) file.
|
189
|
+
|
190
|
+
Licensing is very important to open source projects. It helps ensure the
|
191
|
+
software continues to be available under the terms that the author desired.
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2025 James Couball
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
# nested_objects gem
|
2
|
+
|
3
|
+
[](https://badge.fury.io/rb/nested_objects)
|
4
|
+
[](https://github.com/main-branch/nested_objects/actions/workflows/continuous_integration.yml)
|
5
|
+
[](https://rubydoc.info/gems/nested_objects/)
|
6
|
+
[](https://rubydoc.info/gems/nested_objects/file/CHANGELOG.md)
|
7
|
+
[](https://main-branch.slack.com/archives/C01CHR7TMM2)
|
8
|
+
|
9
|
+
The `NestedObjects` module provides module level methods to safely navigate and
|
10
|
+
manage a heirarchy of Ruby POROs nested using Hashes or Arrays. Think of these
|
11
|
+
nested data objects like what you would get after reading in a JSON file.
|
12
|
+
|
13
|
+
The key methods are:
|
14
|
+
|
15
|
+
* `NestedObjects.deep_copy(data)` - returns a deep copy of data including nested hash
|
16
|
+
values and array elements
|
17
|
+
* `NestedObjects.dig(data, path)` - returns the value at the given path
|
18
|
+
* `NestedObjects.bury(data, path, value)` - sets a value within the data structure at
|
19
|
+
the given path
|
20
|
+
* `NestedObjects.delete(data, path)` - deletes the Hash key or Array index at the
|
21
|
+
given path
|
22
|
+
* `NestedObjects.path?(data, path)` - returns true if the path exists in the given
|
23
|
+
data structure
|
24
|
+
|
25
|
+
These methods (prefixed with `nested_` to avoid method conflicts) can be mixed into
|
26
|
+
`Object` for ease of use:
|
27
|
+
|
28
|
+
```Ruby
|
29
|
+
Object.include NestedObjects::Mixin
|
30
|
+
|
31
|
+
data = { 'users' => [{ 'name' => 'John Smith'}, { 'name' => 'Jane Doe' }] }
|
32
|
+
|
33
|
+
data.nested_dig(%w[users 1 name]) #=> 'Jane Doe'
|
34
|
+
```
|
35
|
+
|
36
|
+
If the path is malformed or does not exist, a `BadPathError` will be raised.
|
37
|
+
|
38
|
+
## Development
|
39
|
+
|
40
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
41
|
+
`bundle exec rake` to run tests, static analysis, and build the gem.
|
42
|
+
|
43
|
+
For experimentation, you can also run `bin/console` for an interactive (IRB) prompt that
|
44
|
+
automatically requires nested_objects.
|
45
|
+
|
46
|
+
## Contributing
|
47
|
+
|
48
|
+
Bug reports and pull requests are welcome on GitHub at <https://github.com/main-branch/nested_objects>.
|
49
|
+
|
50
|
+
### Commit message guidelines
|
51
|
+
|
52
|
+
All commit messages must follow the [Conventional Commits
|
53
|
+
standard](https://www.conventionalcommits.org/en/v1.0.0/). This helps us maintain a
|
54
|
+
clear and structured commit history, automate versioning, and generate changelogs
|
55
|
+
effectively.
|
56
|
+
|
57
|
+
To ensure compliance, this project includes:
|
58
|
+
|
59
|
+
- A git commit-msg hook that validates your commit messages before they are accepted.
|
60
|
+
|
61
|
+
To activate the hook, you must have node installed and run `npm install`.
|
62
|
+
|
63
|
+
- A GitHub Actions workflow that will enforce the Conventional Commit standard as
|
64
|
+
part of the continuous integration pipeline.
|
65
|
+
|
66
|
+
Any commit message that does not conform to the Conventional Commits standard will
|
67
|
+
cause the workflow to fail and not allow the PR to be merged.
|
68
|
+
|
69
|
+
### Pull request guidelines
|
70
|
+
|
71
|
+
All pull requests must be merged using rebase merges. This ensures that commit
|
72
|
+
messages from the feature branch are preserved in the release branch, keeping the
|
73
|
+
history clean and meaningful.
|
data/Rakefile
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
desc 'Run the same tasks that the CI build will run'
|
4
|
+
if RUBY_PLATFORM == 'java'
|
5
|
+
task default: %w[spec rubocop bundle:audit build]
|
6
|
+
else
|
7
|
+
task default: %w[spec rubocop yard bundle:audit build]
|
8
|
+
end
|
9
|
+
|
10
|
+
# Bundler Audit
|
11
|
+
|
12
|
+
require 'bundler/audit/task'
|
13
|
+
Bundler::Audit::Task.new
|
14
|
+
|
15
|
+
# Bundler Gem Build
|
16
|
+
|
17
|
+
require 'bundler'
|
18
|
+
require 'bundler/gem_tasks'
|
19
|
+
|
20
|
+
# Make it so that calling `rake release` just calls `rake release:rubygems_push` to
|
21
|
+
# avoid creating and pushing a new tag.
|
22
|
+
|
23
|
+
Rake::Task['release'].clear
|
24
|
+
desc 'Customized release task to avoid creating a new tag'
|
25
|
+
task release: 'release:rubygem_push'
|
26
|
+
|
27
|
+
# RSpec
|
28
|
+
|
29
|
+
require 'rspec/core/rake_task'
|
30
|
+
|
31
|
+
RSpec::Core::RakeTask.new
|
32
|
+
|
33
|
+
CLEAN << 'coverage'
|
34
|
+
CLEAN << '.rspec_status'
|
35
|
+
CLEAN << 'rspec-report.xml'
|
36
|
+
|
37
|
+
# Rubocop
|
38
|
+
|
39
|
+
require 'rubocop/rake_task'
|
40
|
+
|
41
|
+
RuboCop::RakeTask.new
|
42
|
+
|
43
|
+
# YARD
|
44
|
+
|
45
|
+
unless RUBY_PLATFORM == 'java'
|
46
|
+
# yard:build
|
47
|
+
|
48
|
+
require 'yard'
|
49
|
+
|
50
|
+
YARD::Rake::YardocTask.new('yard:build') do |t|
|
51
|
+
t.files = %w[lib/**/*.rb examples/**/*]
|
52
|
+
t.options = %w[--no-private]
|
53
|
+
t.stats_options = %w[--list-undoc]
|
54
|
+
end
|
55
|
+
|
56
|
+
CLEAN << '.yardoc'
|
57
|
+
CLEAN << 'doc'
|
58
|
+
|
59
|
+
# yard:audit
|
60
|
+
|
61
|
+
desc 'Run yardstick to show missing YARD doc elements'
|
62
|
+
task :'yard:audit' do
|
63
|
+
sh "yardstick 'lib/**/*.rb'"
|
64
|
+
end
|
65
|
+
|
66
|
+
# yard:coverage
|
67
|
+
|
68
|
+
require 'yardstick/rake/verify'
|
69
|
+
|
70
|
+
Yardstick::Rake::Verify.new(:'yard:coverage') do |verify|
|
71
|
+
verify.threshold = 100
|
72
|
+
end
|
73
|
+
|
74
|
+
# yard
|
75
|
+
|
76
|
+
desc 'Run all YARD tasks'
|
77
|
+
task yard: %i[yard:build yard:audit yard:coverage]
|
78
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module NestedObjects
|
4
|
+
# Include this module to add methods for working with nested data structures
|
5
|
+
#
|
6
|
+
# Usually included into the Object class.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# require 'nested_objects/mixin'
|
10
|
+
# Object.include(NestedObjects::Mixin)
|
11
|
+
# data = { 'a' => { 'b' => [1, 2, 3] } }
|
12
|
+
# data.nested_dig(['a', 'b', '0']) #=> 1
|
13
|
+
#
|
14
|
+
# @api public
|
15
|
+
module Mixin
|
16
|
+
# (see NestedObjects.path?)
|
17
|
+
def nested_path?(path) = NestedObjects.path?(self, path)
|
18
|
+
|
19
|
+
# (see NestedObjects.dig)
|
20
|
+
def nested_dig(path) = NestedObjects.dig(self, path)
|
21
|
+
|
22
|
+
# (see NestedObjects.bury)
|
23
|
+
def nested_bury(path, value) = NestedObjects.bury(self, path, value)
|
24
|
+
|
25
|
+
# (see NestedObjects.delete)
|
26
|
+
def nested_delete(path) = NestedObjects.delete(self, path)
|
27
|
+
|
28
|
+
# (see NestedObjects.deep_copy)
|
29
|
+
def nested_deep_copy = NestedObjects.deep_copy(self)
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,207 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'nested_objects/mixin'
|
4
|
+
require_relative 'nested_objects/version'
|
5
|
+
|
6
|
+
# Utilities for working with POROs arbitrarily nested with Hashes and Arrays
|
7
|
+
# @api public
|
8
|
+
module NestedObjects
|
9
|
+
# Error raised when a path is invalid or does not exist in the data
|
10
|
+
class BadPathError < StandardError; end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
# Creates a deep copy of data using Marshal
|
14
|
+
#
|
15
|
+
# @example
|
16
|
+
# data = { 'a' => { 'b' => [1, 2, 3] } }
|
17
|
+
# NestedObjects.deep_copy(data) #=> { 'a' => { 'b' => [1, 2, 3] } }
|
18
|
+
#
|
19
|
+
# @param data [Object] The object to be deeply copied
|
20
|
+
# @return [Object] A new object that is a deep copy of the input `obj`
|
21
|
+
# @raise [TypeError] if the object cannot be marshaled (see Marshal documentation)
|
22
|
+
def deep_copy(data)
|
23
|
+
Marshal.load(Marshal.dump(data))
|
24
|
+
end
|
25
|
+
|
26
|
+
# Retrieves the value at the specified path in the given data
|
27
|
+
#
|
28
|
+
# @example
|
29
|
+
# data = { 'a' => { 'b' => [1, 2, 3] } }
|
30
|
+
# NestedObjects.dig(data, ['a', 'b', '0']) #=> 1
|
31
|
+
#
|
32
|
+
# @param data [Hash, Array, Object] The data containing the value to retrieve
|
33
|
+
# @param path [Array<String>] An array of keys/indices representing the path to the desired value
|
34
|
+
# @return [Object] the value at the specified path
|
35
|
+
# @raise [BadPathError] if the path is invalid or does not exist
|
36
|
+
def dig(data, path)
|
37
|
+
return data if path.empty?
|
38
|
+
|
39
|
+
raise BadPathError unless data.is_a?(Hash) || data.is_a?(Array)
|
40
|
+
|
41
|
+
if data.is_a?(Hash)
|
42
|
+
dig_into_hash(data, path)
|
43
|
+
else
|
44
|
+
dig_into_array(data, path)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Sets a value within a nested data structure
|
49
|
+
#
|
50
|
+
# Creates intermediate Hashes along the path if they do not exist.
|
51
|
+
# Does NOT create intermediate Arrays (creates a Hash instead).
|
52
|
+
#
|
53
|
+
# @example
|
54
|
+
# data = { 'a' => { 'b' => [1, 2, 3] } }
|
55
|
+
# NestedObjects.bury(data, ['a', 'b', '0'], 42) #=> { 'a' => { 'b' => [42, 2, 3] } }
|
56
|
+
#
|
57
|
+
# @example will overwrite existing values
|
58
|
+
# data = { 'a' => { 'b' => [1, 2, 3] } }
|
59
|
+
# NestedObjects.bury(data, ['a'], 42) #=> { 'a' => 42 }
|
60
|
+
#
|
61
|
+
# @example will create intermediate Hashes
|
62
|
+
# data = {}
|
63
|
+
# NestedObjects.bury(data, ['a', 'b'], 42) #=> { 'a' => { 'b' => 42 } })
|
64
|
+
#
|
65
|
+
# @example will NOT create intermediate Arrays (creates a Hash instead)
|
66
|
+
# data = {}
|
67
|
+
# NestedObjects.bury(data, ['a', '0'], 42) #=> { 'a' => { '0' => [42, 2, 3] } }
|
68
|
+
#
|
69
|
+
# @param data [Hash, Array, Object] The structure to modify
|
70
|
+
# @param path [Array<String>] An array of keys/indices representing the path to the item to set
|
71
|
+
# @param value [Object] The value to set at the specified path
|
72
|
+
# @return [Object] The modified data structure
|
73
|
+
# @raise [BadPathError] if the path is invalid or the item does not exist
|
74
|
+
#
|
75
|
+
def bury(data, path, value)
|
76
|
+
raise BadPathError if path.empty? || !(data.is_a?(Hash) || data.is_a?(Array))
|
77
|
+
|
78
|
+
key, found = next_key(data, path)
|
79
|
+
|
80
|
+
if path.length == 1
|
81
|
+
data[key] = value
|
82
|
+
else
|
83
|
+
data[key] = {} unless found
|
84
|
+
bury(data[key], path[1..], value)
|
85
|
+
end
|
86
|
+
|
87
|
+
data
|
88
|
+
end
|
89
|
+
|
90
|
+
# Delete a key or element from nested data identified by path
|
91
|
+
#
|
92
|
+
# @example
|
93
|
+
# data = { 'a' => { 'b' => [1, 2, 3] } }
|
94
|
+
# NestedObjects.delete(data, ['a', 'b', '0']) #=> 1
|
95
|
+
# data #=> { 'a' => { 'b' => [2, 3] } }
|
96
|
+
#
|
97
|
+
# @param data [Hash, Array, Object] The structure to modify
|
98
|
+
# @param path [Array<String>] An array of keys/indices representing the path to the item to delete
|
99
|
+
# @return [Object] The value of the element that was deleted
|
100
|
+
# @raise [BadPathError] if the path is invalid or the item does not exist
|
101
|
+
#
|
102
|
+
def delete(data, path)
|
103
|
+
raise BadPathError if path.empty? || !(data.is_a?(Hash) || data.is_a?(Array))
|
104
|
+
|
105
|
+
key, found = next_key(data, path)
|
106
|
+
|
107
|
+
raise BadPathError unless found
|
108
|
+
|
109
|
+
if path.length == 1
|
110
|
+
delete_key(data, key)
|
111
|
+
else
|
112
|
+
delete(data[key], path[1..])
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# Check if the path is valid for the given data structure
|
117
|
+
#
|
118
|
+
# @example
|
119
|
+
# data = { 'a' => { 'b' => [1, 2, 3] } }
|
120
|
+
# NestedObjects.path?(data, ['a', 'b', '0']) #=> true
|
121
|
+
# NestedObjects.path?(data, ['d']) #=> false
|
122
|
+
#
|
123
|
+
# @param data [Hash, Array, Object] The structure to check
|
124
|
+
# @param path [Array<String>] An array of keys/indices representing the path to check
|
125
|
+
# @return [Boolean] `true` if the path is valid, `false` otherwise
|
126
|
+
# @raise [BadPathError] if path tries to traverse an Array with a non-integer key
|
127
|
+
#
|
128
|
+
def path?(data, path)
|
129
|
+
return true if path.empty?
|
130
|
+
|
131
|
+
return false unless data.is_a?(Hash) || data.is_a?(Array)
|
132
|
+
|
133
|
+
key, found = next_key(data, path)
|
134
|
+
|
135
|
+
return false unless found
|
136
|
+
|
137
|
+
path?(data[key], path[1..])
|
138
|
+
end
|
139
|
+
|
140
|
+
private
|
141
|
+
|
142
|
+
# Traverse through a Hash via the nest path component
|
143
|
+
# @return the value at the end of the path
|
144
|
+
# @raise [BadPathError] if the path is invalid or does not exist
|
145
|
+
# @api private
|
146
|
+
def dig_into_hash(data, path)
|
147
|
+
key = path.first
|
148
|
+
raise BadPathError unless data.key?(key)
|
149
|
+
|
150
|
+
dig(data[key], path[1..])
|
151
|
+
end
|
152
|
+
|
153
|
+
# Traverse through an Array via the nest path component
|
154
|
+
# @return the value at the end of the path
|
155
|
+
# @raise [BadPathError] if the path is invalid or does not exist
|
156
|
+
# @api private
|
157
|
+
def dig_into_array(data, path)
|
158
|
+
index = key_to_index(path.first)
|
159
|
+
raise BadPathError unless !index.nil? && index >= 0 && index < data.length
|
160
|
+
|
161
|
+
dig(data[index], path[1..])
|
162
|
+
end
|
163
|
+
|
164
|
+
# Delete a Hash key or an Array element from data
|
165
|
+
# @return the value of the element that was deleted
|
166
|
+
# @api private
|
167
|
+
def delete_key(data, key)
|
168
|
+
if data.is_a?(Hash)
|
169
|
+
data.delete(key)
|
170
|
+
else
|
171
|
+
data.delete_at(key)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
# The next key in the path and whether it exists in the root of the data structure
|
176
|
+
#
|
177
|
+
# The next key is a string for Hashes and an integer for Arrays
|
178
|
+
#
|
179
|
+
# @example
|
180
|
+
# next_key({ 'a' => 1 }, ['a']) #=> ['a', true]
|
181
|
+
# next_key({ 'a' => 1 }, ['b']) #=> ['b', false]
|
182
|
+
# @param data [Hash, Array, Object] The data structure to check
|
183
|
+
# @param path [Array<String>] An array of keys/indices representing the path being traversed
|
184
|
+
# @return [Array<[String, Integer], Boolean>] The next key and whether it exists
|
185
|
+
# @api private
|
186
|
+
def next_key(data, path)
|
187
|
+
if data.is_a?(Hash)
|
188
|
+
key = path.first
|
189
|
+
[key, data.key?(key)]
|
190
|
+
else
|
191
|
+
index = key_to_index(path.first)
|
192
|
+
[index, index >= 0 && index < data.length]
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
# Convert a String key to an Integer array index
|
197
|
+
# @param key [String] The key to convert to an index
|
198
|
+
# @return [Integer] the index of the key in the array
|
199
|
+
# @raise [BadPathError] if the key is not a String representation of an Integer
|
200
|
+
# @api private
|
201
|
+
def key_to_index(key)
|
202
|
+
Integer(key)
|
203
|
+
rescue ArgumentError
|
204
|
+
raise BadPathError
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
data/package.json
ADDED
data/pre-commit
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
##
|
4
|
+
# Run this before doing a commit. To ensure this happens, after cloning this
|
5
|
+
# repository, run bin/setup from the projects root directory
|
6
|
+
|
7
|
+
echo 'Performing pre-commit checks'
|
8
|
+
|
9
|
+
# Make sure we are testing with the latest version of gems
|
10
|
+
# since this is what will get installed in the CI build
|
11
|
+
#
|
12
|
+
echo "Running 'bundle update'..."
|
13
|
+
if ! bundle update > /dev/null; then
|
14
|
+
echo 'FAIL: bundle update failed'
|
15
|
+
exit 1
|
16
|
+
fi
|
17
|
+
|
18
|
+
# Run all the tests, code/doc analysis, gem build, etc.
|
19
|
+
#
|
20
|
+
echo "Running 'bundle exec rake default'..."
|
21
|
+
if ! bundle exec rake default > /dev/null 2>&1; then
|
22
|
+
echo 'FAIL: Rake default task failed'
|
23
|
+
exit 1
|
24
|
+
fi
|
25
|
+
|
26
|
+
echo 'SUCCESS'
|
@@ -0,0 +1,36 @@
|
|
1
|
+
{
|
2
|
+
"bootstrap-sha": "c0076bab53d3eae31f3798217e281e3d51a292a3",
|
3
|
+
"packages": {
|
4
|
+
".": {
|
5
|
+
"release-type": "ruby",
|
6
|
+
"package-name": "nested_objects",
|
7
|
+
"changelog-path": "CHANGELOG.md",
|
8
|
+
"version-file": "lib/nested_objects/version.rb",
|
9
|
+
"bump-minor-pre-major": true,
|
10
|
+
"bump-patch-for-minor-pre-major": true,
|
11
|
+
"draft": false,
|
12
|
+
"prerelease": false,
|
13
|
+
"include-component-in-tag": false,
|
14
|
+
"pull-request-title-pattern": "chore: release v${version}",
|
15
|
+
"changelog-sections": [
|
16
|
+
{ "type": "feat", "section": "Features", "hidden": false },
|
17
|
+
{ "type": "fix", "section": "Bug Fixes", "hidden": false },
|
18
|
+
{ "type": "build", "section": "Other Changes", "hidden": false },
|
19
|
+
{ "type": "chore", "section": "Other Changes", "hidden": false },
|
20
|
+
{ "type": "ci", "section": "Other Changes", "hidden": false },
|
21
|
+
{ "type": "docs", "section": "Other Changes", "hidden": false },
|
22
|
+
{ "type": "perf", "section": "Other Changes", "hidden": false },
|
23
|
+
{ "type": "refactor", "section": "Other Changes", "hidden": false },
|
24
|
+
{ "type": "revert", "section": "Other Changes", "hidden": false },
|
25
|
+
{ "type": "style", "section": "Other Changes", "hidden": false },
|
26
|
+
{ "type": "test", "section": "Other Changes", "hidden": false }
|
27
|
+
]
|
28
|
+
}
|
29
|
+
},
|
30
|
+
"plugins": [
|
31
|
+
{
|
32
|
+
"type": "sentence-case"
|
33
|
+
}
|
34
|
+
],
|
35
|
+
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json"
|
36
|
+
}
|
metadata
ADDED
@@ -0,0 +1,244 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nested_objects
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.16
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- James Couball
|
8
|
+
bindir: exe
|
9
|
+
cert_chain: []
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
|
+
dependencies:
|
12
|
+
- !ruby/object:Gem::Dependency
|
13
|
+
name: bundler-audit
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - "~>"
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: '0.9'
|
19
|
+
type: :development
|
20
|
+
prerelease: false
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - "~>"
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: '0.9'
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: create_github_release
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - "~>"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2.1'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '2.1'
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: main_branch_shared_rubocop_config
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0.1'
|
47
|
+
type: :development
|
48
|
+
prerelease: false
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0.1'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: rake
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '13.2'
|
61
|
+
type: :development
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '13.2'
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: rspec
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '3.13'
|
75
|
+
type: :development
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '3.13'
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: rubocop
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '1.75'
|
89
|
+
type: :development
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '1.75'
|
96
|
+
- !ruby/object:Gem::Dependency
|
97
|
+
name: simplecov
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0.22'
|
103
|
+
type: :development
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0.22'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: simplecov-json
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - "~>"
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0.2'
|
117
|
+
type: :development
|
118
|
+
prerelease: false
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - "~>"
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0.2'
|
124
|
+
- !ruby/object:Gem::Dependency
|
125
|
+
name: simplecov-rspec
|
126
|
+
requirement: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - "~>"
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '0.4'
|
131
|
+
type: :development
|
132
|
+
prerelease: false
|
133
|
+
version_requirements: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - "~>"
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0.4'
|
138
|
+
- !ruby/object:Gem::Dependency
|
139
|
+
name: redcarpet
|
140
|
+
requirement: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - "~>"
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '3.6'
|
145
|
+
type: :development
|
146
|
+
prerelease: false
|
147
|
+
version_requirements: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - "~>"
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '3.6'
|
152
|
+
- !ruby/object:Gem::Dependency
|
153
|
+
name: yard
|
154
|
+
requirement: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - "~>"
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '0.9'
|
159
|
+
- - ">="
|
160
|
+
- !ruby/object:Gem::Version
|
161
|
+
version: 0.9.28
|
162
|
+
type: :development
|
163
|
+
prerelease: false
|
164
|
+
version_requirements: !ruby/object:Gem::Requirement
|
165
|
+
requirements:
|
166
|
+
- - "~>"
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: '0.9'
|
169
|
+
- - ">="
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: 0.9.28
|
172
|
+
- !ruby/object:Gem::Dependency
|
173
|
+
name: yardstick
|
174
|
+
requirement: !ruby/object:Gem::Requirement
|
175
|
+
requirements:
|
176
|
+
- - "~>"
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
version: '0.9'
|
179
|
+
type: :development
|
180
|
+
prerelease: false
|
181
|
+
version_requirements: !ruby/object:Gem::Requirement
|
182
|
+
requirements:
|
183
|
+
- - "~>"
|
184
|
+
- !ruby/object:Gem::Version
|
185
|
+
version: '0.9'
|
186
|
+
description: |
|
187
|
+
Utility methods such as deep_copy, dig, bury, delete, and path? for working with
|
188
|
+
PORO structures arbitrarily nested with Hashes and Arrays.
|
189
|
+
email:
|
190
|
+
- jcouball@yahoo.com
|
191
|
+
executables: []
|
192
|
+
extensions: []
|
193
|
+
extra_rdoc_files: []
|
194
|
+
files:
|
195
|
+
- ".commitlintrc.yml"
|
196
|
+
- ".husky/commit-msg"
|
197
|
+
- ".markdownlint.yml"
|
198
|
+
- ".release-please-manifest.json"
|
199
|
+
- ".rspec"
|
200
|
+
- ".rubocop.yml"
|
201
|
+
- ".yamllint.yml"
|
202
|
+
- ".yardopts"
|
203
|
+
- CHANGELOG.md
|
204
|
+
- CONTRIBUTING.md
|
205
|
+
- LICENSE.txt
|
206
|
+
- README.md
|
207
|
+
- Rakefile
|
208
|
+
- lib/nested_objects.rb
|
209
|
+
- lib/nested_objects/mixin.rb
|
210
|
+
- lib/nested_objects/version.rb
|
211
|
+
- package.json
|
212
|
+
- pre-commit
|
213
|
+
- release-please-config.json
|
214
|
+
homepage: https://github.com/main-branch/nested_objects
|
215
|
+
licenses:
|
216
|
+
- MIT
|
217
|
+
metadata:
|
218
|
+
allowed_push_host: https://rubygems.org
|
219
|
+
homepage_uri: https://github.com/main-branch/nested_objects
|
220
|
+
source_code_uri: https://github.com/main-branch/nested_objects
|
221
|
+
documentation_uri: https://rubydoc.info/gems/nested_objects/0.1.16
|
222
|
+
changelog_uri: https://rubydoc.info/gems/nested_objects/0.1.16/file/CHANGELOG.md
|
223
|
+
rubygems_mfa_required: 'true'
|
224
|
+
rdoc_options: []
|
225
|
+
require_paths:
|
226
|
+
- lib
|
227
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
228
|
+
requirements:
|
229
|
+
- - ">="
|
230
|
+
- !ruby/object:Gem::Version
|
231
|
+
version: 3.1.0
|
232
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
233
|
+
requirements:
|
234
|
+
- - ">="
|
235
|
+
- !ruby/object:Gem::Version
|
236
|
+
version: '0'
|
237
|
+
requirements:
|
238
|
+
- 'Platform: Mac, Linux, or Windows'
|
239
|
+
- 'Ruby: MRI 3.1 or later, TruffleRuby 24 or later, or JRuby 9.4 or later'
|
240
|
+
rubygems_version: 3.6.7
|
241
|
+
specification_version: 4
|
242
|
+
summary: Utilities for working with PORO structures arbitrarily nested with Hashes
|
243
|
+
and Arrays
|
244
|
+
test_files: []
|