foobara 0.0.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.
Files changed (359) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +5 -0
  3. data/.rubocop.yml +20 -0
  4. data/.ruby-version +1 -0
  5. data/CHANGELOG.md +10 -0
  6. data/DECISION_LOG.md +220 -0
  7. data/Guardfile +9 -0
  8. data/LICENSE-AGPL.txt +666 -0
  9. data/LICENSE.txt +4 -0
  10. data/README.md +50 -0
  11. data/Rakefile +10 -0
  12. data/concepts.md +153 -0
  13. data/projects/builtin_types/lib/foobara/builtin_types.rb +67 -0
  14. data/projects/builtin_types/src/README.md +140 -0
  15. data/projects/builtin_types/src/array/casters/arrayable.rb +22 -0
  16. data/projects/builtin_types/src/array/supported_processors/element_type_declaration.rb +41 -0
  17. data/projects/builtin_types/src/array/supported_validators/size.rb +43 -0
  18. data/projects/builtin_types/src/associative_array/casters/array.rb +22 -0
  19. data/projects/builtin_types/src/associative_array/supported_processors/key_type_declaration.rb +44 -0
  20. data/projects/builtin_types/src/associative_array/supported_processors/value_type_declaration.rb +44 -0
  21. data/projects/builtin_types/src/atomic_duck.rb +6 -0
  22. data/projects/builtin_types/src/attributes/casters/array.rb +33 -0
  23. data/projects/builtin_types/src/attributes/casters/hash.rb +28 -0
  24. data/projects/builtin_types/src/attributes/supported_processors/element_type_declarations.rb +89 -0
  25. data/projects/builtin_types/src/attributes/supported_transformers/defaults/type_declaration_extension/extend_attributes_type_declaration/desugarizers/move_defaults_from_element_types_to_root.rb +40 -0
  26. data/projects/builtin_types/src/attributes/supported_transformers/defaults/type_declaration_extension/extend_attributes_type_declaration/desugarizers/symbolize_defaults.rb +31 -0
  27. data/projects/builtin_types/src/attributes/supported_transformers/defaults/type_declaration_extension/extend_attributes_type_declaration/type_declaration_validators/hash_with_symbolic_keys.rb +37 -0
  28. data/projects/builtin_types/src/attributes/supported_transformers/defaults/type_declaration_extension/extend_attributes_type_declaration/type_declaration_validators/valid_attribute_names.rb +60 -0
  29. data/projects/builtin_types/src/attributes/supported_transformers/defaults.rb +41 -0
  30. data/projects/builtin_types/src/attributes/supported_validators/required/type_declaration_extension/extend_attributes_type_declaration/desugarizers/move_required_from_element_types_to_root.rb +55 -0
  31. data/projects/builtin_types/src/attributes/supported_validators/required/type_declaration_extension/extend_attributes_type_declaration/type_declaration_validators/array_of_symbols.rb +47 -0
  32. data/projects/builtin_types/src/attributes/supported_validators/required/type_declaration_extension/extend_attributes_type_declaration/type_declaration_validators/array_with_valid_attribute_names.rb +54 -0
  33. data/projects/builtin_types/src/attributes/supported_validators/required.rb +51 -0
  34. data/projects/builtin_types/src/big_decimal/casters/integer.rb +21 -0
  35. data/projects/builtin_types/src/big_decimal/casters/string.rb +24 -0
  36. data/projects/builtin_types/src/boolean/casters/numeric.rb +21 -0
  37. data/projects/builtin_types/src/boolean/casters/string_or_symbol.rb +27 -0
  38. data/projects/builtin_types/src/builtin_types.rb +189 -0
  39. data/projects/builtin_types/src/date/casters/hash.rb +23 -0
  40. data/projects/builtin_types/src/date/casters/string.rb +40 -0
  41. data/projects/builtin_types/src/datetime/casters/date.rb +21 -0
  42. data/projects/builtin_types/src/datetime/casters/hash.rb +77 -0
  43. data/projects/builtin_types/src/datetime/casters/seconds_since_epoch.rb +21 -0
  44. data/projects/builtin_types/src/datetime/casters/string.rb +31 -0
  45. data/projects/builtin_types/src/duck/supported_casters/allow_nil.rb +38 -0
  46. data/projects/builtin_types/src/duck/supported_validators/instance_of/type_declaration_extension/extend_registered_type_declaration/desugarizers/class_desugarizer.rb +29 -0
  47. data/projects/builtin_types/src/duck/supported_validators/instance_of/type_declaration_extension/extend_registered_type_declaration/desugarizers/instance_of_class_desugarizer.rb +31 -0
  48. data/projects/builtin_types/src/duck/supported_validators/instance_of/type_declaration_extension/extend_registered_type_declaration/desugarizers/instance_of_symbol_desugarizer.rb +31 -0
  49. data/projects/builtin_types/src/duck/supported_validators/instance_of/type_declaration_extension/extend_registered_type_declaration/type_declaration_validators/is_valid_class.rb +43 -0
  50. data/projects/builtin_types/src/duck/supported_validators/instance_of.rb +42 -0
  51. data/projects/builtin_types/src/duck/supported_validators/one_of/type_declaration_extension/extend_registered_type_declaration/desugarizers/cast_one_of.rb +37 -0
  52. data/projects/builtin_types/src/duck/supported_validators/one_of/type_declaration_extension/extend_registered_type_declaration/desugarizers/module_desugarizer.rb +41 -0
  53. data/projects/builtin_types/src/duck/supported_validators/one_of.rb +41 -0
  54. data/projects/builtin_types/src/duck.rb +6 -0
  55. data/projects/builtin_types/src/duckture.rb +6 -0
  56. data/projects/builtin_types/src/email/transformers/downcase.rb +15 -0
  57. data/projects/builtin_types/src/email/validator_base.rb +94 -0
  58. data/projects/builtin_types/src/float/casters/integer.rb +21 -0
  59. data/projects/builtin_types/src/float/casters/string.rb +24 -0
  60. data/projects/builtin_types/src/integer/casters/string.rb +23 -0
  61. data/projects/builtin_types/src/number/supported_validators/max.rb +41 -0
  62. data/projects/builtin_types/src/number/supported_validators/min.rb +41 -0
  63. data/projects/builtin_types/src/string/casters/numeric.rb +21 -0
  64. data/projects/builtin_types/src/string/casters/symbol.rb +21 -0
  65. data/projects/builtin_types/src/string/supported_transformers/downcase.rb +11 -0
  66. data/projects/builtin_types/src/string/supported_validators/matches.rb +41 -0
  67. data/projects/builtin_types/src/string/supported_validators/max_length.rb +37 -0
  68. data/projects/builtin_types/src/symbol/casters/string.rb +21 -0
  69. data/projects/builtin_types/src/tuple/supported_processors/element_type_declarations/type_declaration_extension/extend_tuple_type_declaration/desugarizers/set_size.rb +32 -0
  70. data/projects/builtin_types/src/tuple/supported_processors/element_type_declarations/type_declaration_extension/extend_tuple_type_declaration/type_declaration_validators/size_matches.rb +50 -0
  71. data/projects/builtin_types/src/tuple/supported_processors/element_type_declarations.rb +59 -0
  72. data/projects/callback/lib/foobara/callback.rb +1 -0
  73. data/projects/callback/src/block/after.rb +10 -0
  74. data/projects/callback/src/block/around.rb +10 -0
  75. data/projects/callback/src/block/before.rb +10 -0
  76. data/projects/callback/src/block/concerns/block_parameter_not_allowed.rb +21 -0
  77. data/projects/callback/src/block/concerns/block_parameter_required.rb +21 -0
  78. data/projects/callback/src/block/concerns/keyword_argumentable_block.rb +31 -0
  79. data/projects/callback/src/block/concerns/single_argument_block.rb +22 -0
  80. data/projects/callback/src/block/concerns/type.rb +17 -0
  81. data/projects/callback/src/block/error.rb +10 -0
  82. data/projects/callback/src/block.rb +83 -0
  83. data/projects/callback/src/registry/base.rb +90 -0
  84. data/projects/callback/src/registry/chained_conditioned.rb +24 -0
  85. data/projects/callback/src/registry/chained_multiple_action.rb +24 -0
  86. data/projects/callback/src/registry/conditioned.rb +101 -0
  87. data/projects/callback/src/registry/multiple_action.rb +110 -0
  88. data/projects/callback/src/registry/single_action.rb +15 -0
  89. data/projects/callback/src/runner.rb +89 -0
  90. data/projects/callback/src/set.rb +56 -0
  91. data/projects/command/lib/foobara/command.rb +9 -0
  92. data/projects/command/src/command/entity_helpers.rb +145 -0
  93. data/projects/command/src/command.rb +36 -0
  94. data/projects/command/src/concerns/callbacks.rb +93 -0
  95. data/projects/command/src/concerns/description.rb +23 -0
  96. data/projects/command/src/concerns/domain_mappers.rb +35 -0
  97. data/projects/command/src/concerns/entities.rb +88 -0
  98. data/projects/command/src/concerns/errors.rb +181 -0
  99. data/projects/command/src/concerns/errors_type.rb +124 -0
  100. data/projects/command/src/concerns/inputs.rb +59 -0
  101. data/projects/command/src/concerns/inputs_type.rb +58 -0
  102. data/projects/command/src/concerns/namespace.rb +49 -0
  103. data/projects/command/src/concerns/reflection.rb +137 -0
  104. data/projects/command/src/concerns/result.rb +25 -0
  105. data/projects/command/src/concerns/result_type.rb +29 -0
  106. data/projects/command/src/concerns/runtime.rb +119 -0
  107. data/projects/command/src/concerns/state_machine.rb +12 -0
  108. data/projects/command/src/concerns/subcommands.rb +102 -0
  109. data/projects/command/src/concerns/transactions.rb +81 -0
  110. data/projects/command/src/state_machine.rb +57 -0
  111. data/projects/command/src/transformed_command.rb +459 -0
  112. data/projects/command_connectors/lib/foobara/command_connectors.rb +12 -0
  113. data/projects/command_connectors/src/command_connector.rb +401 -0
  114. data/projects/command_connectors/src/command_registry/allowed_rule.rb +29 -0
  115. data/projects/command_connectors/src/command_registry/exposed_command.rb +140 -0
  116. data/projects/command_connectors/src/command_registry/exposed_domain.rb +30 -0
  117. data/projects/command_connectors/src/command_registry/exposed_organization.rb +30 -0
  118. data/projects/command_connectors/src/command_registry.rb +257 -0
  119. data/projects/command_connectors/src/commands/describe.rb +36 -0
  120. data/projects/command_connectors/src/commands/list_commands.rb +51 -0
  121. data/projects/command_connectors/src/commands/ping.rb +21 -0
  122. data/projects/command_connectors/src/commands/query_git_commit_info.rb +81 -0
  123. data/projects/command_connectors/src/request.rb +99 -0
  124. data/projects/command_connectors/src/response.rb +17 -0
  125. data/projects/command_connectors/src/serializer.rb +25 -0
  126. data/projects/command_connectors/src/serializers/aggregate_serializer.rb +32 -0
  127. data/projects/command_connectors/src/serializers/atomic_serializer.rb +25 -0
  128. data/projects/command_connectors/src/serializers/entities_to_primary_keys_serializer.rb +28 -0
  129. data/projects/command_connectors/src/serializers/errors_serializer.rb +18 -0
  130. data/projects/command_connectors/src/serializers/json_serializer.rb +20 -0
  131. data/projects/command_connectors/src/serializers/noop_serializer.rb +20 -0
  132. data/projects/command_connectors/src/serializers/record_store_serializer.rb +31 -0
  133. data/projects/command_connectors/src/serializers/success_serializer.rb +14 -0
  134. data/projects/command_connectors/src/serializers/yaml_serializer.rb +20 -0
  135. data/projects/command_connectors/src/transformers/auth_errors_transformer.rb +35 -0
  136. data/projects/command_connectors/src/transformers/load_aggregates_pre_commit_transformer.rb +36 -0
  137. data/projects/command_connectors_http/lib/foobara/command_connectors_http.rb +6 -0
  138. data/projects/command_connectors_http/src/http/commands/get_options.rb +16 -0
  139. data/projects/command_connectors_http/src/http/commands/help/presenter/command.rb +14 -0
  140. data/projects/command_connectors_http/src/http/commands/help/presenter/domain.rb +14 -0
  141. data/projects/command_connectors_http/src/http/commands/help/presenter/entity.rb +14 -0
  142. data/projects/command_connectors_http/src/http/commands/help/presenter/error.rb +14 -0
  143. data/projects/command_connectors_http/src/http/commands/help/presenter/model.rb +14 -0
  144. data/projects/command_connectors_http/src/http/commands/help/presenter/organization.rb +14 -0
  145. data/projects/command_connectors_http/src/http/commands/help/presenter/processor.rb +14 -0
  146. data/projects/command_connectors_http/src/http/commands/help/presenter/processor_class.rb +14 -0
  147. data/projects/command_connectors_http/src/http/commands/help/presenter/root.rb +14 -0
  148. data/projects/command_connectors_http/src/http/commands/help/presenter/type.rb +14 -0
  149. data/projects/command_connectors_http/src/http/commands/help/presenter.rb +162 -0
  150. data/projects/command_connectors_http/src/http/commands/help/templates/command.html.erb +11 -0
  151. data/projects/command_connectors_http/src/http/commands/help/templates/domain.html.erb +1 -0
  152. data/projects/command_connectors_http/src/http/commands/help/templates/entity.html.erb +1 -0
  153. data/projects/command_connectors_http/src/http/commands/help/templates/error.html.erb +1 -0
  154. data/projects/command_connectors_http/src/http/commands/help/templates/model.html.erb +1 -0
  155. data/projects/command_connectors_http/src/http/commands/help/templates/organization.html.erb +1 -0
  156. data/projects/command_connectors_http/src/http/commands/help/templates/processor.html.erb +1 -0
  157. data/projects/command_connectors_http/src/http/commands/help/templates/processor_class.html.erb +1 -0
  158. data/projects/command_connectors_http/src/http/commands/help/templates/root.html.erb +3 -0
  159. data/projects/command_connectors_http/src/http/commands/help/templates/type.html.erb +1 -0
  160. data/projects/command_connectors_http/src/http/commands/help.rb +98 -0
  161. data/projects/command_connectors_http/src/http/request.rb +98 -0
  162. data/projects/command_connectors_http/src/http/response.rb +14 -0
  163. data/projects/command_connectors_http/src/http.rb +84 -0
  164. data/projects/common/lib/foobara/common.rb +11 -0
  165. data/projects/common/src/data_path.rb +272 -0
  166. data/projects/common/src/error.rb +215 -0
  167. data/projects/common/src/error_collection.rb +97 -0
  168. data/projects/common/src/error_key.rb +168 -0
  169. data/projects/common/src/outcome.rb +101 -0
  170. data/projects/common/src/possible_error.rb +80 -0
  171. data/projects/common/src/runtime_error.rb +24 -0
  172. data/projects/concerns/lib/foobara/concerns.rb +1 -0
  173. data/projects/concerns/src/concern.rb +93 -0
  174. data/projects/delegate/lib/foobara/delegate.rb +1 -0
  175. data/projects/delegate/src/extensions/module.rb +12 -0
  176. data/projects/domain/lib/foobara/domain.rb +25 -0
  177. data/projects/domain/src/domain.rb +65 -0
  178. data/projects/domain/src/domain_mapper/registry.rb +47 -0
  179. data/projects/domain/src/domain_mapper.rb +162 -0
  180. data/projects/domain/src/domain_module_extension.rb +510 -0
  181. data/projects/domain/src/extensions/foobara.rb +69 -0
  182. data/projects/domain/src/global_domain.rb +14 -0
  183. data/projects/domain/src/global_organization.rb +12 -0
  184. data/projects/domain/src/is_manifestable.rb +68 -0
  185. data/projects/domain/src/manifestable.rb +12 -0
  186. data/projects/domain/src/module_extension.rb +122 -0
  187. data/projects/domain/src/organization.rb +52 -0
  188. data/projects/domain/src/organization_module_extension.rb +50 -0
  189. data/projects/entity/lib/foobara/entity.rb +27 -0
  190. data/projects/entity/src/concerns/associations.rb +241 -0
  191. data/projects/entity/src/concerns/attributes.rb +170 -0
  192. data/projects/entity/src/concerns/callbacks.rb +97 -0
  193. data/projects/entity/src/concerns/initialization.rb +127 -0
  194. data/projects/entity/src/concerns/persistence.rb +142 -0
  195. data/projects/entity/src/concerns/primary_key.rb +43 -0
  196. data/projects/entity/src/concerns/queries.rb +96 -0
  197. data/projects/entity/src/concerns/reflection.rb +51 -0
  198. data/projects/entity/src/concerns/transactions.rb +31 -0
  199. data/projects/entity/src/concerns/types.rb +31 -0
  200. data/projects/entity/src/entity.rb +61 -0
  201. data/projects/entity/src/extensions/builtin_types/entity/casters/hash.rb +33 -0
  202. data/projects/entity/src/extensions/builtin_types/entity/validators/attributes_declaration.rb +32 -0
  203. data/projects/entity/src/extensions/builtin_types/entity.rb +6 -0
  204. data/projects/entity/src/extensions/type_declarations/handlers/extend_entity_type_declaration/attributes_handler_desugarizer.rb +14 -0
  205. data/projects/entity/src/extensions/type_declarations/handlers/extend_entity_type_declaration/hash_desugarizer.rb +43 -0
  206. data/projects/entity/src/extensions/type_declarations/handlers/extend_entity_type_declaration/model_class_desugarizer.rb +21 -0
  207. data/projects/entity/src/extensions/type_declarations/handlers/extend_entity_type_declaration/primary_key_desugarizer.rb +19 -0
  208. data/projects/entity/src/extensions/type_declarations/handlers/extend_entity_type_declaration/to_type_transformer.rb +64 -0
  209. data/projects/entity/src/extensions/type_declarations/handlers/extend_entity_type_declaration/validate_primary_key_is_symbol.rb +35 -0
  210. data/projects/entity/src/extensions/type_declarations/handlers/extend_entity_type_declaration/validate_primary_key_present.rb +27 -0
  211. data/projects/entity/src/extensions/type_declarations/handlers/extend_entity_type_declaration/validate_primary_key_references_attribute.rb +36 -0
  212. data/projects/entity/src/extensions/type_declarations/handlers/extend_entity_type_declaration.rb +11 -0
  213. data/projects/entity/src/new_prepend.rb +21 -0
  214. data/projects/entity/src/not_found_error.rb +72 -0
  215. data/projects/enumerated/lib/foobara/enumerated.rb +1 -0
  216. data/projects/enumerated/src/accessors.rb +61 -0
  217. data/projects/enumerated/src/values.rb +121 -0
  218. data/projects/foobara/lib/foobara/all.rb +44 -0
  219. data/projects/in_memory_crud_driver/lib/foobara/in_memory_crud_driver.rb +3 -0
  220. data/projects/in_memory_crud_driver/src/in_memory.rb +10 -0
  221. data/projects/in_memory_crud_driver_minimal/lib/foobara/in_memory_crud_driver_minimal.rb +1 -0
  222. data/projects/in_memory_crud_driver_minimal/src/in_memory_minimal.rb +113 -0
  223. data/projects/manifest/lib/foobara/manifest.rb +4 -0
  224. data/projects/manifest/src/foobara/manifest/array.rb +13 -0
  225. data/projects/manifest/src/foobara/manifest/attributes.rb +40 -0
  226. data/projects/manifest/src/foobara/manifest/base_manifest.rb +161 -0
  227. data/projects/manifest/src/foobara/manifest/command.rb +59 -0
  228. data/projects/manifest/src/foobara/manifest/domain.rb +43 -0
  229. data/projects/manifest/src/foobara/manifest/entity.rb +35 -0
  230. data/projects/manifest/src/foobara/manifest/error.rb +33 -0
  231. data/projects/manifest/src/foobara/manifest/model.rb +43 -0
  232. data/projects/manifest/src/foobara/manifest/organization.rb +45 -0
  233. data/projects/manifest/src/foobara/manifest/possible_error.rb +30 -0
  234. data/projects/manifest/src/foobara/manifest/processor.rb +11 -0
  235. data/projects/manifest/src/foobara/manifest/processor_class.rb +11 -0
  236. data/projects/manifest/src/foobara/manifest/root_manifest.rb +112 -0
  237. data/projects/manifest/src/foobara/manifest/type.rb +86 -0
  238. data/projects/manifest/src/foobara/manifest/type_declaration.rb +117 -0
  239. data/projects/model/lib/foobara/model.rb +23 -0
  240. data/projects/model/src/concerns/reflection.rb +22 -0
  241. data/projects/model/src/concerns/types.rb +104 -0
  242. data/projects/model/src/extensions/builtin_types/model/casters/hash.rb +23 -0
  243. data/projects/model/src/extensions/builtin_types/model/transformers/mutable.rb +26 -0
  244. data/projects/model/src/extensions/builtin_types/model/validators/attributes_declaration.rb +33 -0
  245. data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration/attributes_handler_desugarizer.rb +24 -0
  246. data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration/hash_desugarizer.rb +32 -0
  247. data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration/model_class_desugarizer.rb +119 -0
  248. data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration/to_type_transformer.rb +57 -0
  249. data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration.rb +21 -0
  250. data/projects/model/src/extensions/type_declarations/handlers/extend_registered_model_type_declaration/hash_desugarizer.rb +37 -0
  251. data/projects/model/src/extensions/type_declarations/handlers/extend_registered_model_type_declaration/model_class_type_desugarizer.rb +25 -0
  252. data/projects/model/src/extensions/type_declarations/handlers/extend_registered_model_type_declaration/mutable_validator.rb +46 -0
  253. data/projects/model/src/extensions/type_declarations/handlers/extend_registered_model_type_declaration/normalize_mutable_attributes_desugarizer.rb +28 -0
  254. data/projects/model/src/extensions/type_declarations/handlers/extend_registered_model_type_declaration/to_type_transformer.rb +27 -0
  255. data/projects/model/src/extensions/type_declarations/handlers/extend_registered_model_type_declaration.rb +31 -0
  256. data/projects/model/src/extensions/type_declarations/handlers/registered_type_declaration/model_class_desugarizer.rb +23 -0
  257. data/projects/model/src/model.rb +320 -0
  258. data/projects/monorepo/lib/foobara/monorepo/project.rb +52 -0
  259. data/projects/monorepo/lib/foobara/monorepo.rb +63 -0
  260. data/projects/namespace/lib/foobara/namespace.rb +4 -0
  261. data/projects/namespace/src/ambiguous_registry.rb +104 -0
  262. data/projects/namespace/src/base_registry.rb +66 -0
  263. data/projects/namespace/src/extensions/module.rb +5 -0
  264. data/projects/namespace/src/is_namespace.rb +352 -0
  265. data/projects/namespace/src/namespace/lookup_mode.rb +41 -0
  266. data/projects/namespace/src/namespace.rb +61 -0
  267. data/projects/namespace/src/namespace_helpers.rb +273 -0
  268. data/projects/namespace/src/prefixless_registry.rb +54 -0
  269. data/projects/namespace/src/scoped.rb +113 -0
  270. data/projects/namespace/src/unambiguous_registry.rb +65 -0
  271. data/projects/persistence/lib/foobara/persistence.rb +22 -0
  272. data/projects/persistence/src/entity_attributes_crud_driver.rb +241 -0
  273. data/projects/persistence/src/entity_base/table.rb +14 -0
  274. data/projects/persistence/src/entity_base/transaction/concerns/entity_callback_handling.rb +157 -0
  275. data/projects/persistence/src/entity_base/transaction/concerns/state_transitions.rb +83 -0
  276. data/projects/persistence/src/entity_base/transaction/concerns/transaction_tracking.rb +53 -0
  277. data/projects/persistence/src/entity_base/transaction/state_machine.rb +27 -0
  278. data/projects/persistence/src/entity_base/transaction.rb +163 -0
  279. data/projects/persistence/src/entity_base/transaction_table/concerns/queries.rb +42 -0
  280. data/projects/persistence/src/entity_base/transaction_table/concerns/record_tracking.rb +134 -0
  281. data/projects/persistence/src/entity_base/transaction_table.rb +620 -0
  282. data/projects/persistence/src/entity_base.rb +114 -0
  283. data/projects/persistence/src/persistence.rb +172 -0
  284. data/projects/state_machine/lib/foobara/state_machine.rb +1 -0
  285. data/projects/state_machine/src/callbacks.rb +158 -0
  286. data/projects/state_machine/src/log_entry.rb +13 -0
  287. data/projects/state_machine/src/state_machine.rb +91 -0
  288. data/projects/state_machine/src/sugar.rb +125 -0
  289. data/projects/state_machine/src/transition_log.rb +19 -0
  290. data/projects/state_machine/src/validations.rb +69 -0
  291. data/projects/thread_parent/lib/foobara/thread_parent.rb +1 -0
  292. data/projects/thread_parent/src/thread_parent.rb +38 -0
  293. data/projects/type_declarations/lib/foobara/type_declarations.rb +131 -0
  294. data/projects/type_declarations/src/attributes.rb +34 -0
  295. data/projects/type_declarations/src/caster.rb +7 -0
  296. data/projects/type_declarations/src/desugarizer.rb +25 -0
  297. data/projects/type_declarations/src/dsl/attributes.rb +199 -0
  298. data/projects/type_declarations/src/element_processor.rb +7 -0
  299. data/projects/type_declarations/src/error_extension.rb +73 -0
  300. data/projects/type_declarations/src/handlers/extend_array_type_declaration/array_desugarizer.rb +31 -0
  301. data/projects/type_declarations/src/handlers/extend_array_type_declaration/element_type_declaration_desugarizer.rb +37 -0
  302. data/projects/type_declarations/src/handlers/extend_array_type_declaration/to_type_transformer.rb +22 -0
  303. data/projects/type_declarations/src/handlers/extend_array_type_declaration/type_set_to_array_desugarizer.rb +36 -0
  304. data/projects/type_declarations/src/handlers/extend_array_type_declaration.rb +14 -0
  305. data/projects/type_declarations/src/handlers/extend_associative_array_type_declaration/to_type_transformer.rb +28 -0
  306. data/projects/type_declarations/src/handlers/extend_associative_array_type_declaration.rb +20 -0
  307. data/projects/type_declarations/src/handlers/extend_attributes_type_declaration/dsl_desugarizer.rb +25 -0
  308. data/projects/type_declarations/src/handlers/extend_attributes_type_declaration/element_type_declarations_desugarizer.rb +34 -0
  309. data/projects/type_declarations/src/handlers/extend_attributes_type_declaration/hash_desugarizer.rb +60 -0
  310. data/projects/type_declarations/src/handlers/extend_attributes_type_declaration/to_type_transformer.rb +21 -0
  311. data/projects/type_declarations/src/handlers/extend_attributes_type_declaration.rb +16 -0
  312. data/projects/type_declarations/src/handlers/extend_registered_type_declaration/to_type_transformer.rb +75 -0
  313. data/projects/type_declarations/src/handlers/extend_registered_type_declaration.rb +23 -0
  314. data/projects/type_declarations/src/handlers/extend_tuple_type_declaration/array_desugarizer.rb +30 -0
  315. data/projects/type_declarations/src/handlers/extend_tuple_type_declaration/to_type_transformer.rb +24 -0
  316. data/projects/type_declarations/src/handlers/extend_tuple_type_declaration.rb +13 -0
  317. data/projects/type_declarations/src/handlers/registered_type_declaration/desugarizer_metadata_cleanup_desugarizer.rb +29 -0
  318. data/projects/type_declarations/src/handlers/registered_type_declaration/short_type_name_desugarizer.rb +65 -0
  319. data/projects/type_declarations/src/handlers/registered_type_declaration/strict_desugarizer.rb +32 -0
  320. data/projects/type_declarations/src/handlers/registered_type_declaration/strict_stringified_desugarizer.rb +39 -0
  321. data/projects/type_declarations/src/handlers/registered_type_declaration/symbol_desugarizer.rb +26 -0
  322. data/projects/type_declarations/src/handlers/registered_type_declaration/to_type_transformer.rb +28 -0
  323. data/projects/type_declarations/src/handlers/registered_type_declaration/type_desugarizer.rb +24 -0
  324. data/projects/type_declarations/src/handlers/registered_type_declaration.rb +26 -0
  325. data/projects/type_declarations/src/processor.rb +7 -0
  326. data/projects/type_declarations/src/to_type_transformer.rb +11 -0
  327. data/projects/type_declarations/src/transformer.rb +7 -0
  328. data/projects/type_declarations/src/type_builder.rb +112 -0
  329. data/projects/type_declarations/src/type_declaration_error.rb +9 -0
  330. data/projects/type_declarations/src/type_declaration_handler.rb +120 -0
  331. data/projects/type_declarations/src/type_declaration_handler_registry.rb +27 -0
  332. data/projects/type_declarations/src/type_declaration_validator.rb +19 -0
  333. data/projects/type_declarations/src/type_declarations.rb +128 -0
  334. data/projects/type_declarations/src/typed_transformer.rb +89 -0
  335. data/projects/type_declarations/src/validator.rb +7 -0
  336. data/projects/type_declarations/src/with_registries.rb +41 -0
  337. data/projects/types/lib/foobara/types.rb +11 -0
  338. data/projects/types/src/element_processor.rb +7 -0
  339. data/projects/types/src/extensions/error.rb +32 -0
  340. data/projects/types/src/type/concerns/reflection.rb +79 -0
  341. data/projects/types/src/type/concerns/supported_processor_registration.rb +56 -0
  342. data/projects/types/src/type.rb +375 -0
  343. data/projects/types/src/types.rb +4 -0
  344. data/projects/value/lib/foobara/value.rb +7 -0
  345. data/projects/value/src/caster.rb +84 -0
  346. data/projects/value/src/data_error.rb +27 -0
  347. data/projects/value/src/processor/casting.rb +123 -0
  348. data/projects/value/src/processor/multi.rb +63 -0
  349. data/projects/value/src/processor/pipeline.rb +27 -0
  350. data/projects/value/src/processor/runner.rb +38 -0
  351. data/projects/value/src/processor/selection.rb +90 -0
  352. data/projects/value/src/processor.rb +358 -0
  353. data/projects/value/src/transformer.rb +84 -0
  354. data/projects/value/src/validator.rb +53 -0
  355. data/projects/version/lib/foobara/version.rb +4 -0
  356. data/projects/version/src/version.rb +5 -0
  357. data/projects/weak_object_set/lib/foobara/weak_object_set.rb +3 -0
  358. data/projects/weak_object_set/src/weak_object_set.rb +163 -0
  359. metadata +445 -0
@@ -0,0 +1,32 @@
1
+ module Foobara
2
+ class Error
3
+ class << self
4
+ def types_depended_on(*args)
5
+ if args.size == 1
6
+ context_type.types_depended_on(args.first)
7
+ elsif args.empty?
8
+ begin
9
+ if context_type
10
+ context_type.types_depended_on
11
+ else
12
+ raise Foobara::TypeDeclarations::ErrorExtension::NoContextTypeSetError
13
+ end
14
+ rescue Foobara::TypeDeclarations::ErrorExtension::NoContextTypeSetError
15
+ if abstract?
16
+ []
17
+ else
18
+ # :nocov:
19
+ raise
20
+ # :nocov:
21
+ end
22
+ end
23
+
24
+ else
25
+ # :nocov:
26
+ raise ArgumentError, "Too many arguments #{args}"
27
+ # :nocov:
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,79 @@
1
+ module Foobara
2
+ module Types
3
+ class Type < Value::Processor::Pipeline
4
+ module Concerns
5
+ module Reflection
6
+ include Concern
7
+
8
+ # as soon as we hit a registered type, don't go further down that path
9
+ def types_depended_on(result = nil)
10
+ start = result.nil?
11
+ result ||= Set.new
12
+ return if result.include?(self)
13
+
14
+ result << self
15
+
16
+ return if !start && registered?
17
+
18
+ to_process = [*base_type, *element_type, *possible_errors.map(&:error_class)]
19
+
20
+ if element_types
21
+ to_process += case element_types
22
+ when Type
23
+ [element_types]
24
+ when ::Hash
25
+ element_types.values.select { |value| value.is_a?(Type) }
26
+ when ::Array
27
+ element_types
28
+ else
29
+ # :nocov:
30
+ raise "Not sure how to find dependent types for #{element_types}"
31
+ # :nocov:
32
+ end
33
+ end
34
+
35
+ to_process.each do |type|
36
+ type.types_depended_on(result)
37
+ end
38
+
39
+ if start
40
+ result = result.select { |type| type.registered? && type != self }.to_set
41
+ end
42
+
43
+ result
44
+ end
45
+
46
+ def deep_types_depended_on
47
+ result = Set.new
48
+ to_process = types_depended_on
49
+
50
+ until to_process.empty?
51
+ type = to_process.first
52
+ to_process.delete(type)
53
+
54
+ next if result.include?(type)
55
+
56
+ result << type
57
+
58
+ to_process |= type.types_depended_on
59
+ end
60
+
61
+ result.select(&:registered?)
62
+ end
63
+
64
+ def inspect
65
+ # :nocov:
66
+ name = if scoped_path_set?
67
+ scoped_full_name
68
+ else
69
+ "Anonymous #{base_type.type_symbol}"
70
+ end
71
+
72
+ "#<Type:#{name}:0x#{object_id.to_s(16)} #{declaration_data}>"
73
+ # :nocov:
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,56 @@
1
+ module Foobara
2
+ module Types
3
+ class Type < Value::Processor::Pipeline
4
+ module Concerns
5
+ # What do we actually need here?
6
+ # we need a way to associate a type with a collection of supported processors.
7
+ # Type could make the most sense for this functionality.
8
+ # Any reason we should be decoupling the concept of validators to apply
9
+ # from validators that are supported and may or may not be applied?
10
+ # OK let's attempt doing this on Type instead.
11
+ module SupportedProcessorRegistration
12
+ class MissingProcessorError < StandardError; end
13
+
14
+ def supported_processor_classes
15
+ @supported_processor_classes ||= {}
16
+ end
17
+
18
+ def all_supported_processor_classes
19
+ if base_type
20
+ supported_processor_classes.values + base_type.all_supported_processor_classes
21
+ else
22
+ supported_processor_classes.values
23
+ end
24
+ end
25
+
26
+ def find_supported_processor_class(processor_symbol)
27
+ if supported_processor_classes.key?(processor_symbol)
28
+ supported_processor_classes[processor_symbol]
29
+ elsif base_type
30
+ base_type.find_supported_processor_class(processor_symbol)
31
+ else
32
+ # TODO: can we catch this via a type declaration validator before hitting it here?
33
+ raise MissingProcessorError, "No such processor for #{processor_symbol}"
34
+ end
35
+ end
36
+
37
+ def register_supported_processor_class(processor_class, symbol: processor_class.symbol)
38
+ unless symbol.is_a?(Symbol)
39
+ # :nocov:
40
+ raise "Invalid symbol value #{symbol.inspect}. Should instead be a symbol but was a #{symbol.class.name}"
41
+ # :nocov:
42
+ end
43
+
44
+ if supported_processor_classes.key?(symbol)
45
+ # :nocov:
46
+ raise "There's already a processor registered for #{symbol}"
47
+ # :nocov:
48
+ end
49
+
50
+ supported_processor_classes[symbol] = processor_class
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,375 @@
1
+ module Foobara
2
+ module Types
3
+ # TODO: move casting interface to here?
4
+ class Type < Value::Processor::Pipeline
5
+ include Concerns::SupportedProcessorRegistration
6
+ include Concerns::Reflection
7
+ include IsManifestable
8
+
9
+ foobara_instances_are_namespaces!
10
+
11
+ class << self
12
+ def requires_declaration_data?
13
+ true
14
+ end
15
+ end
16
+
17
+ # TODO: needed/useful transformers/validators to implement:
18
+ #
19
+ # allow_empty (validation at attribute level)
20
+ # allow_nil (validation at attribute level)
21
+ # one_of (validation at attribute level)
22
+
23
+ attr_accessor :base_type,
24
+ :casters,
25
+ :transformers,
26
+ :validators,
27
+ :element_processors,
28
+ :structure_count,
29
+ :element_types,
30
+ :element_type,
31
+ :raw_declaration_data,
32
+ :name,
33
+ :target_classes,
34
+ :description
35
+ attr_reader :type_symbol
36
+
37
+ def initialize(
38
+ *args,
39
+ target_classes:,
40
+ base_type:,
41
+ description: nil,
42
+ name: "anonymous",
43
+ casters: [],
44
+ transformers: [],
45
+ validators: [],
46
+ element_processors: nil,
47
+ element_type: nil,
48
+ element_types: nil,
49
+ structure_count: nil,
50
+ **opts
51
+ )
52
+ self.base_type = base_type
53
+ self.description = description
54
+ self.casters = [*casters, *base_type&.casters]
55
+ self.transformers = [*transformers, *base_type&.transformers]
56
+ self.validators = [*validators, *base_type&.validators]
57
+ self.element_processors = [*element_processors, *base_type&.element_processors]
58
+
59
+ self.structure_count = structure_count
60
+ # TODO: combine these maybe with the term "children_types"?
61
+ self.element_types = element_types
62
+ self.element_type = element_type
63
+ self.name = name
64
+ self.target_classes = Util.array(target_classes)
65
+
66
+ super(*args, **opts.merge(processors:, prioritize: false))
67
+
68
+ validate_processors!
69
+ end
70
+
71
+ def validate_processors!
72
+ all = [casters, transformers, validators, element_processors]
73
+
74
+ all.each do |processor_group|
75
+ processor_group.each.with_index do |processor, index|
76
+ if processor.requires_parent_declaration_data?
77
+ processor_group[index] = processor.dup_processor(parent_declaration_data: declaration_data)
78
+ end
79
+ end
80
+
81
+ processor_group.group_by(&:symbol).each_pair do |symbol, members|
82
+ if members.size > 1
83
+ if members.map { |m| m.class.name }.uniq.size == members.size
84
+ members[1..].each do |member|
85
+ processor_group.delete(member)
86
+ end
87
+ else
88
+ # :nocov:
89
+ raise "Type #{name} has multiple processors with symbol #{symbol}"
90
+ # :nocov:
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ def target_class
98
+ if target_classes.empty?
99
+ # :nocov:
100
+ raise "No target classes"
101
+ # :nocov:
102
+ elsif target_classes.size > 1
103
+ # :nocov:
104
+ raise "Cannot use #target_class because this type has multiple target_classes"
105
+ # :nocov:
106
+ end
107
+
108
+ target_classes.first
109
+ end
110
+
111
+ def extends?(type)
112
+ case type
113
+ when Type
114
+ extends_type?(type)
115
+ when Symbol, String
116
+ concrete_type = created_in_namespace.foobara_lookup_type(type)
117
+ if concrete_type.nil?
118
+ # :nocov:
119
+ raise "No type found for #{type}"
120
+ # :nocov:
121
+ end
122
+
123
+ extends_type?(concrete_type)
124
+ else
125
+ # :nocov:
126
+ raise ArgumentError, "Expected a Type or a Symbol/String, but got #{type.inspect}"
127
+ # :nocov:
128
+ end
129
+ end
130
+
131
+ def extends_type?(type)
132
+ return true if self == type
133
+
134
+ unless type
135
+ # :nocov:
136
+ raise ArgumentError, "Expected a type but got nil"
137
+ # :nocov:
138
+ end
139
+
140
+ if registered?
141
+ if type.registered?
142
+ if type.foobara_manifest_reference == foobara_manifest_reference
143
+ return true
144
+ end
145
+ end
146
+ end
147
+
148
+ base_type&.extends_type?(type)
149
+ end
150
+
151
+ def type_symbol=(type_symbol)
152
+ @scoped_path ||= type_symbol.to_s.split("::")
153
+ @type_symbol = type_symbol.to_sym
154
+ end
155
+
156
+ def full_type_symbol
157
+ return @full_type_symbol if defined?(@full_type_symbol)
158
+
159
+ @full_type_symbol ||= if scoped_path_set?
160
+ scoped_full_name.to_sym
161
+ end
162
+ end
163
+
164
+ def processors
165
+ [
166
+ value_caster,
167
+ value_transformer,
168
+ value_validator,
169
+ element_processor
170
+ ].compact
171
+ end
172
+
173
+ def value_caster
174
+ # TODO: how can declaration_data be blank? That seems really strange...
175
+ Value::Processor::Casting.new({ cast_to: declaration_data }, casters:, target_classes:)
176
+ end
177
+
178
+ def applicable?(value)
179
+ value_caster.can_cast?(value)
180
+ end
181
+
182
+ foobara_delegate :needs_cast?, to: :value_caster
183
+
184
+ def cast(value)
185
+ value_caster.process_value(value)
186
+ end
187
+
188
+ def cast!(value)
189
+ value_caster.process_value!(value)
190
+ end
191
+
192
+ # TODO: an interesting thought... we have Processor and then a subclass of Processor and then an instance of
193
+ # processor that encapsulates the declaration_data for that processor. But then we pass `value` to every
194
+ # method in the instance of the processor as needed. This means it can't really memoize stuff. Should we create
195
+ # an instance of something from the instance of the processor and then ask it questions?? TODO: try this
196
+ def value_transformer
197
+ if transformers && !transformers.empty?
198
+ Value::Processor::Pipeline.new(processors: transformers)
199
+ end
200
+ end
201
+
202
+ # TODO: figure out how to safely memoize stuff so like this for performance reasons
203
+ # A good way, but potentially a decent amount of work, is to have a class that takes value to its initialize
204
+ # method.
205
+ def value_validator
206
+ if validators && !validators.empty?
207
+ Value::Processor::Pipeline.new(processors: validators)
208
+ end
209
+ end
210
+
211
+ def element_processor
212
+ if element_processors && !element_processors.empty?
213
+ Value::Processor::Pipeline.new(processors: element_processors)
214
+ end
215
+ end
216
+
217
+ # TODO: some way of memoizing these values? Would need to introduce a new class that takes the value to its
218
+ # constructor
219
+ def validation_errors(value)
220
+ value = cast!(value)
221
+ if value_transformer
222
+ value = value_transformer.process_value!(value)
223
+ end
224
+
225
+ if value_validator
226
+ value_validator.process_value(value).errors
227
+ else
228
+ []
229
+ end
230
+ end
231
+
232
+ def full_type_name
233
+ scoped_full_name
234
+ end
235
+
236
+ def reference_or_declaration_data(declaration_data = self.declaration_data)
237
+ if registered?
238
+ # TODO: we should just use the symbol and nothing else in this context instead of a hash with 1 element.
239
+ { type: foobara_manifest_reference.to_sym }
240
+ else
241
+ declaration_data
242
+ end
243
+ end
244
+
245
+ # TODO: put this somewhere else
246
+ def foobara_manifest_reference
247
+ scoped_full_name
248
+ end
249
+
250
+ def foobara_manifest(to_include:)
251
+ types = []
252
+
253
+ types_depended_on.each do |dependent_type|
254
+ if dependent_type.registered?
255
+ types << dependent_type.foobara_manifest_reference
256
+ to_include << dependent_type
257
+ end
258
+ end
259
+
260
+ possible_errors_manifests = possible_errors.map do |possible_error|
261
+ [possible_error.key.to_s, possible_error.foobara_manifest(to_include:)]
262
+ end.sort.to_h
263
+
264
+ h = Util.remove_blank(
265
+ name:,
266
+ target_classes: target_classes.map(&:name).sort,
267
+ declaration_data:,
268
+ types_depended_on: types.sort,
269
+ possible_errors: possible_errors_manifests
270
+ ).merge(description:, base_type: base_type&.full_type_name&.to_sym)
271
+
272
+ h.merge!(
273
+ supported_processor_manifest(to_include).merge(
274
+ Util.remove_blank(processors: processor_manifest(to_include))
275
+ )
276
+ )
277
+
278
+ target_classes.sort_by(&:name).each do |target_class|
279
+ if target_class.respond_to?(:foobara_manifest)
280
+ h.merge!(target_class.foobara_manifest(to_include:))
281
+ end
282
+ end
283
+
284
+ super.merge(h)
285
+ end
286
+
287
+ def supported_processor_manifest(to_include)
288
+ supported_casters = []
289
+ supported_transformers = []
290
+ supported_validators = []
291
+ supported_processors = []
292
+
293
+ all_supported_processor_classes.each do |processor_class|
294
+ to_include << processor_class
295
+
296
+ target = if processor_class < Value::Caster
297
+ supported_casters
298
+ elsif processor_class < Value::Validator
299
+ supported_validators
300
+ elsif processor_class < Value::Transformer
301
+ supported_transformers
302
+ else
303
+ supported_processors
304
+ end
305
+
306
+ target << processor_class.foobara_manifest_reference
307
+ end
308
+
309
+ Util.remove_blank(
310
+ supported_casters: supported_casters.sort,
311
+ supported_transformers: supported_transformers.sort,
312
+ supported_validators: supported_validators.sort,
313
+ supported_processors: supported_processors.sort
314
+ )
315
+ end
316
+
317
+ def processor_manifest(to_include)
318
+ casters_manifest = []
319
+ transformers_manifest = []
320
+ validators_manifest = []
321
+ caster_classes_manifest = []
322
+ transformer_classes_manifest = []
323
+ validator_classes_manifest = []
324
+
325
+ casters.each do |caster|
326
+ klass = caster.class
327
+ to_include << klass
328
+ caster_classes_manifest << klass.foobara_manifest_reference
329
+
330
+ if caster.scoped_path_set?
331
+ to_include << caster
332
+ casters_manifest << caster.foobara_manifest_reference
333
+ end
334
+ end
335
+
336
+ transformers.each do |transformer|
337
+ klass = transformer.class
338
+ to_include << klass
339
+ transformer_classes_manifest << klass.foobara_manifest_reference
340
+
341
+ if transformer.scoped_path_set?
342
+ to_include << transformer
343
+ transformers_manifest << transformer.foobara_manifest_reference
344
+ end
345
+ end
346
+
347
+ validators.each do |validator|
348
+ klass = validator.class
349
+ to_include << klass
350
+ validator_classes_manifest << klass.foobara_manifest_reference
351
+
352
+ if validator.scoped_path_set?
353
+ to_include << validator
354
+ validators_manifest << validator.foobara_manifest_reference
355
+ end
356
+ end
357
+
358
+ Util.remove_blank(
359
+ casters: casters_manifest.sort,
360
+ caster_classes: caster_classes_manifest.sort,
361
+ transformers: transformers_manifest.sort,
362
+ transformer_classes: transformer_classes_manifest.sort,
363
+ validators: validators_manifest.sort,
364
+ validator_classes: validator_classes_manifest.sort
365
+ )
366
+ end
367
+
368
+ def registered?
369
+ !!type_symbol
370
+ end
371
+ end
372
+ end
373
+
374
+ Type = Foobara::Types::Type
375
+ end
@@ -0,0 +1,4 @@
1
+ module Foobara
2
+ module Types
3
+ end
4
+ end
@@ -0,0 +1,7 @@
1
+ module Foobara
2
+ module Value
3
+ foobara_domain!
4
+ end
5
+
6
+ Foobara.require_project_file("value", "processor")
7
+ end
@@ -0,0 +1,84 @@
1
+ module Foobara
2
+ module Value
3
+ # TODO: do we really need these?? Can't just use a transformer?
4
+ class Caster < Transformer
5
+ class << self
6
+ def foobara_manifest(to_include:)
7
+ super.merge(processor_type: :caster)
8
+ end
9
+
10
+ def requires_declaration_data?
11
+ false
12
+ end
13
+
14
+ def create(options)
15
+ subclass(**options).instance
16
+ end
17
+
18
+ def subclass(name: nil, **options)
19
+ arity_zero = %i[name applies_message]
20
+ arity_one = %i[applicable? cast]
21
+ allowed = arity_zero + arity_one
22
+
23
+ invalid_options = options.keys - allowed
24
+
25
+ unless invalid_options.empty?
26
+ # :nocov:
27
+ raise ArgumentError, "Invalid options #{invalid_options} expected only #{allowed}"
28
+ # :nocov:
29
+ end
30
+
31
+ name ||= "#{self.name}::Anon#{SecureRandom.hex}"
32
+
33
+ unless name.include?(":")
34
+ name = "#{self.name}::#{name}"
35
+ end
36
+
37
+ Util.make_class name, self do
38
+ arity_one.each do |method_name|
39
+ if options.key?(method_name)
40
+ method = options[method_name]
41
+
42
+ define_method method_name do |value|
43
+ method.call(value)
44
+ end
45
+ end
46
+ end
47
+
48
+ arity_zero.each do |method_name|
49
+ if options.key?(method_name)
50
+ value = options[method_name]
51
+
52
+ define_method method_name do
53
+ value
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ def applicable?(_value)
62
+ # :nocov:
63
+ raise "subclass responsibility"
64
+ # :nocov:
65
+ end
66
+
67
+ def applies_message
68
+ # :nocov:
69
+ raise "subclass responsibility"
70
+ # :nocov:
71
+ end
72
+
73
+ def transform(value)
74
+ cast(value)
75
+ end
76
+
77
+ def cast(_value)
78
+ # :nocov:
79
+ raise "subclass responsibility"
80
+ # :nocov:
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,27 @@
1
+ module Foobara
2
+ module Value
3
+ class DataError < Error
4
+ class << self
5
+ def category
6
+ :data
7
+ end
8
+ end
9
+
10
+ def initialize(message: nil, symbol: nil, context: nil, path: nil)
11
+ args = { message:, symbol:, context:, path: }.compact
12
+ super(**args.merge(category: self.class.category))
13
+ end
14
+
15
+ def attribute_name
16
+ # TODO: feels awkward... something is not right
17
+ # how is path actually set?
18
+ path.last || context[:attribute_name]
19
+ end
20
+
21
+ def eql?(other)
22
+ # TODO: this doesn't feel right at all...
23
+ super && other.is_a?(DataError) && path == other.path
24
+ end
25
+ end
26
+ end
27
+ end