familia 2.0.0.pre15 → 2.0.0.pre17

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 (288) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +2 -2
  3. data/.github/workflows/code-quality.yml +138 -0
  4. data/.github/workflows/code-smells.yml +85 -0
  5. data/.github/workflows/docs.yml +31 -8
  6. data/.gitignore +3 -1
  7. data/.pre-commit-config.yaml +7 -1
  8. data/.reek.yml +98 -0
  9. data/.rubocop.yml +54 -10
  10. data/.talismanrc +9 -0
  11. data/.yardopts +18 -13
  12. data/CHANGELOG.rst +86 -4
  13. data/CLAUDE.md +39 -1
  14. data/Gemfile +6 -5
  15. data/Gemfile.lock +99 -23
  16. data/LICENSE.txt +1 -1
  17. data/README.md +285 -85
  18. data/changelog.d/README.md +2 -2
  19. data/docs/archive/FAMILIA_RELATIONSHIPS.md +22 -22
  20. data/docs/archive/FAMILIA_TECHNICAL.md +42 -42
  21. data/docs/archive/FAMILIA_UPDATE.md +3 -3
  22. data/docs/archive/README.md +3 -2
  23. data/docs/{guides/API-Reference.md → archive/api-reference.md} +87 -101
  24. data/docs/conf.py +29 -0
  25. data/docs/guides/{Field-System-Guide.md → core-field-system.md} +9 -9
  26. data/docs/guides/feature-encrypted-fields.md +785 -0
  27. data/docs/guides/{Expiration-Feature-Guide.md → feature-expiration.md} +11 -2
  28. data/docs/guides/feature-external-identifiers.md +637 -0
  29. data/docs/guides/feature-object-identifiers.md +435 -0
  30. data/docs/guides/{Quantization-Feature-Guide.md → feature-quantization.md} +94 -29
  31. data/docs/guides/feature-relationships-methods.md +684 -0
  32. data/docs/guides/feature-relationships.md +200 -0
  33. data/docs/guides/{Features-System-Developer-Guide.md → feature-system-devs.md} +4 -4
  34. data/docs/guides/{Feature-System-Guide.md → feature-system.md} +5 -5
  35. data/docs/guides/{Transient-Fields-Guide.md → feature-transient-fields.md} +2 -2
  36. data/docs/guides/{Implementation-Guide.md → implementation.md} +3 -3
  37. data/docs/guides/index.md +176 -0
  38. data/docs/guides/{Security-Model.md → security-model.md} +1 -1
  39. data/docs/migrating/v2.0.0-pre.md +1 -1
  40. data/docs/migrating/v2.0.0-pre11.md +2 -2
  41. data/docs/migrating/v2.0.0-pre12.md +2 -2
  42. data/docs/migrating/v2.0.0-pre5.md +33 -12
  43. data/docs/migrating/v2.0.0-pre6.md +2 -2
  44. data/docs/migrating/v2.0.0-pre7.md +8 -8
  45. data/docs/overview.md +624 -20
  46. data/docs/reference/api-technical.md +1365 -0
  47. data/examples/autoloader/mega_customer/features/deprecated_fields.rb +7 -0
  48. data/examples/autoloader/mega_customer/safe_dump_fields.rb +1 -1
  49. data/examples/autoloader/mega_customer.rb +3 -1
  50. data/examples/encrypted_fields.rb +378 -0
  51. data/examples/json_usage_patterns.rb +144 -0
  52. data/examples/relationships.rb +13 -13
  53. data/examples/safe_dump.rb +7 -7
  54. data/examples/single_connection_transaction_confusions.rb +379 -0
  55. data/lib/familia/base.rb +51 -10
  56. data/lib/familia/connection/handlers.rb +223 -0
  57. data/lib/familia/connection/individual_command_proxy.rb +64 -0
  58. data/lib/familia/connection/middleware.rb +75 -0
  59. data/lib/familia/connection/operation_core.rb +93 -0
  60. data/lib/familia/connection/operations.rb +277 -0
  61. data/lib/familia/connection/pipeline_core.rb +87 -0
  62. data/lib/familia/connection/transaction_core.rb +100 -0
  63. data/lib/familia/connection.rb +60 -186
  64. data/lib/familia/data_type/class_methods.rb +63 -0
  65. data/lib/familia/data_type/commands.rb +53 -51
  66. data/lib/familia/data_type/connection.rb +83 -0
  67. data/lib/familia/data_type/serialization.rb +108 -107
  68. data/lib/familia/data_type/settings.rb +96 -0
  69. data/lib/familia/data_type/types/counter.rb +1 -1
  70. data/lib/familia/data_type/types/hashkey.rb +15 -11
  71. data/lib/familia/data_type/types/{list.rb → listkey.rb} +13 -5
  72. data/lib/familia/data_type/types/lock.rb +3 -2
  73. data/lib/familia/data_type/types/sorted_set.rb +128 -14
  74. data/lib/familia/data_type/types/{string.rb → stringkey.rb} +7 -9
  75. data/lib/familia/data_type/types/unsorted_set.rb +20 -27
  76. data/lib/familia/data_type.rb +12 -171
  77. data/lib/familia/distinguisher.rb +85 -0
  78. data/lib/familia/encryption/encrypted_data.rb +15 -24
  79. data/lib/familia/encryption/manager.rb +6 -4
  80. data/lib/familia/encryption/providers/aes_gcm_provider.rb +1 -1
  81. data/lib/familia/encryption/providers/secure_xchacha20_poly1305_provider.rb +7 -9
  82. data/lib/familia/encryption/providers/xchacha20_poly1305_provider.rb +4 -5
  83. data/lib/familia/encryption/request_cache.rb +7 -7
  84. data/lib/familia/encryption.rb +2 -3
  85. data/lib/familia/errors.rb +9 -3
  86. data/lib/familia/features/autoloader.rb +30 -12
  87. data/lib/familia/features/encrypted_fields/concealed_string.rb +3 -4
  88. data/lib/familia/features/encrypted_fields/encrypted_field_type.rb +13 -14
  89. data/lib/familia/features/encrypted_fields.rb +71 -66
  90. data/lib/familia/features/expiration/extensions.rb +1 -1
  91. data/lib/familia/features/expiration.rb +31 -26
  92. data/lib/familia/features/external_identifier.rb +57 -19
  93. data/lib/familia/features/object_identifier.rb +134 -25
  94. data/lib/familia/features/quantization.rb +16 -21
  95. data/lib/familia/features/relationships/README.md +97 -0
  96. data/lib/familia/features/relationships/collection_operations.rb +104 -0
  97. data/lib/familia/features/relationships/indexing/multi_index_generators.rb +202 -0
  98. data/lib/familia/features/relationships/indexing/unique_index_generators.rb +306 -0
  99. data/lib/familia/features/relationships/indexing.rb +182 -256
  100. data/lib/familia/features/relationships/indexing_relationship.rb +35 -0
  101. data/lib/familia/features/relationships/participation/participant_methods.rb +164 -0
  102. data/lib/familia/features/relationships/participation/target_methods.rb +225 -0
  103. data/lib/familia/features/relationships/participation.rb +656 -0
  104. data/lib/familia/features/relationships/participation_relationship.rb +31 -0
  105. data/lib/familia/features/relationships/score_encoding.rb +20 -20
  106. data/lib/familia/features/relationships.rb +65 -266
  107. data/lib/familia/features/safe_dump.rb +127 -130
  108. data/lib/familia/features/transient_fields/redacted_string.rb +6 -6
  109. data/lib/familia/features/transient_fields/transient_field_type.rb +5 -5
  110. data/lib/familia/features/transient_fields.rb +10 -7
  111. data/lib/familia/features.rb +10 -14
  112. data/lib/familia/field_type.rb +6 -4
  113. data/lib/familia/horreum/connection.rb +297 -0
  114. data/lib/familia/horreum/{core/database_commands.rb → database_commands.rb} +27 -17
  115. data/lib/familia/horreum/{subclass/definition.rb → definition.rb} +139 -74
  116. data/lib/familia/horreum/{subclass/management.rb → management.rb} +73 -27
  117. data/lib/familia/horreum/{core/serialization.rb → persistence.rb} +108 -185
  118. data/lib/familia/horreum/{subclass/related_fields_management.rb → related_fields.rb} +104 -23
  119. data/lib/familia/horreum/serialization.rb +172 -0
  120. data/lib/familia/horreum/{shared/settings.rb → settings.rb} +2 -1
  121. data/lib/familia/horreum/{core/utils.rb → utils.rb} +2 -1
  122. data/lib/familia/horreum.rb +222 -119
  123. data/lib/familia/json_serializer.rb +0 -1
  124. data/lib/familia/logging.rb +11 -114
  125. data/lib/familia/refinements/dear_json.rb +122 -0
  126. data/lib/familia/refinements/logger_trace.rb +20 -17
  127. data/lib/familia/refinements/stylize_words.rb +65 -0
  128. data/lib/familia/refinements/time_literals.rb +60 -52
  129. data/lib/familia/refinements.rb +2 -1
  130. data/lib/familia/secure_identifier.rb +60 -28
  131. data/lib/familia/settings.rb +83 -7
  132. data/lib/familia/utils.rb +5 -87
  133. data/lib/familia/verifiable_identifier.rb +4 -4
  134. data/lib/familia/version.rb +1 -1
  135. data/lib/familia.rb +72 -14
  136. data/lib/middleware/database_middleware.rb +56 -14
  137. data/lib/{familia/multi_result.rb → multi_result.rb} +23 -16
  138. data/try/configuration/scenarios_try.rb +2 -2
  139. data/try/connection/fiber_context_preservation_try.rb +250 -0
  140. data/try/connection/handler_constraints_try.rb +59 -0
  141. data/try/connection/operation_mode_guards_try.rb +208 -0
  142. data/try/connection/pipeline_fallback_integration_try.rb +128 -0
  143. data/try/connection/responsibility_chain_tracking_try.rb +72 -0
  144. data/try/connection/transaction_fallback_integration_try.rb +288 -0
  145. data/try/connection/transaction_mode_permissive_try.rb +153 -0
  146. data/try/connection/transaction_mode_strict_try.rb +98 -0
  147. data/try/connection/transaction_mode_warn_try.rb +131 -0
  148. data/try/connection/transaction_modes_try.rb +249 -0
  149. data/try/core/autoloader_try.rb +120 -2
  150. data/try/core/connection_try.rb +10 -10
  151. data/try/core/conventional_inheritance_try.rb +130 -0
  152. data/try/core/create_method_try.rb +15 -23
  153. data/try/core/database_consistency_try.rb +11 -10
  154. data/try/core/errors_try.rb +11 -14
  155. data/try/core/familia_extended_try.rb +2 -2
  156. data/try/core/familia_members_methods_try.rb +76 -0
  157. data/try/core/familia_try.rb +1 -1
  158. data/try/core/isolated_dbclient_try.rb +165 -0
  159. data/try/core/middleware_try.rb +16 -16
  160. data/try/core/persistence_operations_try.rb +4 -4
  161. data/try/core/pools_try.rb +42 -26
  162. data/try/core/secure_identifier_try.rb +28 -24
  163. data/try/core/time_utils_try.rb +10 -10
  164. data/try/core/tools_try.rb +3 -3
  165. data/try/core/utils_try.rb +2 -2
  166. data/try/data_types/boolean_try.rb +4 -4
  167. data/try/data_types/datatype_base_try.rb +0 -2
  168. data/try/data_types/list_try.rb +10 -10
  169. data/try/data_types/sorted_set_try.rb +5 -5
  170. data/try/data_types/sorted_set_zadd_options_try.rb +625 -0
  171. data/try/data_types/string_try.rb +12 -12
  172. data/try/data_types/unsortedset_try.rb +33 -0
  173. data/try/debugging/cache_behavior_tracer.rb +7 -7
  174. data/try/debugging/debug_aad_process.rb +1 -1
  175. data/try/debugging/debug_concealed_internal.rb +1 -1
  176. data/try/debugging/debug_cross_context.rb +1 -1
  177. data/try/debugging/debug_fresh_cross_context.rb +1 -1
  178. data/try/debugging/encryption_method_tracer.rb +10 -10
  179. data/try/edge_cases/hash_symbolization_try.rb +1 -1
  180. data/try/edge_cases/ttl_side_effects_try.rb +1 -1
  181. data/try/encryption/config_persistence_try.rb +2 -2
  182. data/try/encryption/encryption_core_try.rb +19 -19
  183. data/try/encryption/instance_variable_scope_try.rb +1 -1
  184. data/try/encryption/module_loading_try.rb +2 -2
  185. data/try/encryption/providers/aes_gcm_provider_try.rb +1 -1
  186. data/try/encryption/providers/xchacha20_poly1305_provider_try.rb +1 -1
  187. data/try/encryption/secure_memory_handling_try.rb +1 -1
  188. data/try/features/encrypted_fields/concealed_string_core_try.rb +11 -7
  189. data/try/features/encrypted_fields/encrypted_fields_core_try.rb +1 -1
  190. data/try/features/encrypted_fields/encrypted_fields_integration_try.rb +3 -3
  191. data/try/features/encrypted_fields/encrypted_fields_no_cache_security_try.rb +10 -10
  192. data/try/features/encrypted_fields/encrypted_fields_security_try.rb +14 -14
  193. data/try/features/encrypted_fields/error_conditions_try.rb +7 -7
  194. data/try/features/encrypted_fields/fresh_key_try.rb +1 -1
  195. data/try/features/encrypted_fields/nonce_uniqueness_try.rb +1 -1
  196. data/try/features/encrypted_fields/secure_by_default_behavior_try.rb +7 -7
  197. data/try/features/encrypted_fields/universal_serialization_safety_try.rb +13 -20
  198. data/try/features/external_identifier/external_identifier_try.rb +1 -1
  199. data/try/features/feature_dependencies_try.rb +3 -3
  200. data/try/features/field_groups_try.rb +244 -0
  201. data/try/features/object_identifier/object_identifier_integration_try.rb +28 -34
  202. data/try/features/object_identifier/object_identifier_try.rb +10 -0
  203. data/try/features/quantization/quantization_try.rb +1 -1
  204. data/try/features/relationships/indexing_commands_verification_try.rb +136 -0
  205. data/try/features/relationships/indexing_try.rb +443 -0
  206. data/try/features/relationships/participation_commands_verification_spec.rb +102 -0
  207. data/try/features/relationships/participation_commands_verification_try.rb +105 -0
  208. data/try/features/relationships/participation_performance_improvements_try.rb +124 -0
  209. data/try/features/relationships/participation_reverse_index_try.rb +196 -0
  210. data/try/features/relationships/relationships_api_changes_try.rb +72 -71
  211. data/try/features/relationships/relationships_edge_cases_try.rb +15 -18
  212. data/try/features/relationships/relationships_performance_minimal_try.rb +2 -2
  213. data/try/features/relationships/relationships_performance_simple_try.rb +8 -8
  214. data/try/features/relationships/relationships_performance_try.rb +20 -20
  215. data/try/features/relationships/relationships_try.rb +27 -38
  216. data/try/features/safe_dump/safe_dump_advanced_try.rb +2 -2
  217. data/try/features/transient_fields/refresh_reset_try.rb +3 -1
  218. data/try/features/transient_fields/simple_refresh_test.rb +1 -1
  219. data/try/helpers/test_cleanup.rb +86 -0
  220. data/try/helpers/test_helpers.rb +6 -7
  221. data/try/horreum/auto_indexing_on_save_try.rb +212 -0
  222. data/try/horreum/base_try.rb +3 -2
  223. data/try/horreum/commands_try.rb +3 -1
  224. data/try/horreum/defensive_initialization_try.rb +86 -0
  225. data/try/horreum/destroy_related_fields_cleanup_try.rb +332 -0
  226. data/try/horreum/initialization_try.rb +11 -7
  227. data/try/horreum/relations_try.rb +21 -13
  228. data/try/horreum/serialization_try.rb +12 -11
  229. data/try/horreum/settings_try.rb +2 -0
  230. data/try/integration/cross_component_try.rb +3 -3
  231. data/try/memory/memory_basic_test.rb +1 -1
  232. data/try/memory/memory_docker_ruby_dump.sh +2 -2
  233. data/try/models/customer_safe_dump_try.rb +1 -1
  234. data/try/models/customer_try.rb +13 -15
  235. data/try/models/datatype_base_try.rb +3 -3
  236. data/try/models/familia_object_try.rb +9 -8
  237. data/try/performance/benchmarks_try.rb +2 -2
  238. data/try/prototypes/atomic_saves_v1_context_proxy.rb +2 -2
  239. data/try/prototypes/atomic_saves_v3_connection_pool.rb +3 -3
  240. data/try/prototypes/atomic_saves_v4.rb +1 -1
  241. data/try/prototypes/lib/atomic_saves_v2_connection_switching_helpers.rb +4 -4
  242. data/try/prototypes/lib/atomic_saves_v3_connection_pool_helpers.rb +4 -4
  243. data/try/prototypes/pooling/lib/atomic_saves_v3_connection_pool_helpers.rb +4 -4
  244. data/try/prototypes/pooling/lib/connection_pool_metrics.rb +5 -5
  245. data/try/prototypes/pooling/lib/connection_pool_stress_test.rb +26 -26
  246. data/try/prototypes/pooling/lib/connection_pool_threading_models.rb +7 -7
  247. data/try/prototypes/pooling/lib/visualize_stress_results.rb +1 -1
  248. data/try/prototypes/pooling/pool_siege.rb +11 -11
  249. data/try/prototypes/pooling/run_stress_tests.rb +7 -7
  250. data/try/refinements/dear_json_array_methods_try.rb +53 -0
  251. data/try/refinements/dear_json_hash_methods_try.rb +54 -0
  252. data/try/refinements/logger_trace_methods_try.rb +44 -0
  253. data/try/refinements/time_literals_numeric_methods_try.rb +141 -0
  254. data/try/refinements/time_literals_string_methods_try.rb +80 -0
  255. data/try/valkey.conf +26 -0
  256. metadata +92 -52
  257. data/.rubocop_todo.yml +0 -208
  258. data/docs/connection_pooling.md +0 -192
  259. data/docs/guides/Connection-Pooling-Guide.md +0 -437
  260. data/docs/guides/Encrypted-Fields-Overview.md +0 -101
  261. data/docs/guides/Feature-System-Autoloading.md +0 -198
  262. data/docs/guides/Home.md +0 -116
  263. data/docs/guides/Relationships-Guide.md +0 -737
  264. data/docs/guides/relationships-methods.md +0 -266
  265. data/docs/reference/auditing_database_commands.rb +0 -228
  266. data/examples/permissions.rb +0 -240
  267. data/lib/familia/features/relationships/cascading.rb +0 -437
  268. data/lib/familia/features/relationships/membership.rb +0 -497
  269. data/lib/familia/features/relationships/permission_management.rb +0 -264
  270. data/lib/familia/features/relationships/querying.rb +0 -615
  271. data/lib/familia/features/relationships/redis_operations.rb +0 -274
  272. data/lib/familia/features/relationships/tracking.rb +0 -418
  273. data/lib/familia/horreum/core/connection.rb +0 -73
  274. data/lib/familia/horreum/core.rb +0 -21
  275. data/lib/familia/refinements/snake_case.rb +0 -40
  276. data/lib/familia/validation/command_recorder.rb +0 -336
  277. data/lib/familia/validation/expectations.rb +0 -519
  278. data/lib/familia/validation/validation_helpers.rb +0 -443
  279. data/lib/familia/validation/validator.rb +0 -412
  280. data/lib/familia/validation.rb +0 -140
  281. data/try/data_types/set_try.rb +0 -33
  282. data/try/features/relationships/categorical_permissions_try.rb +0 -515
  283. data/try/features/safe_dump/module_based_extensions_try.rb +0 -100
  284. data/try/features/safe_dump/safe_dump_autoloading_try.rb +0 -107
  285. data/try/validation/atomic_operations_try.rb.disabled +0 -320
  286. data/try/validation/command_validation_try.rb.disabled +0 -207
  287. data/try/validation/performance_validation_try.rb.disabled +0 -324
  288. data/try/validation/real_world_scenarios_try.rb.disabled +0 -390
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 00416beac08786c1fffd75a0c2578669c6a0d18169824ca1a23e9122018a386b
4
- data.tar.gz: c38f7bfe985a7d6151abf2ce4b6d7ca32ddb97adf8d069880f7e919662937851
3
+ metadata.gz: e760a3ff094446126c56a0c2b76fd5bed0f6ff64d8eed89580e19d98a5a9ba66
4
+ data.tar.gz: 74545b0bbb8c89b06ffd385c1448a95a7808b168686a955155a004b91160dafa
5
5
  SHA512:
6
- metadata.gz: a3d6a60c86460578567fbd6f33e96c8ae0ee2dbfc80f3ffc6f123dc6fb84c6020efd359601122e63543c0128401d235587e9770df8acbbfa1f55cb908a012e07
7
- data.tar.gz: 5062f93d7494df05a6d62dade395a0522ca8ab02afd4fdc5a00ee21db08b05ace8c3227d07739ef7cdd727fa72888ea4ec415491eb60028b25166d107d574e8e
6
+ metadata.gz: cd9cd6c374f24859279125ef05199b0dfdac51f7cccdf2bcdf0489c7cca5126ac03d7cab1d54aa8021ce38b286203212514b2b412322ea151b8957fa16c9b445
7
+ data.tar.gz: 3e44e06249e6daf715ce09b02643b8faf153c85fc2d8451d4cf56d77c5115e5e5fdb1b752acef3f1fdd46f7b7eb7f019213f22850ffe728ec51a05d98ecc5528
@@ -35,8 +35,8 @@ jobs:
35
35
  --health-retries 5
36
36
  ports:
37
37
  # https://docs.github.com/en/actions/using-containerized-services/creating-redis-service-containers#running-jobs-in-containers
38
- # Maps port 6379 on service container to the host
39
- - 6379:6379
38
+ # Maps port 6379 on service container to 2525 on the host
39
+ - 2525:6379
40
40
 
41
41
  steps:
42
42
  - uses: actions/checkout@v4
@@ -0,0 +1,138 @@
1
+ name: Code Quality
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [ main ]
6
+ push:
7
+ branches: [ main ]
8
+ workflow_dispatch:
9
+
10
+ permissions:
11
+ contents: read
12
+ pull-requests: write # Needed to post comments on PRs
13
+
14
+ jobs:
15
+ reek:
16
+ name: Reek Code Analysis
17
+ runs-on: ubuntu-24.04
18
+ timeout-minutes: 5
19
+
20
+ steps:
21
+ - name: Checkout code
22
+ uses: actions/checkout@v4
23
+
24
+ - name: Set up Ruby
25
+ uses: ruby/setup-ruby@v1
26
+ with:
27
+ ruby-version: 3.4
28
+ bundler-cache: true
29
+
30
+ - name: Configure Bundler for secure gem installation
31
+ run: |
32
+ bundle config set --local path 'vendor/bundle'
33
+ bundle config set --local deployment 'false'
34
+
35
+ - name: Install dependencies
36
+ run: bundle install
37
+
38
+ - name: Run Reek analysis
39
+ run: |
40
+ echo "=== Running Reek code analysis ==="
41
+ echo "This analysis identifies code smells and potential improvements."
42
+ echo "Results are informational and won't fail the build."
43
+ echo ""
44
+
45
+ # Run reek and capture output (don't fail on warnings)
46
+ # Use success-exit-code to prevent failures from stopping the analysis
47
+ bundle exec reek --format=text --success-exit-code 0 --failure-exit-code 0 || true
48
+
49
+ echo ""
50
+ echo "=== Reek analysis complete ==="
51
+ continue-on-error: true # Don't fail the build on code smells
52
+
53
+ - name: Generate Reek report (if analysis available)
54
+ run: |
55
+ echo "=== Generating detailed Reek report ==="
56
+
57
+ # Generate JSON report for potential future processing
58
+ bundle exec reek --format=json --success-exit-code 0 --failure-exit-code 0 > reek-report.json || true
59
+
60
+ # Display summary
61
+ if [ -s reek-report.json ]; then
62
+ echo "Reek JSON report generated: $(wc -l < reek-report.json) lines"
63
+ echo "Top code smell types found:"
64
+ jq -r '.[].smells[].smell_type' reek-report.json 2>/dev/null | sort | uniq -c | sort -rn | head -10 || echo "Unable to parse JSON report"
65
+ else
66
+ echo "No code smells detected or analysis failed"
67
+ fi
68
+ continue-on-error: true
69
+
70
+ - name: Upload Reek report as artifact
71
+ uses: actions/upload-artifact@v4
72
+ if: always()
73
+ with:
74
+ name: reek-report
75
+ path: reek-report.json
76
+ retention-days: 30
77
+
78
+ # Add other code quality checks here
79
+ additional-quality-checks:
80
+ name: Additional Quality Checks
81
+ runs-on: ubuntu-24.04
82
+ timeout-minutes: 5
83
+
84
+ steps:
85
+ - name: Checkout code
86
+ uses: actions/checkout@v4
87
+
88
+ - name: Set up Ruby
89
+ uses: ruby/setup-ruby@v1
90
+ with:
91
+ ruby-version: 3.4
92
+ bundler-cache: true
93
+
94
+ - name: Configure Bundler for secure gem installation
95
+ run: |
96
+ bundle config set --local path 'vendor/bundle'
97
+ bundle config set --local deployment 'false'
98
+
99
+ - name: Install dependencies
100
+ run: bundle install
101
+
102
+ - name: Check for TODO/FIXME comments
103
+ run: |
104
+ echo "=== Scanning for TODO/FIXME comments ==="
105
+ echo "This helps track technical debt and action items."
106
+ echo ""
107
+
108
+ # Find TODO/FIXME comments (excluding this workflow file)
109
+ find . -name "*.rb" -not -path "./vendor/*" -not -path "./tmp/*" | \
110
+ xargs grep -Hn -i -E "(TODO|FIXME|HACK|XXX|NOTE):" 2>/dev/null | \
111
+ head -20 || echo "No TODO/FIXME comments found"
112
+ continue-on-error: true
113
+
114
+ - name: Check Ruby file syntax
115
+ run: |
116
+ echo "=== Checking Ruby syntax ==="
117
+ echo "Validates that all Ruby files have correct syntax."
118
+ echo ""
119
+
120
+ find . -name "*.rb" -not -path "./vendor/*" -not -path "./tmp/*" | \
121
+ while read -r file; do
122
+ if ! ruby -c "$file" > /dev/null 2>&1; then
123
+ echo "Syntax error in: $file"
124
+ ruby -c "$file"
125
+ fi
126
+ done
127
+ continue-on-error: true
128
+
129
+ - name: Check for long lines
130
+ run: |
131
+ echo "=== Checking for long lines (>120 characters) ==="
132
+ echo "Identifies potentially hard-to-read code lines."
133
+ echo ""
134
+
135
+ find . -name "*.rb" -not -path "./vendor/*" -not -path "./tmp/*" | \
136
+ xargs grep -Hn "^.\{121,\}$" | \
137
+ head -10 || echo "No overly long lines found"
138
+ continue-on-error: true
@@ -0,0 +1,85 @@
1
+ # ..github/workflows/code-smells.yml
2
+ ---
3
+ name: Code Smells
4
+
5
+ on:
6
+ pull_request:
7
+ branches: [main]
8
+ push:
9
+ branches: [main]
10
+ workflow_dispatch:
11
+
12
+ permissions:
13
+ contents: read
14
+ pull-requests: write # Needed to post comments on PRs
15
+
16
+ jobs:
17
+ reek:
18
+ name: Reek Code Analysis
19
+ runs-on: ubuntu-24.04
20
+ timeout-minutes: 5
21
+
22
+ steps:
23
+ - name: Checkout code
24
+ uses: actions/checkout@v4
25
+
26
+ - name: Set up Ruby
27
+ uses: ruby/setup-ruby@v1
28
+ with:
29
+ ruby-version: 3.4
30
+ bundler-cache: true
31
+
32
+ - name: Configure Bundler for secure gem installation
33
+ run: |
34
+ bundle config set --local path 'vendor/bundle'
35
+ bundle config set --local deployment 'false'
36
+
37
+ - name: Install dependencies
38
+ run: bundle install --jobs 4 --retry 3
39
+
40
+ - name: Run Reek analysis
41
+ run: |
42
+ echo "=== Running Reek code analysis ==="
43
+ echo "This analysis identifies code smells and potential improvements."
44
+ echo "Results are informational and won't fail the build."
45
+ echo ""
46
+
47
+ # Run reek and capture output (don't fail on warnings)
48
+ # Use success-exit-code to prevent failures from stopping the analysis
49
+ bundle exec reek --format=text --success-exit-code 0 --failure-exit-code 0 || true
50
+
51
+ echo ""
52
+ echo "=== Reek analysis complete ==="
53
+ continue-on-error: true # Don't fail the build on code smells
54
+
55
+ - name: Generate Reek report (if analysis available)
56
+ run: |
57
+ echo "=== Generating detailed Reek report ==="
58
+
59
+ # Generate JSON report for potential future processing
60
+ bundle exec reek --format=json --success-exit-code 0 --failure-exit-code 0 > reek-report.json || true
61
+
62
+ # If no JSON was generated, create an empty valid JSON array
63
+ if [ ! -s reek-report.json ]; then
64
+ echo "[]" > reek-report.json
65
+ echo "No code smells detected - created empty report"
66
+ else
67
+ echo "Reek JSON report generated: $(wc -l < reek-report.json) lines"
68
+ echo "Top code smell types found:"
69
+ jq -r '.[].smells[].smell_type' reek-report.json 2>/dev/null | sort | uniq -c | sort -rn | head -10 || echo "Unable to parse JSON report"
70
+ fi
71
+
72
+ # Also generate a human-readable HTML report for easier viewing
73
+ bundle exec reek --format=html --success-exit-code 0 --failure-exit-code 0 > reek-report.html || echo "<!-- No code smells detected -->" > reek-report.html
74
+ continue-on-error: true
75
+
76
+ - name: Upload Reek report as artifact
77
+ uses: actions/upload-artifact@v4
78
+ if: always()
79
+ with:
80
+ name: reek-report
81
+ path: |
82
+ reek-report.json
83
+ reek-report.html
84
+ if-no-files-found: ignore
85
+ retention-days: 30
@@ -1,3 +1,5 @@
1
+ # .github/workflows/docs.yml
2
+ ---
1
3
  name: Build and Publish YARD Documentation
2
4
 
3
5
  on:
@@ -7,9 +9,14 @@ on:
7
9
  workflow_dispatch:
8
10
  inputs:
9
11
  reason:
10
- description: 'Reason for manual documentation build'
12
+ description: "Reason for manual documentation build"
11
13
  required: false
12
- default: 'Manual documentation update'
14
+ default: "Manual documentation update"
15
+ debug_enabled:
16
+ type: boolean
17
+ description: "Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)"
18
+ required: false
19
+ default: false
13
20
 
14
21
  permissions:
15
22
  contents: read
@@ -33,23 +40,39 @@ jobs:
33
40
  - name: Set up Ruby
34
41
  uses: ruby/setup-ruby@v1
35
42
  with:
36
- ruby-version: '3.4'
43
+ ruby-version: "3.4"
37
44
  bundler-cache: true
38
45
 
39
46
  - name: Install dependencies
40
47
  run: bundle install
41
48
 
49
+ - name: Setup tmate session
50
+ uses: mxschmitt/action-tmate@7b6a61a73bbb9793cb80ad69b8dd8ac19261834c # v3
51
+ if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}
52
+ with:
53
+ detached: true
54
+
42
55
  - name: Build YARD documentation
43
56
  run: |
44
- bundle exec yard doc --output-dir ./doc
45
- # Ensure doc directory exists and create .nojekyll file to prevent GitHub Pages Jekyll processing
46
- mkdir -p ./doc
47
- touch ./doc/.nojekyll
57
+ # Generate docs with maximum volume
58
+ bundle exec yard doc --debug --backtrace 2>&1 | tee yard_debug.log
59
+
60
+ # Display the last 10 lines of the log file
61
+ tail -n 10 yard_debug.log
62
+
63
+ # Search for specific error messages in the log file
64
+ grep -A 5 -B 5 "Exception occurred" yard_debug.log || echo "No exceptions found (good!)"
65
+ grep -A 5 -B 5 "Cannot resolve link" yard_debug.log || echo "No unresolved links found (good!)"
66
+
67
+ # Ensure public directory exists and create .nojekyll file to
68
+ # prevent GitHub Pages Jekyll processing
69
+ mkdir -p ./public
70
+ touch ./public/.nojekyll
48
71
 
49
72
  - name: Upload documentation artifacts
50
73
  uses: actions/upload-pages-artifact@v3
51
74
  with:
52
- path: ./doc
75
+ path: ./public
53
76
 
54
77
  deploy:
55
78
  environment:
data/.gitignore CHANGED
@@ -14,12 +14,14 @@
14
14
  *.log
15
15
  *.txt
16
16
  .ruby-version
17
+ dump.rdb
17
18
  appendonlydir
19
+ data
18
20
  log
19
21
  tmp
20
22
  vendor
21
23
  *.gem
22
- doc/
24
+ public/
23
25
 
24
26
  # Ignore WIP or temp dev files with uppercase names
25
27
  [A-Z]*.md
@@ -50,7 +50,6 @@ repos:
50
50
  - id: trailing-whitespace
51
51
  - id: end-of-file-fixer
52
52
  - id: check-yaml
53
- - id: detect-private-key
54
53
  - id: mixed-line-ending
55
54
  - id: check-added-large-files
56
55
  args: ["--maxkb=1000"]
@@ -59,6 +58,13 @@ repos:
59
58
  - id: check-merge-conflict
60
59
  - id: forbid-submodules
61
60
 
61
+ - repo: https://github.com/thoughtworks/talisman
62
+ rev: v1.32.2
63
+ hooks:
64
+ - id: talisman-commit
65
+ env:
66
+ TALISMAN_SCAN_MODE: CI
67
+
62
68
  - repo: https://github.com/avilaton/add-msg-issue-prefix-hook
63
69
  rev: v0.0.11
64
70
  hooks:
data/.reek.yml ADDED
@@ -0,0 +1,98 @@
1
+ # .reek.yml
2
+ # Reek configuration for Familia
3
+ #
4
+ # Basic commands:
5
+ # bundle exec reek # Analyze all Ruby files
6
+ # bundle exec reek lib/ # Analyze specific directory
7
+ # bundle exec reek lib/familia/horreum.rb # Analyze specific file
8
+ # bundle exec reek --help # Show all options
9
+ # bundle exec reek --docs # Open documentation
10
+ #
11
+ # Advanced usage:
12
+ # bundle exec reek --format=html > report.html # Generate HTML report
13
+ # bundle exec reek --format=json # JSON output for CI
14
+ # bundle exec reek --config .reek.yml # Use specific config
15
+ # bundle exec reek --show-docs IrresponsibleModule # Explain specific smell
16
+ # bundle exec reek --failure-exit-code 1 # Exit with error on smells (for CI)
17
+
18
+ ---
19
+ detectors:
20
+ # Disable some detectors for initial adoption
21
+ # You can gradually enable these as you clean up the codebase
22
+
23
+ # Class/Module Structure
24
+ IrresponsibleModule:
25
+ enabled: false # Modules without documentation - start with this disabled
26
+
27
+ # Method Complexity
28
+ TooManyStatements:
29
+ enabled: true
30
+ max_statements: 15 # Default is 5, relaxed for initial adoption
31
+
32
+ TooManyMethods:
33
+ enabled: true
34
+ max_methods: 25 # Default is 15, relaxed for ORMs which often have many methods
35
+
36
+ LongParameterList:
37
+ enabled: true
38
+ max_params: 4 # Default is 3, slightly relaxed
39
+
40
+ # Data Classes and Feature Envy
41
+ DataClump:
42
+ enabled: true
43
+
44
+ FeatureEnvy:
45
+ enabled: true
46
+
47
+ # Control Structure
48
+ NestedIterators:
49
+ enabled: true
50
+ max_allowed_nesting: 2 # Default is 1, relaxed for data processing
51
+
52
+ # Variable and Constant Usage
53
+ UnusedParameters:
54
+ enabled: true
55
+
56
+ InstanceVariableAssumption:
57
+ enabled: true
58
+
59
+ # Naming
60
+ UncommunicativeParameterName:
61
+ enabled: true
62
+ reject:
63
+ - '/^.$/' # Single letter names
64
+ - '/[0-9]$/' # Names ending in numbers
65
+ - '/^_/' # Names starting with underscore (common Ruby pattern)
66
+ accept: []
67
+
68
+ UncommunicativeVariableName:
69
+ enabled: true
70
+ reject:
71
+ - '/^.$/' # Single letter names
72
+ - '/[0-9]$/' # Names ending in numbers
73
+ accept:
74
+ - e # Exception variable
75
+ - id # Common identifier
76
+ - db # Database connection
77
+ - op # Operation
78
+ - io # Input/output
79
+
80
+ UncommunicativeMethodName:
81
+ enabled: true
82
+ reject:
83
+ - '/^.$/' # Single letter method names
84
+ - '/[0-9]$/' # Methods ending in numbers
85
+ accept:
86
+ - "<<" # Common Ruby operator overload
87
+
88
+ # Directory and file exclusions
89
+ exclude_paths:
90
+ - "vendor/**/*.rb"
91
+ - "tmp/**/*.rb"
92
+ - "try/**/*.rb" # Test files using tryouts framework
93
+ - "examples/**/*.rb" # Example code files
94
+ - "bin/*" # Executable scripts
95
+ - "*.gemspec" # Gem specification files
96
+
97
+ # Note: For limiting warnings output, use CLI: bundle exec reek | head -50
98
+ # Note: For failure exit codes, use CLI: bundle exec reek --failure-exit-code 1
data/.rubocop.yml CHANGED
@@ -16,7 +16,6 @@
16
16
  # How to resolve "RuboCop version incompatibility found":
17
17
  # `rubocop --stop-server`
18
18
  #
19
- inherit_from: .rubocop_todo.yml
20
19
 
21
20
  plugins:
22
21
  - rubocop-performance
@@ -28,11 +27,9 @@ AllCops:
28
27
  MaxFilesInCache: 100
29
28
  TargetRubyVersion: 3.4
30
29
  Exclude:
31
- - "migrate/**/*.rb"
32
- - "migrate/*.rb"
33
- - "try/**/*"
34
- - "try/*.rb"
35
- - "vendor/**/*"
30
+ - "rspec/**/*.rb"
31
+ - "tmp/**/*.rb"
32
+ - "try/**/*.rb"
36
33
 
37
34
  #
38
35
  # Trailing commas
@@ -46,6 +43,7 @@ Style/TrailingCommaInArrayLiteral:
46
43
 
47
44
  Style/TrailingCommaInArguments:
48
45
  Enabled: true
46
+ EnforcedStyleForMultiline: comma
49
47
 
50
48
  Style/TrailingCommaInBlockArgs:
51
49
  Enabled: true
@@ -62,30 +60,59 @@ Gemspec/DevelopmentDependencies:
62
60
  Layout/HashAlignment:
63
61
  Enabled: false
64
62
 
63
+ # Format with consistent indentation levels rather than vertical dot alignment.
64
+ Layout/MultilineMethodCallIndentation:
65
+ Enabled: false
66
+ EnforcedStyle: indented
67
+ IndentationWidth: 2
68
+
69
+ Layout/IndentationWidth:
70
+ Width: 2
71
+
72
+ Layout/ArgumentAlignment:
73
+ Enabled: false
74
+
75
+ Layout/DotPosition:
76
+ EnforcedStyle: leading # or 'trailing'
77
+
65
78
  Lint/Void:
66
79
  Enabled: false
67
80
 
81
+ Layout/MultilineAssignmentLayout:
82
+ Enabled: true
83
+ EnforcedStyle: same_line
84
+
85
+ Layout/EndAlignment:
86
+ EnforcedStyleAlignWith: start_of_line
87
+
88
+ Layout/FirstArgumentIndentation:
89
+ EnforcedStyle: consistent
90
+
68
91
  Metrics/AbcSize:
69
92
  Enabled: false
70
93
  Max: 20
71
94
 
72
95
  Metrics/ClassLength:
73
96
  Enabled: true
74
- Max: 200
97
+ Max: 350
75
98
 
76
99
  Metrics/CyclomaticComplexity:
77
100
  Enabled: false
78
101
 
79
102
  Metrics/MethodLength:
80
103
  Enabled: true
81
- Max: 40
104
+ Max: 50
82
105
  CountAsOne: ["method_call"]
83
106
 
84
107
  Metrics/ModuleLength:
85
108
  Enabled: true
86
- Max: 250
109
+ Max: 350
87
110
  CountAsOne: ["method_call"]
88
111
 
112
+ Metrics/ParameterLists:
113
+ Enabled: true
114
+ Max: 6
115
+
89
116
  Performance/Size:
90
117
  Enabled: true
91
118
  Exclude:
@@ -97,8 +124,25 @@ Style/NegatedIfElseCondition:
97
124
  Naming/AsciiIdentifiers:
98
125
  Enabled: false
99
126
 
100
- Style/FrozenStringLiteralComment:
127
+ Naming/PredicateMethod:
101
128
  Enabled: false
102
129
 
130
+ Style/StringLiterals:
131
+ Enabled: true
132
+ EnforcedStyle: single_quotes
133
+
134
+ Style/FrozenStringLiteralComment:
135
+ Enabled: true
136
+ EnforcedStyle: never
137
+
103
138
  Naming/MemoizedInstanceVariableName:
104
139
  Enabled: false
140
+
141
+ ThreadSafety/ClassAndModuleAttributes:
142
+ Enabled: false
143
+
144
+ ThreadSafety/ClassInstanceVariable:
145
+ Enabled: false
146
+
147
+ ThreadSafety/MutableClassInstanceVariable:
148
+ Enabled: false
data/.talismanrc ADDED
@@ -0,0 +1,9 @@
1
+ # .talismanrc
2
+ #
3
+ # @see:
4
+ # https://thoughtworks.github.io/talisman/docs/configuring-talisman/ignoring/
5
+ # https://thoughtworks.github.io/talisman/docs/configuring-talisman/severity-threshold/
6
+ #
7
+ threshold: medium
8
+ fileignoreconfig: []
9
+ version: ""
data/.yardopts CHANGED
@@ -1,30 +1,35 @@
1
1
  --readme README.md
2
2
  --title "Familia Ruby Library Documentation"
3
- --markup markdown
4
- --markup-provider kramdown
5
3
  --protected
6
4
  --no-private
5
+ --verbose
6
+ --charset utf-8
7
+ --markup markdown
8
+ --markup-provider redcarpet
9
+ --output-dir public
7
10
  --embed-mixin ClassMethods
11
+ --embed-mixin InstanceMethods
8
12
  --embed-mixin Features
9
13
  --tag feature:"Feature"
10
14
  --tag since:"Since Version"
11
- --tag example:"Example Usage"
12
15
  --tag note:"Note"
13
16
  --tag warning:"Warning"
14
17
  --tag deprecated:"Deprecated"
18
+ --tag abstract:"Abstract"
19
+ --tag security:"Security"
15
20
  --hide-tag nodoc
16
21
  --exclude lib/familia/version.rb
22
+ --readme README.md
23
+ --no-stats
24
+ --no-save
25
+ --no-cache
17
26
  lib/**/*.rb
18
27
  -
19
- CHANGELOG.md
28
+ README.md
29
+ CHANGELOG.rst
20
30
  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
31
+ docs/guides/*
32
+ docs/reference/*
33
+ docs/migrating/*.md
34
+ docs/overview.md
30
35
  examples/*.rb