familia 2.0.0.pre7 → 2.0.0.pre10

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 (91) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +13 -0
  3. data/.github/workflows/docs.yml +1 -1
  4. data/.gitignore +9 -9
  5. data/.rubocop.yml +19 -0
  6. data/.yardopts +22 -1
  7. data/CHANGELOG.md +184 -0
  8. data/CLAUDE.md +8 -5
  9. data/Gemfile +1 -1
  10. data/Gemfile.lock +3 -3
  11. data/README.md +97 -2
  12. data/changelog.d/README.md +66 -0
  13. data/changelog.d/fragments/.keep +0 -0
  14. data/changelog.d/template.md.j2 +29 -0
  15. data/docs/archive/.gitignore +2 -0
  16. data/docs/archive/FAMILIA_RELATIONSHIPS.md +210 -0
  17. data/docs/archive/FAMILIA_TECHNICAL.md +823 -0
  18. data/docs/archive/FAMILIA_UPDATE.md +226 -0
  19. data/docs/archive/README.md +67 -0
  20. data/docs/guides/.gitignore +2 -0
  21. data/docs/{wiki → guides}/Feature-System-Guide.md +0 -15
  22. data/docs/{wiki → guides}/Relationships-Guide.md +103 -50
  23. data/docs/guides/relationships-methods.md +266 -0
  24. data/examples/relationships_basic.rb +90 -157
  25. data/familia.gemspec +4 -4
  26. data/lib/familia/connection.rb +4 -21
  27. data/lib/familia/features/external_identifiers/external_identifier_field_type.rb +120 -0
  28. data/lib/familia/features/external_identifiers.rb +111 -0
  29. data/lib/familia/features/object_identifiers/object_identifier_field_type.rb +91 -0
  30. data/lib/familia/features/object_identifiers.rb +194 -0
  31. data/lib/familia/features/relationships/cascading.rb +0 -1
  32. data/lib/familia/features/relationships/indexing.rb +160 -176
  33. data/lib/familia/features/relationships/membership.rb +16 -22
  34. data/lib/familia/features/relationships/querying.rb +7 -12
  35. data/lib/familia/features/relationships/score_encoding.rb +1 -3
  36. data/lib/familia/features/relationships/tracking.rb +61 -22
  37. data/lib/familia/features/relationships.rb +15 -8
  38. data/lib/familia/features/transient_fields.rb +8 -10
  39. data/lib/familia/features.rb +16 -13
  40. data/lib/familia/horreum/core/serialization.rb +2 -5
  41. data/lib/familia/horreum/subclass/definition.rb +36 -0
  42. data/lib/familia/horreum.rb +15 -24
  43. data/lib/familia/version.rb +1 -3
  44. data/setup.cfg +12 -0
  45. data/try/core/errors_try.rb +1 -1
  46. data/try/features/{encrypted_fields_core_try.rb → encrypted_fields/encrypted_fields_core_try.rb} +1 -1
  47. data/try/features/{encrypted_fields_integration_try.rb → encrypted_fields/encrypted_fields_integration_try.rb} +1 -1
  48. data/try/features/{encrypted_fields_no_cache_security_try.rb → encrypted_fields/encrypted_fields_no_cache_security_try.rb} +1 -1
  49. data/try/features/{encrypted_fields_security_try.rb → encrypted_fields/encrypted_fields_security_try.rb} +1 -1
  50. data/try/features/{expiration_try.rb → expiration/expiration_try.rb} +1 -1
  51. data/try/features/external_identifiers/external_identifiers_try.rb +203 -0
  52. data/try/features/object_identifiers/object_identifiers_integration_try.rb +289 -0
  53. data/try/features/object_identifiers/object_identifiers_try.rb +191 -0
  54. data/try/features/{quantization_try.rb → quantization/quantization_try.rb} +1 -1
  55. data/try/features/{categorical_permissions_try.rb → relationships/categorical_permissions_try.rb} +1 -1
  56. data/try/features/relationships/relationships_api_changes_try.rb +339 -0
  57. data/try/features/{relationships_edge_cases_try.rb → relationships/relationships_edge_cases_try.rb} +1 -1
  58. data/try/features/{relationships_performance_minimal_try.rb → relationships/relationships_performance_minimal_try.rb} +1 -1
  59. data/try/features/{relationships_performance_simple_try.rb → relationships/relationships_performance_simple_try.rb} +1 -1
  60. data/try/features/{relationships_performance_try.rb → relationships/relationships_performance_try.rb} +1 -1
  61. data/try/features/{relationships_performance_working_try.rb → relationships/relationships_performance_working_try.rb} +1 -1
  62. data/try/features/{relationships_try.rb → relationships/relationships_try.rb} +7 -6
  63. data/try/features/{safe_dump_advanced_try.rb → safe_dump/safe_dump_advanced_try.rb} +1 -1
  64. data/try/features/{safe_dump_try.rb → safe_dump/safe_dump_try.rb} +1 -1
  65. data/try/features/{transient_fields_core_try.rb → transient_fields/transient_fields_core_try.rb} +1 -1
  66. data/try/features/{transient_fields_integration_try.rb → transient_fields/transient_fields_integration_try.rb} +1 -1
  67. metadata +80 -60
  68. /data/docs/{wiki → guides}/API-Reference.md +0 -0
  69. /data/docs/{wiki → guides}/Connection-Pooling-Guide.md +0 -0
  70. /data/docs/{wiki → guides}/Encrypted-Fields-Overview.md +0 -0
  71. /data/docs/{wiki → guides}/Expiration-Feature-Guide.md +0 -0
  72. /data/docs/{wiki → guides}/Features-System-Developer-Guide.md +0 -0
  73. /data/docs/{wiki → guides}/Field-System-Guide.md +0 -0
  74. /data/docs/{wiki → guides}/Home.md +0 -0
  75. /data/docs/{wiki → guides}/Implementation-Guide.md +0 -0
  76. /data/docs/{wiki → guides}/Quantization-Feature-Guide.md +0 -0
  77. /data/docs/{wiki → guides}/Security-Model.md +0 -0
  78. /data/docs/{wiki → guides}/Transient-Fields-Guide.md +0 -0
  79. /data/try/features/{encryption_fields → encrypted_fields}/aad_protection_try.rb +0 -0
  80. /data/try/features/{encryption_fields → encrypted_fields}/concealed_string_core_try.rb +0 -0
  81. /data/try/features/{encryption_fields → encrypted_fields}/context_isolation_try.rb +0 -0
  82. /data/try/features/{encryption_fields → encrypted_fields}/error_conditions_try.rb +0 -0
  83. /data/try/features/{encryption_fields → encrypted_fields}/fresh_key_derivation_try.rb +0 -0
  84. /data/try/features/{encryption_fields → encrypted_fields}/fresh_key_try.rb +0 -0
  85. /data/try/features/{encryption_fields → encrypted_fields}/key_rotation_try.rb +0 -0
  86. /data/try/features/{encryption_fields → encrypted_fields}/memory_security_try.rb +0 -0
  87. /data/try/features/{encryption_fields → encrypted_fields}/missing_current_key_version_try.rb +0 -0
  88. /data/try/features/{encryption_fields → encrypted_fields}/nonce_uniqueness_try.rb +0 -0
  89. /data/try/features/{encryption_fields → encrypted_fields}/secure_by_default_behavior_try.rb +0 -0
  90. /data/try/features/{encryption_fields → encrypted_fields}/thread_safety_try.rb +0 -0
  91. /data/try/features/{encryption_fields → encrypted_fields}/universal_serialization_safety_try.rb +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7a93de51c8a35c420067d9e48895af37862866667af224a8e13f44647c4e4c76
4
- data.tar.gz: bbdf64f77c182a0498fc757c393071b04b5da3594b4c7d5c12992fe058b44777
3
+ metadata.gz: 5f09bb44b39f033bc38faaff02dd33c645ecd6a98bee533a756707daeb47e00c
4
+ data.tar.gz: 77afd574073258009058ed9f638151b1ca26ba65d06b49f841ad46b52e50a82a
5
5
  SHA512:
6
- metadata.gz: 59a39a481db42739bbebabab9211645b2f7e9eb605742ab936c0b65dfc32973931b1b1f8a1c5d725fed5f5eb0ebdbb87c1c405f87108390ad3b6eb8f5ca89c5a
7
- data.tar.gz: 4dc7dededb21bd7ee988a4d260e30eceb43f19be4c3f5d99f87bac5d632af6e517af5eab2633758e0c6b1552a2635bd0e024ace2210ee1ee83362aa811458b8c
6
+ metadata.gz: c9bf8c181236218f04e7fff9902b63521d316265792a416525ee5da671789ddd636c372d0481b926b9b65b3116680bac698ebef6d37fd3d0117c9235053b98aa
7
+ data.tar.gz: d046f73ca2f6d46833e4bdb0f2a59c6c400b807f5e44f92657a470bd50c09ffae56debfd991f6513898a603ce44e761047d1e4449f8526d3d2a5ac333ebb8e72
@@ -66,3 +66,16 @@ jobs:
66
66
 
67
67
  - name: Run the tryouts
68
68
  run: bundle exec try -vf
69
+
70
+ - name: Validate examples
71
+ continue-on-error: true
72
+ run: |
73
+ echo "=== Validating example syntax ==="
74
+ find examples/ -name "*.rb" -exec ruby -c {} \;
75
+
76
+ echo "=== Running executable examples ==="
77
+ cd examples
78
+ for example in *.rb; do
79
+ echo "Running $example..."
80
+ ruby "$example" || echo "Warning: $example failed to run"
81
+ done
@@ -41,7 +41,7 @@ jobs:
41
41
 
42
42
  - name: Build YARD documentation
43
43
  run: |
44
- bundle exec yard doc --output-dir ./doc --readme README.md
44
+ bundle exec yard doc --output-dir ./doc
45
45
  # Ensure doc directory exists and create .nojekyll file to prevent GitHub Pages Jekyll processing
46
46
  mkdir -p ./doc
47
47
  touch ./doc/.nojekyll
data/.gitignore CHANGED
@@ -12,20 +12,20 @@
12
12
  .*.json
13
13
  *.env
14
14
  *.log
15
- *.md
16
- .mcp.json
17
- !README.md
18
- !CLAUDE.md
19
15
  *.txt
20
- !LICENSE.txt
21
16
  .ruby-version
22
17
  appendonlydir
23
- etc/config
24
18
  log
25
19
  tmp
26
20
  vendor
27
21
  *.gem
28
22
  doc/
29
- !docs/overview.md
30
- !docs/connection_pooling.md
31
- !docs/wiki/**/*.md
23
+
24
+ # Ignore WIP or temp dev files with uppercase names
25
+ [A-Z]*.md
26
+
27
+ # Exclusions
28
+ !README.md
29
+ !CHANGELOG.md
30
+ !CLAUDE.md
31
+ !LICENSE.txt
data/.rubocop.yml CHANGED
@@ -34,6 +34,25 @@ AllCops:
34
34
  - "try/*.rb"
35
35
  - "vendor/**/*"
36
36
 
37
+ #
38
+ # Trailing commas
39
+ Style/TrailingCommaInHashLiteral:
40
+ EnforcedStyleForMultiline: comma
41
+ Enabled: true
42
+
43
+ Style/TrailingCommaInArrayLiteral:
44
+ EnforcedStyleForMultiline: comma
45
+ Enabled: true
46
+
47
+ Style/TrailingCommaInArguments:
48
+ Enabled: true
49
+
50
+ Style/TrailingCommaInBlockArgs:
51
+ Enabled: true
52
+
53
+ Lint/TrailingCommaInAttributeDeclaration:
54
+ Enabled: true
55
+
37
56
  Gemspec/DeprecatedAttributeAssignment:
38
57
  Enabled: true
39
58
 
data/.yardopts CHANGED
@@ -4,6 +4,27 @@
4
4
  --markup-provider kramdown
5
5
  --protected
6
6
  --no-private
7
+ --embed-mixin ClassMethods
8
+ --embed-mixin Features
9
+ --tag feature:"Feature"
10
+ --tag since:"Since Version"
11
+ --tag example:"Example Usage"
12
+ --tag note:"Note"
13
+ --tag warning:"Warning"
14
+ --tag deprecated:"Deprecated"
15
+ --hide-tag nodoc
16
+ --exclude lib/familia/version.rb
7
17
  lib/**/*.rb
8
18
  -
9
- - LICENSE.txt
19
+ CHANGELOG.md
20
+ LICENSE.txt
21
+ docs/guides/Home.md
22
+ docs/guides/Getting-Started.md
23
+ docs/guides/Feature-System-Guide.md
24
+ docs/guides/Relationships-Guide.md
25
+ docs/guides/relationships-methods.md
26
+ docs/guides/Encrypted-Fields-Overview.md
27
+ docs/guides/Connection-Pooling-Guide.md
28
+ docs/reference/api-technical.md
29
+ docs/migration/*.md
30
+ examples/*.rb
data/CHANGELOG.md ADDED
@@ -0,0 +1,184 @@
1
+ # CHANGELOG.md
2
+
3
+ All notable changes to Familia are documented here.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ <!--scriv-insert-here-->
9
+
10
+ <a id='changelog-2.0.0-pre10'></a>
11
+ ## [2.0.0-pre10] - 2025-09-02 18:07:56.439890
12
+
13
+ ### Added
14
+
15
+ - The `Familia::Horreum` initializer now supports creating an object directly from its identifier by passing a single argument (e.g., `Customer.new(customer_id)`). This provides a more convenient and intuitive way to instantiate objects from lookups.
16
+
17
+ - Automatic indexing and class-level tracking on `save()` operations, eliminating the need for manual index updates.
18
+ - Enhanced collection syntax supports the Ruby-idiomatic `<<` operator for more natural relationship management.
19
+
20
+ ### Changed
21
+
22
+ - The `member_of` relationship is now bidirectional. A single call to `member.add_to_owner_collection(owner)` is sufficient to establish the relationship, removing the need for a second, redundant call on the owner object. This fixes bugs where members could be added to collections twice.
23
+
24
+ - **BREAKING**: Refactored Familia Relationships API to remove "global" terminology and simplify method generation. (Closes #86)
25
+ - Split `generate_indexing_instance_methods` into focused `generate_direct_index_methods` and `generate_relationship_index_methods` for better separation between direct class-level and relationship-based indexing.
26
+ - Simplified method generation by removing complex global vs parent conditionals.
27
+ - All indexes are now stored at the class level for consistency.
28
+
29
+ ### Fixed
30
+
31
+ - Fixed a bug in the `class_indexed_by` feature where finder methods (e.g., `find_by_email`) would fail to correctly instantiate objects from the index, returning partially-formed objects.
32
+
33
+ - Refactored connection handling to properly cache and reuse Redis connections. This eliminates repetitive "Overriding existing connection" warnings and improves performance.
34
+
35
+ - Method generation now works consistently for both `class_indexed_by` and `indexed_by` with a `parent:`.
36
+ - Resolved metadata storage issues for dynamically created classes.
37
+ - Improved error handling for nil class names in tracking relationships.
38
+
39
+ ### Documentation
40
+
41
+ - Updated the `examples/relationships_basic.rb` script to reflect the improved, bidirectional `member_of` API and to ensure a clean database state for each run.
42
+
43
+ ### AI Assistance
44
+
45
+ - This refactoring was implemented with Claude Code assistance, including comprehensive test updates and API modernization.
46
+
47
+ <a id='changelog-2.0.0-pre9'></a>
48
+ # [2.0.0-pre9] - 2025-09-02 00:35:28.974817
49
+
50
+ ## Added
51
+
52
+ - Added `class_tracked_in` method for global tracking relationships following Horreum's established `class_` prefix convention
53
+ - Added `class_indexed_by` method for global index relationships with consistent API design
54
+
55
+ ## Changed
56
+
57
+ - **BREAKING**: `tracked_in :global, collection` syntax now raises ArgumentError - use `class_tracked_in collection` instead
58
+ - **BREAKING**: `indexed_by field, index, context: :global` syntax replaced with `class_indexed_by field, index`
59
+ - **BREAKING**: `indexed_by field, index, context: SomeClass` syntax replaced with `indexed_by field, index, parent: SomeClass`
60
+ - Relationships API now provides consistent parameter naming across all relationship types
61
+
62
+ ## Documentation
63
+
64
+ - Updated Relationships Guide with new API syntax and migration examples
65
+ - Updated relationships method documentation with new method signatures
66
+ - Updated basic relationships example to demonstrate new API patterns
67
+ - Added tryouts test coverage in try/features/relationships/relationships_api_changes_try.rb
68
+
69
+
70
+ <a id='changelog-2.0.0-pre8'></a>
71
+ ## [2.0.0-pre8] - 2025-09-01
72
+
73
+ #### Added
74
+
75
+ - Implemented Scriv-based changelog system for sustainable documentation
76
+ - Added fragment-based workflow for tracking changes
77
+ - Created structured changelog templates and configuration
78
+
79
+ ### Documentation
80
+
81
+ - Set up Scriv configuration and directory structure
82
+ - Created README for changelog fragment workflow
83
+
84
+
85
+ <a id='changelog-2.0.0-pre7'></a>
86
+ ## [2.0.0-pre7] - 2025-08-31
87
+
88
+ ### Added
89
+
90
+ - Comprehensive relationships system with three relationship types:
91
+ - `tracked_in` - Multi-presence tracking with score encoding
92
+ - `indexed_by` - O(1) hash-based lookups
93
+ - `member_of` - Bidirectional membership with collision-free naming
94
+ - Categorical permission system with bit-encoded permissions
95
+ - Time-based permission scoring for temporal access control
96
+ - Permission tier hierarchies with inheritance patterns
97
+ - Scalable permission management for large object collections
98
+ - Score-based sorting with custom scoring functions
99
+ - Permission-aware queries filtering by access levels
100
+ - Relationship validation framework ensuring data integrity
101
+
102
+ ### Changed
103
+
104
+ - Performance optimizations for large-scale relationship operations
105
+
106
+ ### Security
107
+
108
+ - GitHub Actions security hardening with matrix optimization
109
+
110
+
111
+ <a id='changelog-2.0.0-pre6'></a>
112
+ ## [2.0.0-pre6] - 2025-08-15
113
+
114
+ ### Added
115
+
116
+ - New `save_if_not_exists` method for conditional persistence
117
+ - Atomic persistence operations with transaction support
118
+ - Enhanced error handling for persistence failures
119
+ - Improved data consistency guarantees
120
+
121
+ ### Changed
122
+
123
+ - Connection provider pattern for flexible pooling strategies
124
+ - Multi-database support with intelligent pool management
125
+ - Thread-safe connection handling for concurrent applications
126
+ - Configurable pool sizing and timeout management
127
+ - Modular class structure with cleaner separation of concerns
128
+ - Enhanced feature system with dependency management
129
+ - Improved inheritance patterns for better code organization
130
+ - Streamlined base class functionality
131
+
132
+ ### Fixed
133
+
134
+ - Critical security fixes in Ruby workflow vulnerabilities
135
+ - Systematic dependency resolution via multi-constraint optimization
136
+
137
+
138
+ <a id='changelog-2.0.0-pre5'></a>
139
+ ## [2.0.0-pre5] - 2025-08-05
140
+
141
+ ### Added
142
+
143
+ - Field-level encryption with transparent access patterns
144
+ - Multiple encryption providers:
145
+ - XChaCha20-Poly1305 (preferred, requires rbnacl)
146
+ - AES-256-GCM (fallback, OpenSSL-based)
147
+ - Field-specific key derivation for cryptographic domain separation
148
+ - Configurable key versioning supporting key rotation
149
+ - Non-persistent field storage for sensitive runtime data
150
+ - RedactedString wrapper preventing accidental logging/serialization
151
+ - Memory-safe handling of sensitive data in Ruby objects
152
+ - API-safe serialization excluding transient fields
153
+
154
+ ### Security
155
+
156
+ - Encryption field security hardening with additional validation
157
+ - Enhanced memory protection for sensitive data handling
158
+ - Improved key management patterns and best practices
159
+ - Security test suite expansion with comprehensive coverage
160
+
161
+
162
+ <a id='changelog-2.0.0-pre'></a>
163
+ ## [2.0.0-pre] - 2025-07-25
164
+
165
+ ### Added
166
+
167
+ - Complete API redesign for clarity and modern Ruby conventions
168
+ - Valkey compatibility alongside traditional Redis support
169
+ - Ruby 3.4+ modernization with fiber and thread safety improvements
170
+ - Connection pooling foundation with provider pattern architecture
171
+
172
+ ### Changed
173
+
174
+ - `Familia::Base` replaced by `Familia::Horreum` as the primary base class
175
+ - Connection configuration moved from simple string to block-based setup
176
+ - Feature activation changed from `include` to `feature` declarations
177
+ - Method naming updated for consistency (`delete` → `destroy`, `exists` → `exists?`, `dump` → `serialize`)
178
+
179
+ ### Documentation
180
+
181
+ - YARD documentation workflow with automated GitHub Pages deployment
182
+ - Comprehensive migration guide for v1.x to v2.0.0-pre transition
183
+
184
+ <!-- scriv-end-here -->
data/CLAUDE.md CHANGED
@@ -44,18 +44,21 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
44
44
  - **Generate documentation**: `bundle exec yard`
45
45
  - **Code linting**: `bundle exec rubocop`
46
46
 
47
+ ### Changelog Management
48
+
49
+ Add changelog fragment with each user-facing or documented change (optional but encouraged). See:
50
+ @changelog.d/README.md
51
+
47
52
  ### Known Issues & Quirks
48
- - **Reserved Keywords**: Cannot use `ttl`, `db`, `redis` as field names - use prefixed alternatives
53
+ - **Reserved Keywords**: Cannot use `ttl`, `db`, `valkey`, `redis` as field names - use prefixed alternatives
49
54
  - **Empty Identifiers**: Cause stack overflow in key generation - validate before operations
50
55
  - **Connection Pool Race Conditions**: Thread safety issues under high concurrency
51
- - **Manual Key Sync**: `key` field doesn't auto-sync with identifier changes
52
- - **RedisType Redis Parameter**: `:redis` parameter silently ignored (missing setter)
53
56
 
54
57
  ### Debugging
55
- - **Database command logging**: `tail plop.log` - Real-time Database command monitoring
58
+ - **Database command logging**: You can request real-time Database command monitoring from the user
56
59
  - Shows all Database operations with timestamps, database numbers, and full commands
57
60
  - Updates live as tests run or code executes
58
- - Essential for debugging Familia ORM Database interactions
61
+ - Essential for debugging Familia ORM Database interactions, multi/exec, pipelining, logical_database issues
59
62
 
60
63
  ### Testing Framework
61
64
  This project uses `tryouts` instead of RSpec/Minitest. Test files are located in the `try/` directory and follow the pattern `*_try.rb`.
data/Gemfile CHANGED
@@ -9,7 +9,7 @@ group :test do
9
9
  gem 'tryouts', path: '../tryouts'
10
10
  gem 'uri-valkey', path: '..//uri-valkey/gems', glob: 'uri-valkey.gemspec'
11
11
  else
12
- gem 'tryouts', '~> 3.5.1', require: false
12
+ gem 'tryouts', '~> 3.5.2', require: false
13
13
  end
14
14
  gem 'concurrent-ruby', '~> 1.3.5', require: false
15
15
  gem 'ruby-prof'
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- familia (2.0.0.pre6)
4
+ familia (2.0.0.pre10)
5
5
  benchmark
6
6
  connection_pool
7
7
  csv
@@ -113,7 +113,7 @@ GEM
113
113
  ruby-progressbar (1.13.0)
114
114
  stackprof (0.2.27)
115
115
  stringio (3.1.7)
116
- tryouts (3.5.1)
116
+ tryouts (3.5.2)
117
117
  concurrent-ruby (~> 1.0)
118
118
  irb
119
119
  minitest (~> 5.0)
@@ -148,7 +148,7 @@ DEPENDENCIES
148
148
  rubocop-thread_safety
149
149
  ruby-prof
150
150
  stackprof
151
- tryouts (~> 3.5.1)
151
+ tryouts (~> 3.5.2)
152
152
  yard (~> 0.9)
153
153
 
154
154
  BUNDLED WITH
data/README.md CHANGED
@@ -118,9 +118,104 @@ user.transaction do |conn|
118
118
  end
119
119
  ```
120
120
 
121
- ## Conclusion
121
+ ### Object Relationships
122
122
 
123
- Familia provides a powerful and flexible way to work with Valkey-compatible in Ruby applications. Its features like automatic expiration, safe dumping, and quantization make it suitable for a wide range of use cases, from simple key-value storage to complex time-series data management.
123
+ Familia includes a powerful relationships system for managing object associations:
124
+
125
+ ```ruby
126
+ class Customer < Familia::Horreum
127
+ feature :relationships
128
+
129
+ identifier_field :custid
130
+ field :custid, :name, :email
131
+ set :domains # Collection for related objects
132
+
133
+ # Automatic indexing and tracking
134
+ class_indexed_by :email, :email_lookup
135
+ class_tracked_in :all_customers, score: :created_at
136
+ end
137
+
138
+ class Domain < Familia::Horreum
139
+ feature :relationships
140
+
141
+ identifier_field :domain_id
142
+ field :domain_id, :name, :status
143
+
144
+ # Bidirectional membership
145
+ member_of Customer, :domains
146
+ end
147
+
148
+ # Clean, Ruby-like syntax
149
+ customer = Customer.new(custid: "cust123", email: "admin@acme.com")
150
+ customer.save # Automatically indexed and tracked
151
+
152
+ domain = Domain.new(domain_id: "dom456", name: "acme.com")
153
+ customer.domains << domain # Clean collection syntax
154
+
155
+ # Fast O(1) lookups
156
+ found_customer = Customer.find_by_email("admin@acme.com")
157
+ ```
158
+
159
+ ## Advanced Features
160
+
161
+ ### Relationships and Associations
162
+
163
+ Familia provides three types of relationships with automatic management:
164
+
165
+ - **`member_of`** - Bidirectional membership with clean `<<` operator support
166
+ - **`indexed_by`** - O(1) hash-based field lookups (class-level or relationship-scoped)
167
+ - **`tracked_in`** - Scored collections for rankings, time-series, and analytics
168
+
169
+ All relationships support automatic indexing and tracking - objects are automatically added to class-level collections when saved, with no manual management required.
170
+
171
+ ## Organizing Complex Models
172
+
173
+ For large applications, you can organize model complexity using custom features:
174
+
175
+ ### Self-Registering Features
176
+
177
+ ```ruby
178
+ # app/features/customer_management.rb
179
+ module MyApp::Features::CustomerManagement
180
+ Familia::Base.add_feature(self, :customer_management)
181
+
182
+ def self.included(base)
183
+ base.extend(ClassMethods)
184
+ end
185
+
186
+ module ClassMethods
187
+ def create_with_validation(attrs)
188
+ # Complex creation logic
189
+ end
190
+ end
191
+
192
+ def complex_business_method
193
+ # Instance methods
194
+ end
195
+ end
196
+
197
+ # models/customer.rb
198
+ class Customer < Familia::Horreum
199
+ field :email, :name
200
+ feature :customer_management # Clean model definition
201
+ end
202
+ ```
203
+
204
+ This keeps complex models organized while maintaining Familia's clean, declarative style.
205
+
206
+ ## AI Development Assistance
207
+
208
+ This version of Familia was developed with assistance from AI tools. The following tools provided significant help with architecture design, code generation, and documentation:
209
+
210
+ - **Google Gemini** - Refactoring, code generation, and documentation.
211
+ - **Claude Sonnet 4, Opus 4.1** - Architecture design, code generation, and documentation
212
+ - **Claude Desktop & Claude Code (Max plan)** - Interactive development sessions and debugging
213
+ - **GitHub Copilot** - Code completion and refactoring assistance
214
+ - **Qodo Merge Pro** - Code review and quality improvements
215
+
216
+ I remain responsible for all design decisions and the final code. I believe in being transparent about development tools, especially as AI becomes more integrated into our workflows as developers.
217
+
218
+ ## Epilogue
124
219
 
125
220
  For more information, visit:
126
221
  - [Github Repository](https://github.com/delano/familia)
@@ -0,0 +1,66 @@
1
+ # Changelog Fragments
2
+
3
+ This directory contains changelog fragments managed by [Scriv](https://scriv.readthedocs.io/).
4
+
5
+ ## Our Approach
6
+
7
+ Changelogs are for humans and agents, not just machines. We follow the core principles of [Keep a Changelog](https://keepachangelog.com) to ensure our release notes are clear, consistent, and trustworthy.
8
+
9
+ To achieve this, we use a fragment-based workflow with `scriv`. Instead of a single, large `CHANGELOG.md` file that can cause merge conflicts, each developer includes a small changelog fragment with their pull request. At release time, these fragments are collected and aggregated into the main changelog.
10
+
11
+ This approach provides several benefits:
12
+ - **Reduces Merge Conflicts:** Developers can work in parallel without conflicting over a central changelog file.
13
+ - **Improves Developer Experience:** Creating a small, focused fragment is a simple and repeatable task during development.
14
+ - **Ensures Consistency:** Automation helps maintain a consistent structure for all changelog entries.
15
+ - **Builds Trust:** A clear and well-maintained changelog communicates respect for our users and collaborators.
16
+
17
+ ## How to Add a Changelog Entry
18
+
19
+ 1. **Create a New Fragment:**
20
+ ```bash
21
+ scriv create
22
+ ```
23
+ This will create a new file in the `changelog.d/fragments/` directory.
24
+
25
+ **Alternative:** Use `scriv create --edit` to create and immediately open in your editor.
26
+ **Important:** You must add content and save before exiting, or scriv will abort with "Empty fragment, aborting..."
27
+
28
+ 2. **Edit the Fragment File:**
29
+ Open the newly created file and add your entry under the relevant category. See the guidelines below for writing good entries.
30
+
31
+ 3. **Commit with Your Code:**
32
+ ```bash
33
+ git add changelog.d/fragments/your_fragment_name.md
34
+ git commit
35
+ ```
36
+
37
+ ## Fragment Guidelines
38
+
39
+ - **One Fragment Per Change:** Keep each fragment focused on a single feature, fix, or improvement.
40
+ - **Documenting AI Assistance:** If a change involved significant AI assistance, place it in its own fragment. This ensures the `### AI Assistance` section clearly corresponds to the single change described in that fragment.
41
+ - **Write for a Human Audience:** Describe the *impact* of the change, not just the implementation details.
42
+ - **Good:** "Improved the performance and stability of Redis connections under high load."
43
+ - **Bad:** "Refactored the `RedisManager` to use a connection pool."
44
+ - **Be Specific:** Avoid generic messages like "fixed a bug." Clearly state what was fixed.
45
+ - **Include Context:** Reference issue or pull request numbers to provide a link to the discussion and implementation details. `scriv` will automatically create links for them.
46
+ - **Example:** `- Fixed a bug where users could not reset their passwords. (Closes #123)`
47
+
48
+ ### Categories
49
+
50
+ Use these categories from [Keep a Changelog](https://keepachangelog.com):
51
+
52
+ - **Added**: New features or capabilities.
53
+ - **Changed**: Changes to existing functionality.
54
+ - **Deprecated**: Soon-to-be removed features.
55
+ - **Removed**: Now removed features.
56
+ - **Fixed**: Bug fixes.
57
+ - **Security**: Security-related improvements.
58
+ - **Documentation**: Documentation improvements.
59
+
60
+ ## Release Process
61
+
62
+ At release time, an authorized maintainer will collect all fragments into the main `CHANGELOG.md` file:
63
+
64
+ ```bash
65
+ scriv collect --version 2.0.0
66
+ ```
File without changes
@@ -0,0 +1,29 @@
1
+ <!--
2
+ A new scriv fragment. Uncomment sections as needed.
3
+ Reference issues or pull requests in parentheses at the end of the entry.
4
+ Example: - Fixed a bug in the connection pool. (Closes #123)
5
+ -->
6
+
7
+ ### Added
8
+ <!-- - New features or capabilities -->
9
+
10
+ ### Changed
11
+ <!-- - Changes to existing functionality -->
12
+
13
+ ### Deprecated
14
+ <!-- - Soon-to-be removed features -->
15
+
16
+ ### Removed
17
+ <!-- - Now removed features -->
18
+
19
+ ### Fixed
20
+ <!-- - Bug fixes -->
21
+
22
+ ### Security
23
+ <!-- - Security-related improvements -->
24
+
25
+ ### Documentation
26
+ <!-- - Documentation improvements -->
27
+
28
+ ### AI Assistance
29
+ <!-- - Briefly describe how AI was used for this change (e.g., "Refactoring and documentation by Gemini"). -->
@@ -0,0 +1,2 @@
1
+ # Even all uppercase markdown docs get the blues
2
+ !*.md