u-struct 1.0.0 → 2.0.0
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/.github/workflows/ci.yml +62 -17
- data/.gitignore +3 -0
- data/.rubocop.yml +137 -0
- data/.rubocop_todo.yml +10 -0
- data/.tool-versions +1 -0
- data/Appraisals +84 -0
- data/CHANGELOG.md +101 -47
- data/CLAUDE.md +144 -0
- data/Gemfile +20 -3
- data/README.md +187 -72
- data/Rakefile +35 -5
- data/bin/console +3 -3
- data/bin/matrix +16 -0
- data/bin/setup +4 -0
- data/bin/tapioca +28 -0
- data/examples/rgb/number.rb +1 -1
- data/examples/rgb_1.rb +3 -3
- data/examples/rgb_2.rb +2 -2
- data/examples/rgb_3.rb +1 -1
- data/lib/micro/struct/factory/create_struct.rb +12 -5
- data/lib/micro/struct/factory/members.rb +1 -0
- data/lib/micro/struct/factory.rb +10 -5
- data/lib/micro/struct/features.rb +18 -23
- data/lib/micro/struct/normalize_names.rb +4 -3
- data/lib/micro/struct/version.rb +2 -1
- data/lib/micro/struct.rb +32 -5
- data/lib/u-struct.rb +2 -0
- data/rbi/micro/struct/factory/create_struct.rbi +60 -0
- data/rbi/micro/struct/factory/members.rbi +67 -0
- data/rbi/micro/struct/factory.rbi +41 -0
- data/rbi/micro/struct/features.rbi +41 -0
- data/rbi/micro/struct/normalize_names.rbi +20 -0
- data/rbi/micro/struct/version.rbi +3 -0
- data/rbi/micro/struct.rbi +68 -0
- data/sorbet/config +8 -0
- data/sorbet/rbi/gems/ast@2.4.2.rbi +54 -0
- data/sorbet/rbi/gems/coderay@1.1.3.rbi +8 -0
- data/sorbet/rbi/gems/diff-lcs@1.5.0.rbi +11 -0
- data/sorbet/rbi/gems/docile@1.4.0.rbi +54 -0
- data/sorbet/rbi/gems/method_source@1.0.0.rbi +8 -0
- data/sorbet/rbi/gems/minitest@5.15.0.rbi +345 -0
- data/sorbet/rbi/gems/parser@3.1.0.0.rbi +1196 -0
- data/sorbet/rbi/gems/pry@0.14.1.rbi +8 -0
- data/sorbet/rbi/gems/rake@13.0.6.rbi +806 -0
- data/sorbet/rbi/gems/rbi@0.0.9.rbi +1602 -0
- data/sorbet/rbi/gems/simplecov-html@0.12.3.rbi +89 -0
- data/sorbet/rbi/gems/simplecov@0.21.2.rbi +577 -0
- data/sorbet/rbi/gems/simplecov_json_formatter@0.1.3.rbi +8 -0
- data/sorbet/rbi/gems/spoom@1.1.8.rbi +1252 -0
- data/sorbet/rbi/gems/tapioca@0.6.2.rbi +1232 -0
- data/sorbet/rbi/gems/thor@1.2.1.rbi +844 -0
- data/sorbet/rbi/gems/unparser@0.6.3.rbi +8 -0
- data/sorbet/rbi/gems/webrick@1.7.0.rbi +601 -0
- data/sorbet/rbi/gems/yard-sorbet@0.6.1.rbi +199 -0
- data/sorbet/rbi/gems/yard@0.9.27.rbi +4112 -0
- data/sorbet/tapioca/config.yml +13 -0
- data/sorbet/tapioca/require.rb +4 -0
- data/u-struct.gemspec +9 -9
- metadata +60 -14
- data/.vscode/settings.json +0 -8
- data/bin/prepare_coverage +0 -27
- data/bin/test +0 -8
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
Notes for AI assistants working in `u-struct`.
|
|
4
|
+
|
|
5
|
+
## Golden rule: maintenance mode — no new features, no breaking changes
|
|
6
|
+
|
|
7
|
+
`u-struct` was created as an alternative to Ruby's native `Data`, which now
|
|
8
|
+
ships with Ruby (3.2+). The gem is therefore considered unnecessary going
|
|
9
|
+
forward and is kept **only to support existing applications**. There are **no
|
|
10
|
+
plans to add new features** — new code should prefer native `Data`.
|
|
11
|
+
|
|
12
|
+
The public API is **frozen**: every change must keep existing code working.
|
|
13
|
+
Major version bumps are reserved for dependency-floor changes (dropping a Ruby
|
|
14
|
+
or Rails version from the supported matrix) per SemVer — they do **not** signal
|
|
15
|
+
a behavior break.
|
|
16
|
+
|
|
17
|
+
So scope work to bug/compatibility fixes and supported-matrix upkeep. If a task
|
|
18
|
+
as stated would add a feature or require a breaking change, stop and surface
|
|
19
|
+
that — suggest native `Data` for new capabilities, or propose a backward-
|
|
20
|
+
compatible path. Don't ship the break or the feature creep.
|
|
21
|
+
|
|
22
|
+
## How to work in this repo
|
|
23
|
+
|
|
24
|
+
### 1. Think before coding
|
|
25
|
+
|
|
26
|
+
**Don't assume. Don't hide confusion. Surface tradeoffs.**
|
|
27
|
+
|
|
28
|
+
- State assumptions explicitly. If uncertain, ask.
|
|
29
|
+
- If multiple interpretations exist, present them — don't pick silently.
|
|
30
|
+
- If a simpler approach exists, say so. Push back when warranted.
|
|
31
|
+
- If something is unclear, stop. Name what's confusing. Ask.
|
|
32
|
+
|
|
33
|
+
### 2. Simplicity first
|
|
34
|
+
|
|
35
|
+
**Minimum code that solves the problem. Nothing speculative.**
|
|
36
|
+
|
|
37
|
+
- No features beyond what was asked.
|
|
38
|
+
- No abstractions for single-use code.
|
|
39
|
+
- No "flexibility" or "configurability" that wasn't requested.
|
|
40
|
+
- No error handling for impossible scenarios.
|
|
41
|
+
- If you write 200 lines and it could be 50, rewrite it.
|
|
42
|
+
|
|
43
|
+
Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes,
|
|
44
|
+
simplify.
|
|
45
|
+
|
|
46
|
+
### 3. Surgical changes
|
|
47
|
+
|
|
48
|
+
**Touch only what you must. Clean up only your own mess.**
|
|
49
|
+
|
|
50
|
+
- Don't "improve" adjacent code, comments, or formatting.
|
|
51
|
+
- Don't refactor things that aren't broken.
|
|
52
|
+
- Match existing style, even if you'd do it differently.
|
|
53
|
+
- If you notice unrelated dead code, mention it — don't delete it.
|
|
54
|
+
- Remove imports/variables/functions that _your_ changes orphaned. Don't
|
|
55
|
+
remove pre-existing dead code unless asked.
|
|
56
|
+
|
|
57
|
+
The test: every changed line should trace directly to the user's request.
|
|
58
|
+
|
|
59
|
+
### 4. Goal-driven execution
|
|
60
|
+
|
|
61
|
+
**Define success criteria. Loop until verified.**
|
|
62
|
+
|
|
63
|
+
Turn vague tasks into verifiable goals:
|
|
64
|
+
|
|
65
|
+
- "Add validation" → "Write tests for invalid inputs, then make them pass"
|
|
66
|
+
- "Fix the bug" → "Write a test that reproduces it, then make it pass"
|
|
67
|
+
- "Refactor X" → "Ensure tests pass before and after"
|
|
68
|
+
|
|
69
|
+
For multi-step work, state a brief plan with a verification check per step.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## What this is
|
|
74
|
+
|
|
75
|
+
`u-struct` is a zero-runtime-dependency Ruby gem for building "powered" Structs.
|
|
76
|
+
The public surface lives under `lib/micro/struct/` and is exposed through
|
|
77
|
+
`Micro::Struct`:
|
|
78
|
+
|
|
79
|
+
- `Micro::Struct.new(...)` — like `Struct`, but members are **required** by
|
|
80
|
+
default; `optional:` / `required:` tune that, and a block adds custom methods.
|
|
81
|
+
- `Micro::Struct.with(*features)` — opt into behaviors before `.new`:
|
|
82
|
+
`:to_ary`, `:to_hash`, `:to_proc`, `:readonly`, `:instance_copy`,
|
|
83
|
+
`:exposed_features`.
|
|
84
|
+
- `Micro::Struct[...]` and `Micro::Struct.instance` — shorthand builders.
|
|
85
|
+
|
|
86
|
+
Internals: `factory/` (`create_struct`, `members`) assembles the Struct,
|
|
87
|
+
`features.rb` implements the opt-in behaviors, `normalize_names.rb` handles
|
|
88
|
+
member-name coercion. The umbrella `require 'u-struct'` loads everything;
|
|
89
|
+
`Micro::Struct::VERSION` lives in `lib/micro/struct/version.rb`.
|
|
90
|
+
|
|
91
|
+
The gem has **no ActiveModel/ActiveRecord dependency** and touches no Rails
|
|
92
|
+
code. The ActiveModel appraisals (see below) exist only to guarantee `u-struct`
|
|
93
|
+
loads and behaves correctly inside Rails apps across the supported range — they
|
|
94
|
+
are a compatibility smoke test, not coverage of Rails-specific behavior.
|
|
95
|
+
|
|
96
|
+
## Running tests
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
bundle exec rake test # default suite, current bundle (no activemodel)
|
|
100
|
+
bundle exec appraisal <name> rake test # one ActiveModel appraisal (see Appraisals)
|
|
101
|
+
bundle exec rake matrix # baseline + every ActiveModel appraisal for the active Ruby
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`bin/setup` reinstalls and refreshes appraisals; `bin/matrix` reinstalls then
|
|
105
|
+
runs `rake matrix`. CI runs the matrix across the full Ruby × ActiveModel grid
|
|
106
|
+
(Ruby 2.7 → head, ActiveModel 6.0 → 8.1 + edge), and additionally runs
|
|
107
|
+
**RuboCop** and **Sorbet** (`srb tc`) on Ruby 3.1 — keep both green:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
bundle exec rubocop # Ruby 3.1 toolchain (pinned in the Gemfile)
|
|
111
|
+
bundle exec srb tc # type-check; sources are `# typed:`-annotated
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Tests are the success criterion for any behavior change — write or update a
|
|
115
|
+
test first, then make it pass (rule 4).
|
|
116
|
+
|
|
117
|
+
## CHANGELOG and README are part of every change
|
|
118
|
+
|
|
119
|
+
Both files are user-facing — keep them in sync with the code:
|
|
120
|
+
|
|
121
|
+
- **`CHANGELOG.md`**: follows [Keep a Changelog](https://keepachangelog.com/).
|
|
122
|
+
Every user-visible change (new API, behavior change, breaking change, dep
|
|
123
|
+
bump that shifts the supported matrix, security fix) gets a bullet under the
|
|
124
|
+
appropriate section (`Added` / `Changed` / `Deprecated` / `Removed` /
|
|
125
|
+
`Fixed` / `Security`) of the `[Unreleased]` block. Pure README/CI/internal-
|
|
126
|
+
refactor changes generally don't need an entry.
|
|
127
|
+
- **`README.md`**: the Ruby/Rails badges at the top encode the supported
|
|
128
|
+
matrix, and the **Usage** section documents the public API. Update the badges
|
|
129
|
+
when the supported bounds move, and update the relevant Usage subsection in
|
|
130
|
+
the same commit when you change a documented API.
|
|
131
|
+
|
|
132
|
+
## Bumping the version
|
|
133
|
+
|
|
134
|
+
1. Edit `lib/micro/struct/version.rb` — change `Micro::Struct::VERSION`. Follow
|
|
135
|
+
[SemVer](https://semver.org/): patch for fixes, minor for additive
|
|
136
|
+
user-visible changes, major for breaking changes.
|
|
137
|
+
2. Add a new entry at the top of `CHANGELOG.md` (`## [X.Y.Z] - YYYY-MM-DD`)
|
|
138
|
+
with a matching `[Diff]`/compare link, and move the `[Unreleased]` items
|
|
139
|
+
into it.
|
|
140
|
+
3. If the supported matrix moved, double-check that the README Ruby/Rails
|
|
141
|
+
badges, the Ruby × Rails CI matrix (`.github/workflows/ci.yml`), and the
|
|
142
|
+
`Appraisals` file all reflect the new bounds.
|
|
143
|
+
|
|
144
|
+
Don't tag, push, or `gem release` — humans do that.
|
data/Gemfile
CHANGED
|
@@ -2,10 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
source 'https://rubygems.org'
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
|
6
|
+
|
|
7
|
+
# Specify your gem's dependencies in u-struct.gemspec
|
|
6
8
|
gemspec
|
|
7
9
|
|
|
8
10
|
gem 'rake', '~> 13.0'
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
gem '
|
|
12
|
+
group :test do
|
|
13
|
+
gem 'minitest', '~> 5.0'
|
|
14
|
+
gem 'ostruct', '~> 0.6.3' if RUBY_VERSION >= '3.5'
|
|
15
|
+
gem 'simplecov', '~> 0.22.0', require: false
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Linting and type-checking run only on Ruby 3.1 (pinned toolchain); see
|
|
19
|
+
# .github/workflows/ci.yml. The pins are gated to that series so they never
|
|
20
|
+
# break `bundle install` on the rest of the Ruby matrix.
|
|
21
|
+
if RUBY_VERSION >= '3.1.0' && RUBY_VERSION < '3.2.0'
|
|
22
|
+
gem 'rubocop', '1.26'
|
|
23
|
+
gem 'rubocop-minitest', '0.18.0'
|
|
24
|
+
gem 'rubocop-rake', '0.6.0'
|
|
25
|
+
|
|
26
|
+
gem 'sorbet', '0.5.9775'
|
|
27
|
+
gem 'tapioca', '0.7.0'
|
|
28
|
+
end
|