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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +62 -17
  3. data/.gitignore +3 -0
  4. data/.rubocop.yml +137 -0
  5. data/.rubocop_todo.yml +10 -0
  6. data/.tool-versions +1 -0
  7. data/Appraisals +84 -0
  8. data/CHANGELOG.md +101 -47
  9. data/CLAUDE.md +144 -0
  10. data/Gemfile +20 -3
  11. data/README.md +187 -72
  12. data/Rakefile +35 -5
  13. data/bin/console +3 -3
  14. data/bin/matrix +16 -0
  15. data/bin/setup +4 -0
  16. data/bin/tapioca +28 -0
  17. data/examples/rgb/number.rb +1 -1
  18. data/examples/rgb_1.rb +3 -3
  19. data/examples/rgb_2.rb +2 -2
  20. data/examples/rgb_3.rb +1 -1
  21. data/lib/micro/struct/factory/create_struct.rb +12 -5
  22. data/lib/micro/struct/factory/members.rb +1 -0
  23. data/lib/micro/struct/factory.rb +10 -5
  24. data/lib/micro/struct/features.rb +18 -23
  25. data/lib/micro/struct/normalize_names.rb +4 -3
  26. data/lib/micro/struct/version.rb +2 -1
  27. data/lib/micro/struct.rb +32 -5
  28. data/lib/u-struct.rb +2 -0
  29. data/rbi/micro/struct/factory/create_struct.rbi +60 -0
  30. data/rbi/micro/struct/factory/members.rbi +67 -0
  31. data/rbi/micro/struct/factory.rbi +41 -0
  32. data/rbi/micro/struct/features.rbi +41 -0
  33. data/rbi/micro/struct/normalize_names.rbi +20 -0
  34. data/rbi/micro/struct/version.rbi +3 -0
  35. data/rbi/micro/struct.rbi +68 -0
  36. data/sorbet/config +8 -0
  37. data/sorbet/rbi/gems/ast@2.4.2.rbi +54 -0
  38. data/sorbet/rbi/gems/coderay@1.1.3.rbi +8 -0
  39. data/sorbet/rbi/gems/diff-lcs@1.5.0.rbi +11 -0
  40. data/sorbet/rbi/gems/docile@1.4.0.rbi +54 -0
  41. data/sorbet/rbi/gems/method_source@1.0.0.rbi +8 -0
  42. data/sorbet/rbi/gems/minitest@5.15.0.rbi +345 -0
  43. data/sorbet/rbi/gems/parser@3.1.0.0.rbi +1196 -0
  44. data/sorbet/rbi/gems/pry@0.14.1.rbi +8 -0
  45. data/sorbet/rbi/gems/rake@13.0.6.rbi +806 -0
  46. data/sorbet/rbi/gems/rbi@0.0.9.rbi +1602 -0
  47. data/sorbet/rbi/gems/simplecov-html@0.12.3.rbi +89 -0
  48. data/sorbet/rbi/gems/simplecov@0.21.2.rbi +577 -0
  49. data/sorbet/rbi/gems/simplecov_json_formatter@0.1.3.rbi +8 -0
  50. data/sorbet/rbi/gems/spoom@1.1.8.rbi +1252 -0
  51. data/sorbet/rbi/gems/tapioca@0.6.2.rbi +1232 -0
  52. data/sorbet/rbi/gems/thor@1.2.1.rbi +844 -0
  53. data/sorbet/rbi/gems/unparser@0.6.3.rbi +8 -0
  54. data/sorbet/rbi/gems/webrick@1.7.0.rbi +601 -0
  55. data/sorbet/rbi/gems/yard-sorbet@0.6.1.rbi +199 -0
  56. data/sorbet/rbi/gems/yard@0.9.27.rbi +4112 -0
  57. data/sorbet/tapioca/config.yml +13 -0
  58. data/sorbet/tapioca/require.rb +4 -0
  59. data/u-struct.gemspec +9 -9
  60. metadata +60 -14
  61. data/.vscode/settings.json +0 -8
  62. data/bin/prepare_coverage +0 -27
  63. 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
- # Specify your gem's dependencies in micro-struct.gemspec
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
- gem 'minitest', '~> 5.0'
11
- gem 'simplecov', '~> 0.21.2' if RUBY_VERSION >= '2.5.0'
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