flexor 0.1.0 → 0.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 823be7501c328a913f46121e7aa40b37fde22d73505f92928087f0d68b9355e2
4
- data.tar.gz: 717311911cdb6e059859390ef9b238c1f524ed96d52071563cbc9f56568d119a
3
+ metadata.gz: 957721d918f235f01e558af4a5303fd07a6e92ca70d0ef11b49d2fb58ea9ccfe
4
+ data.tar.gz: 32dd414daa542578908e01fd737f932a5a01ec886571bde813cf5634d82fe7e9
5
5
  SHA512:
6
- metadata.gz: 9abb50d29119d0cb6deb40e8a14dc1bed3cf860fc65eb599adb1fc8f740374fc664440dc55cc5b3868b1cbe93e44d262ea338ab544f0fc590d587d1d738ab047
7
- data.tar.gz: 531b16d783d2f49bf68edd73a27b47a7565f17f6a465b12b64f9d9542e4d781b9b4dfdacf345b941bad847e36afdee523b8666f42d09cb6ef0dc9f4de393a9c4
6
+ metadata.gz: a9082e8189768c8c073448fff223b1aaf3054d9474ac64faf8b3030fd27296c01d1f40a83356b69aa020e32b98ac4d2d0003f5eeebb8bd7652f98413033b9a4d
7
+ data.tar.gz: cef0d9d8d02589775c9361f21e00e494a208555c3048270ac937ebd995a834ab5a66d075c690404feeccbbd344c8a7ae1e37ca1161ef702676c5767ffbc6b359
data/.rubocop.yml CHANGED
@@ -13,10 +13,9 @@ plugins:
13
13
  - rubocop-claude
14
14
  - rubocop-performance
15
15
  - rubocop-rspec
16
- - rubocop-md
17
- - rubocop-rake
18
16
 
19
17
  AllCops:
18
+ NewCops: enable
20
19
  TargetRubyVersion: 3.4
21
20
 
22
21
  # ===========================================================================
@@ -172,9 +171,6 @@ Style/RedundantReturn:
172
171
  # ===========================================================================
173
172
  # Overrides from rubocop-performance — disable chain-hostile cops
174
173
  # ===========================================================================
175
- Performance:
176
- Exclude:
177
- - "spec/**/*"
178
174
 
179
175
  # ChainArrayAllocation flags idiomatic pipelines for microsecond gains.
180
176
  # If we need real throughput we parallelize, not uglify.
@@ -233,12 +229,19 @@ Metrics/BlockLength:
233
229
  - heredoc
234
230
  - method_call
235
231
  AllowedMethods:
232
+ - command
236
233
  - describe
237
234
  - context
238
235
  - shared_examples
239
236
  - shared_examples_for
240
237
  - shared_context
241
238
 
239
+ # Shared test contexts legitimately define many helpers (stdin, stdout,
240
+ # stderr, env, cli, exit_status, output). These are a single fixture,
241
+ # not independent concerns.
242
+ RSpec/MultipleMemoizedHelpers:
243
+ Max: 10
244
+
242
245
  # Anonymous forwarding (*, **, &) breaks TruffleRuby, JRuby, and
243
246
  # Ruby < 3.2. Named args are explicit and portable.
244
247
  #
@@ -379,16 +382,24 @@ RSpec/LeadingSubject:
379
382
  RSpec/ExpectChange:
380
383
  EnforcedStyle: block
381
384
 
382
- RSpec/NamedSubject:
385
+ # Disabled because OpenStruct is used for testing
386
+ Style/OpenStructUse:
383
387
  Enabled: false
384
388
 
385
- # PROJECT SPECIFIC:
386
- #
387
- # Behavior is very intricate here and warrants separation
388
- RSpec/SpecFilePathFormat:
389
+ RSpec/NamedSubject:
389
390
  Enabled: false
390
391
 
392
+ # Would rather be as thorough as possible here as this is inherently a "not normally safe" library
391
393
  RSpec/NestedGroups:
392
- Enabled: false
394
+ Max: 4
395
+
393
396
  RSpec/MultipleExpectations:
394
- Max: 3
397
+ Max: 2
398
+
399
+ # Prefer the explicit &block rather than &
400
+ Naming/BlockForwarding:
401
+ Enabled: false
402
+
403
+ # This has bugs and is causing specs to fail when autocorrected
404
+ Performance/RedundantMerge:
405
+ Enabled: false
data/CLAUDE.md ADDED
@@ -0,0 +1,62 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Rules
6
+
7
+ 1. DO NOT edit .rubocop.yml or add inline rubocop exemptions without explicit permission
8
+ 2. DO NOT run any git command that will rewrite history without explicit permission
9
+ 3. PREFER method & class extraction over comments
10
+ 4. Making new files, classes, modules, and methods IS NOT overengineering
11
+ 5. BEFORE writing code, identify which domain concept owns the behavior. Each class and module should have a single responsibility. If the new behavior doesn't fit an existing class's responsibility, create a new one — don't expand the scope of what's already there.
12
+ 6. DO NOT name classes with suffixes like "-er" or "-or" unless using a canonical pattern name (e.g., Parser, Router, Controller)
13
+ 7. ALWAYS write specs first. The workflow is: identify the domain concept (rule 5), write specs describing its behavior, then implement. No implementation without a failing spec.
14
+
15
+ ## Project
16
+
17
+ Flexor is a Ruby gem providing a Hash-like data store with autovivifying nested access, nil-safe chaining, and seamless conversion between hashes and method-style access. Requires Ruby >= 3.4.
18
+
19
+ ## Commands
20
+
21
+ - `rake spec` — run all tests
22
+ - `bundle exec rspec spec/flexor/flexor_reading_spec.rb` — run a single spec file
23
+ - `bundle exec rspec spec/flexor/flexor_reading_spec.rb:15` — run a single example by line
24
+ - `rake rubocop` — run linter
25
+ - `bundle exec rubocop -a` — autocorrect safe offenses
26
+ - `rake` — run both specs and rubocop (default task)
27
+ - `rake benchmark` — run performance benchmarks (uses YJIT)
28
+ - `rake rdoc` — generate documentation
29
+ - `rake version:current` — show current version
30
+ - `rake version:bump` — bump patch version
31
+ - `bin/console` — IRB session with Flexor loaded
32
+
33
+ ## Architecture
34
+
35
+ Single class `Flexor` in `lib/flexor.rb` with three mixins:
36
+
37
+ - **`Vivification`** (`lib/flexor/vivification.rb`) — recursively converts Hashes/Arrays into Flexor objects on write; reverses via `recurse_to_h` on read. The `@store` uses a `Hash.new` default block that auto-creates child Flexor nodes (autovivification).
38
+ - **`HashDelegation`** (`lib/flexor/hash_delegation.rb`) — delegates `keys`, `values`, `size`, `empty?`, `key?` to `@store`.
39
+ - **`Serialization`** (`lib/flexor/serialization.rb`) — Marshal and YAML round-trip support.
40
+
41
+ Key internals:
42
+ - `@store` is the backing Hash with an autovivifying default block
43
+ - `@root` flag distinguishes top-level instances from auto-created children (affects `inspect` and `nil?` behavior)
44
+ - `method_missing` handles dynamic getter/setter; once accessed, singleton methods are cached for performance (`cache_getter`/`cache_setter`)
45
+ - `nil?` returns `true` when `@store` is empty (non-root nodes appear nil-like until written to)
46
+
47
+ ## Style Conventions (from .rubocop.yml)
48
+
49
+ - Double quotes always (`Style/StringLiterals`)
50
+ - No frozen_string_literal comments
51
+ - Trailing commas in multiline literals/arguments
52
+ - Pipeline-style chaining encouraged (multiline block chains allowed)
53
+ - Block length max 8 (keeps blocks small, push logic into pipelines)
54
+ - Dot-aligned chaining (`Layout/MultilineMethodCallIndentation: aligned`)
55
+ - Consistent 2-space argument indentation (not aligned to first arg)
56
+ - Explicit `begin/rescue/end` preferred over implicit method-body rescue
57
+ - All classes require rdoc documentation (`Style/Documentation`)
58
+ - RSpec: `expect { }.to change { }` block style, nested groups max 4, multiple expectations max 2
59
+
60
+ ## Tests
61
+
62
+ Specs are organized by concern in `spec/flexor/` (reading, writing, merge, serialization, freeze, etc.). The top-level `spec/flexor_spec.rb` only checks the version. RSpec runs with `--format documentation` and monkey patching disabled.
data/issues.rec ADDED
@@ -0,0 +1,24 @@
1
+ %rec: Issue
2
+ %key: Id
3
+ %typedef: Status_t enum open in_progress closed
4
+ %typedef: Description_t regexp /.*/
5
+ %type: Id uuid
6
+ %type: Title line
7
+ %type: Description Description_t
8
+ %type: Updated date
9
+ %type: Status Status_t
10
+ %auto: Id Updated
11
+
12
+ Id: BAA28228-220B-11F1-88B7-FE6CB9572C2E
13
+ Updated: Tue, 17 Mar 2026 10:15:19 -0400
14
+ Title: Add constant F that is set equal to Flexor
15
+ Description: As Flexor is built to maximize ergonomics, it would be ideal to have a shorter way to call it. In lib, there should be f.rb, where F = Flexor as the only line. It could be called like:
16
+ + puts F[json_string].people.first.first_name
17
+ +
18
+ Status: open
19
+
20
+ Id: A4C9FDF4-2220-11F1-BED9-FE6CB9572C2E
21
+ Updated: Tue, 17 Mar 2026 12:45:02 -0400
22
+ Title: Address rubocop offenses
23
+ Description: Currently 30 violations as I write this
24
+ Status: open
data/lib/f.rb ADDED
@@ -0,0 +1,3 @@
1
+ require_relative "flexor"
2
+
3
+ F = Flexor
@@ -1,3 +1,3 @@
1
1
  class Flexor
2
- VERSION = "0.1.0".freeze
2
+ VERSION = "0.1.1".freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flexor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Gillis
@@ -21,6 +21,7 @@ files:
21
21
  - ".rspec"
22
22
  - ".rubocop.yml"
23
23
  - ".ruby-version"
24
+ - CLAUDE.md
24
25
  - LICENSE.txt
25
26
  - README.md
26
27
  - Rakefile
@@ -29,6 +30,8 @@ files:
29
30
  - docs/benchmark-results.md
30
31
  - docs/original_specification.yaml
31
32
  - docs/specification.yaml
33
+ - issues.rec
34
+ - lib/f.rb
32
35
  - lib/flexor.rb
33
36
  - lib/flexor/hash_delegation.rb
34
37
  - lib/flexor/serialization.rb
@@ -58,7 +61,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
58
61
  - !ruby/object:Gem::Version
59
62
  version: '0'
60
63
  requirements: []
61
- rubygems_version: 4.0.6
64
+ rubygems_version: 4.0.7
62
65
  specification_version: 4
63
66
  summary: A Hash-like data store that does what you tell it to do
64
67
  test_files: []