<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>BeamFoundry Rays on BeamFoundry Rays Core</title><link>https://rays.bfdy.dev/rays/</link><description>Recent content in BeamFoundry Rays on BeamFoundry Rays Core</description><generator>Hugo</generator><language>en-us</language><atom:link href="https://rays.bfdy.dev/rays/index.xml" rel="self" type="application/rss+xml"/><item><title>1. Introduction</title><link>https://rays.bfdy.dev/rays/docs/1-introduction/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rays.bfdy.dev/rays/docs/1-introduction/</guid><description>&lt;h1 id="introduction--philosophy"&gt;Introduction &amp;amp; Philosophy&lt;a class="anchor" href="#introduction--philosophy"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;Go is famous for its simplicity and explicit dependency passing. However, as Go applications scale to hundreds&#10;of services, repositories, and cross-cutting concerns, manual wiring (often done in massive &lt;code&gt;init()&lt;/code&gt;&#10;functions or &lt;code&gt;main.go&lt;/code&gt;) becomes fragile and difficult to maintain.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;BeamFoundry Rays solves this by introducing a robust Inversion of Control (IoC) container.&lt;/strong&gt;&lt;/p&gt;&#10;&lt;h2 id="core-principles"&gt;Core Principles&lt;a class="anchor" href="#core-principles"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;Annotation-Driven, but Type-Safe:&lt;/strong&gt; We use struct tags (&lt;code&gt;@:&amp;quot;Inject&amp;quot;&lt;/code&gt;) for declaring dependencies,&#10;but rely on Go&amp;rsquo;s strict typing to ensure the container wires the correct pointers.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Encapsulation Matters:&lt;/strong&gt; Unlike manual DI which forces you to expose dependencies via public fields&#10;or constructor arguments, Rays natively injects into &lt;strong&gt;private fields&lt;/strong&gt;. Your internal state remains protected.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Two-Phase Bootstrapping:&lt;/strong&gt; To safely handle circular dependencies—a common pain point in large systems—Rays&#10;separates instantiation/injection from initialization.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Context-Aware Scoping:&lt;/strong&gt; Singletons are great for services, but short-lived state requires a different approach.&#10;Rays introduces &lt;code&gt;Foundry[T]&lt;/code&gt; to bridge the gap between global services and request-scoped prototypes.&lt;/li&gt;&#10;&lt;/ol&gt;</description></item><item><title>Error Handling</title><link>https://rays.bfdy.dev/rays/docs/5-language-helpers/1-error-handling/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rays.bfdy.dev/rays/docs/5-language-helpers/1-error-handling/</guid><description>&lt;h1 id="error-handling"&gt;Error Handling&lt;a class="anchor" href="#error-handling"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;If a container fails to boot, you need to know exactly &lt;em&gt;where&lt;/em&gt; the wiring failed. Rays replaces standard Go &lt;code&gt;error&lt;/code&gt; handling during the lifecycle with a richer &lt;code&gt;Error&lt;/code&gt; interface that captures stack traces and key-value attributes automatically.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; . &lt;span style="color:#e6db74"&gt;&amp;#34;github.com/BeamFoundry/rays/pkg/lang&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;UserService&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;PostConstruct&lt;/span&gt;() &lt;span style="color:#a6e22e"&gt;Error&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;db&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;NewError&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;WiringError&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;Database pointer is nil&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// AddAttribute does not return the Error object, so it cannot be chained.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;AddAttribute&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;component&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;UserService&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;AddAttribute&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;action&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;PostConstruct&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="integration-with-logging"&gt;Integration with Logging&lt;a class="anchor" href="#integration-with-logging"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;Because Rays integrates its &lt;code&gt;lang&lt;/code&gt; package directly with the &lt;code&gt;logging&lt;/code&gt; framework (covered in Chapter 4), an &lt;code&gt;Error&lt;/code&gt; can report itself seamlessly.&lt;/p&gt;</description></item><item><title>Message Catalogs &amp; Pluralization</title><link>https://rays.bfdy.dev/rays/docs/7-i18n/1-message-catalogs/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rays.bfdy.dev/rays/docs/7-i18n/1-message-catalogs/</guid><description>&lt;h1 id="message-catalogs--pluralization"&gt;Message Catalogs &amp;amp; Pluralization&lt;a class="anchor" href="#message-catalogs--pluralization"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;Rays simplifies message localization by letting you define translation catalogs directly in your YAML configuration files. Messages are automatically loaded into &lt;code&gt;LocaleMessageBundle&lt;/code&gt; instances, with full support for positional parameters, Unicode CLDR pluralization rules, and numeric ranges.&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="defining-messages-in-yaml"&gt;Defining Messages in YAML&lt;a class="anchor" href="#defining-messages-in-yaml"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;Message catalogs are organized by locale under the &lt;code&gt;localization.messages&lt;/code&gt; property in your &lt;code&gt;application.yaml&lt;/code&gt; file. Rays recognizes four distinct categories of localized messages:&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th style="text-align: left"&gt;Category&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th style="text-align: left"&gt;Description&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th style="text-align: left"&gt;Placeholders&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;strong&gt;&lt;code&gt;translation&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;Simple string translations. Positional parameters are denoted by &lt;code&gt;{0}&lt;/code&gt;, &lt;code&gt;{1}&lt;/code&gt;, &lt;code&gt;{2}&lt;/code&gt;, etc.&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;code&gt;{0}&lt;/code&gt;, &lt;code&gt;{1}&lt;/code&gt;, &lt;code&gt;{2}&lt;/code&gt;, &amp;hellip;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;strong&gt;&lt;code&gt;cardinal&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;Plural rules determined by item quantities (e.g., &amp;ldquo;1 day&amp;rdquo; vs. &amp;ldquo;5 days&amp;rdquo;).&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;code&gt;{0}&lt;/code&gt; (the formatted number)&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;strong&gt;&lt;code&gt;ordinal&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;Plural rules determined by position or rank (e.g., &amp;ldquo;1st&amp;rdquo;, &amp;ldquo;2nd&amp;rdquo;, &amp;ldquo;3rd&amp;rdquo;).&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;code&gt;{0}&lt;/code&gt; (the formatted number)&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;strong&gt;&lt;code&gt;ranges&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;Plural rules for intervals between two numbers (e.g., &amp;ldquo;1-3 days&amp;rdquo;).&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;code&gt;{0}&lt;/code&gt;, &lt;code&gt;{1}&lt;/code&gt; (the start and end numbers)&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h3 id="complete-yaml-example"&gt;Complete YAML Example&lt;a class="anchor" href="#complete-yaml-example"&gt;&lt;/a&gt;&lt;/h3&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;localization&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;messages&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;en&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;translation&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;welcome&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Welcome&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;welcome_user&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Welcome, {0} {1}!&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;fields.registration.username&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Username&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;fields.registration.password&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Password&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;fields.registration.confirm&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Confirm Password&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;cardinal&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;days.left&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ONE&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;{0} day remaining&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;OTHER&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;{0} days remaining&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ordinal&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;competition.place&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ONE&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;{0}st place&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;TWO&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;{0}nd place&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;FEW&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;{0}rd place&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;OTHER&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;{0}th place&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ranges&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;days.range&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;OTHER&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;{0}-{1} days&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;fr&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;translation&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;welcome&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Bienvenue&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;welcome_user&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Bienvenue, {0} {1} !&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;fields.registration.username&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Nom d&amp;#39;utilisateur&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;fields.registration.password&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Mot de passe&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;fields.registration.confirm&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Confirmation du mot de passe&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;cardinal&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;days.left&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ONE&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;{0} jour restant&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;OTHER&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;{0} jours restants&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ordinal&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;competition.place&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ONE&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;{0}er prix&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;OTHER&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;{0}e prix&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ranges&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;days.range&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ONE&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;{0}-{1} jour&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;OTHER&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;{0}-{1} jours&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#10;&lt;h2 id="cldr-plural-rules"&gt;CLDR Plural Rules&lt;a class="anchor" href="#cldr-plural-rules"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;Different languages follow different rules for pluralization. In English, cardinal numbers only distinguish between &lt;code&gt;ONE&lt;/code&gt; (1) and &lt;code&gt;OTHER&lt;/code&gt; (0, 2, 3, &amp;hellip;). Other languages like Polish, Russian, or Arabic use additional categories such as &lt;code&gt;FEW&lt;/code&gt; or &lt;code&gt;MANY&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Stereotypes &amp; Beams</title><link>https://rays.bfdy.dev/rays/docs/3-ioc-container/1-stereotypes/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rays.bfdy.dev/rays/docs/3-ioc-container/1-stereotypes/</guid><description>&lt;h1 id="stereotypes--beams"&gt;Stereotypes &amp;amp; Beams&lt;a class="anchor" href="#stereotypes--beams"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;In Rays, a &amp;ldquo;Beam&amp;rdquo; is any object managed by the IoC container.&#10;You declare a struct as a Beam by embedding a &lt;strong&gt;Stereotype&lt;/strong&gt;.&lt;/p&gt;&#10;&lt;h2 id="-simplifying-with-dot-imports"&gt;🧹 Simplifying with Dot Imports&lt;a class="anchor" href="#-simplifying-with-dot-imports"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;Before we dive in, a quick note on style. To keep your domain code clean and free of repetitive package prefixes,&#10;it is highly recommended to use Go&amp;rsquo;s dot import feature for the &lt;code&gt;core&lt;/code&gt; and &lt;code&gt;lang&lt;/code&gt; packages.&lt;/p&gt;&#10;&lt;p&gt;This allows you to use framework types like &lt;code&gt;Service&lt;/code&gt;, &lt;code&gt;Component&lt;/code&gt;, and &lt;code&gt;Error&lt;/code&gt; directly as if they were&#10;native keywords. We will use this convention in the following examples.&lt;/p&gt;</description></item><item><title>2. Quickstart</title><link>https://rays.bfdy.dev/rays/docs/2-quickstart/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rays.bfdy.dev/rays/docs/2-quickstart/</guid><description>&lt;h1 id="quickstart"&gt;Quickstart&lt;a class="anchor" href="#quickstart"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;h2 id="-installation"&gt;📦 Installation&lt;a class="anchor" href="#-installation"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;go get github.com/BeamFoundry/rays&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="-the-minimal-application"&gt;🚀 The Minimal Application&lt;a class="anchor" href="#-the-minimal-application"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;Here is a complete example of a Rays application. It&amp;rsquo;s not really functional but demonstrate the following :&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;Beam&lt;/code&gt; are defined by marker &lt;code&gt;Stereotype&lt;/code&gt; interfaces like &lt;code&gt;Component&lt;/code&gt;, &lt;code&gt;Service&lt;/code&gt; and &lt;code&gt;Application&lt;/code&gt;.&lt;/li&gt;&#10;&lt;li&gt;Dependency injection is done via struct tag.&lt;/li&gt;&#10;&lt;li&gt;A &lt;code&gt;PostConstruct&lt;/code&gt; method can be defined on any &lt;code&gt;Beam&lt;/code&gt;. They will be called once an instance is injected.&lt;/li&gt;&#10;&lt;li&gt;A custom &lt;code&gt;Error&lt;/code&gt; type.&lt;/li&gt;&#10;&lt;li&gt;A &lt;code&gt;Run&lt;/code&gt; method can be defined on any &lt;code&gt;Beam&lt;/code&gt;. It does not need to be on an &lt;code&gt;Application&lt;/code&gt;.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Notice how &lt;code&gt;UserService&lt;/code&gt; does not need a constructor taking &lt;code&gt;*Database&lt;/code&gt; as an argument.&lt;/p&gt;</description></item><item><title>Container Configuration</title><link>https://rays.bfdy.dev/rays/docs/7-i18n/2-configuration/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rays.bfdy.dev/rays/docs/7-i18n/2-configuration/</guid><description>&lt;h1 id="container-configuration"&gt;Container Configuration&lt;a class="anchor" href="#container-configuration"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;Rays integrates internationalization cleanly into its Inversion of Control (IoC) container. By declaring an i18n &lt;code&gt;Configuration&lt;/code&gt; Beam, you can bind YAML configuration properties, configure default and auxiliary locales, load validator translation packs, and publish i18n services for injection throughout your application.&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="1-defining-configuration-properties"&gt;1. Defining Configuration Properties&lt;a class="anchor" href="#1-defining-configuration-properties"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;First, define a struct embedding &lt;code&gt;ConfigurationProperties&lt;/code&gt; to bind the &lt;code&gt;localization&lt;/code&gt; section from your &lt;code&gt;application.yaml&lt;/code&gt; file:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;config&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; . &lt;span style="color:#e6db74"&gt;&amp;#34;github.com/BeamFoundry/rays/pkg/core&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; . &lt;span style="color:#e6db74"&gt;&amp;#34;github.com/BeamFoundry/rays/pkg/i18n&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// LocalizationProperties binds messages from application.yaml under &amp;#34;localization&amp;#34;.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;LocalizationProperties&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;ConfigurationProperties&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`Name:&amp;#34;localization&amp;#34;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;messages&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;map&lt;/span&gt;[&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;]&lt;span style="color:#a6e22e"&gt;LocalizedMessages&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Rays automatically maps the YAML properties to the internal &lt;code&gt;LocalizedMessages&lt;/code&gt; struct containing &lt;code&gt;translation&lt;/code&gt;, &lt;code&gt;cardinal&lt;/code&gt;, &lt;code&gt;ordinal&lt;/code&gt;, and &lt;code&gt;ranges&lt;/code&gt; maps.&lt;/p&gt;</description></item><item><title>Dependency Injection</title><link>https://rays.bfdy.dev/rays/docs/3-ioc-container/2-dependency-injection/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rays.bfdy.dev/rays/docs/3-ioc-container/2-dependency-injection/</guid><description>&lt;h1 id="dependency-injection"&gt;Dependency Injection&lt;a class="anchor" href="#dependency-injection"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;Rays relies on struct tags to identify injection points.&lt;/p&gt;&#10;&lt;h2 id="basic-injection"&gt;Basic Injection&lt;a class="anchor" href="#basic-injection"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;Add &lt;code&gt;@:&amp;quot;Inject&amp;quot;&lt;/code&gt; to any field that is a &lt;strong&gt;pointer to a struct&lt;/strong&gt; or an &lt;strong&gt;interface&lt;/strong&gt;.&#10;The container will automatically find and wire the matching Beam by type.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: &lt;em&gt;You cannot inject into a concrete value type (like &lt;code&gt;db Database&lt;/code&gt; instead of &lt;code&gt;db *Database&lt;/code&gt;),&#10;as this would break the singleton pattern by copying the struct by value.&lt;/em&gt;&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; . &lt;span style="color:#e6db74"&gt;&amp;#34;github.com/BeamFoundry/rays/pkg/core&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;OrderService&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Service&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;inventory&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;InventoryService&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`@:&amp;#34;Inject&amp;#34;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;payment&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;PaymentGateway&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`@:&amp;#34;Inject&amp;#34;`&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Interfaces do not need a &amp;#39;*&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="private-field-superiority"&gt;Private Field Superiority&lt;a class="anchor" href="#private-field-superiority"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;Idiomatic Go encourages hiding internal state. Rays uses reflection to inject into private fields,&#10;meaning your dependencies aren&amp;rsquo;t exposed to other packages.&lt;/p&gt;</description></item><item><title>Enum Types</title><link>https://rays.bfdy.dev/rays/docs/5-language-helpers/2-enum-types/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rays.bfdy.dev/rays/docs/5-language-helpers/2-enum-types/</guid><description>&lt;h1 id="type-safe-enums"&gt;Type-Safe Enums&lt;a class="anchor" href="#type-safe-enums"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;Go does not have native, strict enums. This often leads to configuration bugs where an invalid string from a YAML file is happily parsed into a &lt;code&gt;string&lt;/code&gt; field, only to fail deep within the application logic.&lt;/p&gt;&#10;&lt;p&gt;Rays solves this with &lt;code&gt;Enum[T]&lt;/code&gt;. It strictly binds string values from YAML into custom Go types and validates them during the framework&amp;rsquo;s Instantiation phase.&lt;/p&gt;&#10;&lt;h3 id="1-define-the-enum-type"&gt;1. Define the Enum Type&lt;a class="anchor" href="#1-define-the-enum-type"&gt;&lt;/a&gt;&lt;/h3&gt;&#10;&lt;p&gt;You can define your enums using a struct to hold the variants as fields.&lt;/p&gt;</description></item><item><title>Lifecycle Management</title><link>https://rays.bfdy.dev/rays/docs/3-ioc-container/3-lifecycle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rays.bfdy.dev/rays/docs/3-ioc-container/3-lifecycle/</guid><description>&lt;h1 id="lifecycle-management"&gt;Lifecycle Management&lt;a class="anchor" href="#lifecycle-management"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;Rays uses a strict, deterministic phase model to ensure application stability.&lt;/p&gt;&#10;&lt;h2 id="phase-1-instantiation--wiring"&gt;Phase 1: Instantiation &amp;amp; Wiring&lt;a class="anchor" href="#phase-1-instantiation--wiring"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;The container scans for all embedded stereotypes.&lt;/li&gt;&#10;&lt;li&gt;It calls &lt;code&gt;New()&lt;/code&gt; on structs that implement it to set up initial state.&lt;/li&gt;&#10;&lt;li&gt;It maps &lt;code&gt;ConfigurationProperties&lt;/code&gt; from YAML.&lt;/li&gt;&#10;&lt;li&gt;It resolves all &lt;code&gt;@:&amp;quot;Inject&amp;quot;&lt;/code&gt; tags and assigns pointers (or interface references).&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;&lt;em&gt;Note: Because no business logic runs in Phase 1, Rays natively handles &lt;strong&gt;Circular Dependencies&lt;/strong&gt; between singletons.&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Web &amp; Template Integration</title><link>https://rays.bfdy.dev/rays/docs/7-i18n/3-web-and-templates/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rays.bfdy.dev/rays/docs/7-i18n/3-web-and-templates/</guid><description>&lt;h1 id="web--template-integration"&gt;Web &amp;amp; Template Integration&lt;a class="anchor" href="#web--template-integration"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;Internationalized web applications must dynamically determine the user&amp;rsquo;s preferred language for each incoming HTTP request without requiring developers to manually pass a locale or context parameter through every service, repository, and template call.&lt;/p&gt;&#10;&lt;p&gt;Rays solves this using &lt;strong&gt;&lt;code&gt;ThreadLocaleContextHolder&lt;/code&gt;&lt;/strong&gt; for request-scoped locale management and &lt;strong&gt;&lt;code&gt;LocaleFuncMap&lt;/code&gt;&lt;/strong&gt; for seamless integration with Go&amp;rsquo;s standard &lt;code&gt;html/template&lt;/code&gt; package.&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="1-request-scoped-locale-management"&gt;1. Request-Scoped Locale Management&lt;a class="anchor" href="#1-request-scoped-locale-management"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;h3 id="how-it-works"&gt;How It Works&lt;a class="anchor" href="#how-it-works"&gt;&lt;/a&gt;&lt;/h3&gt;&#10;&lt;p&gt;&lt;code&gt;ThreadLocaleContextHolder&lt;/code&gt; is powered by thread-local storage (&lt;code&gt;routine.ThreadLocal&lt;/code&gt;). When an HTTP request enters your application:&lt;/p&gt;</description></item><item><title>4. Logging Framework</title><link>https://rays.bfdy.dev/rays/docs/4-logging/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rays.bfdy.dev/rays/docs/4-logging/</guid><description>&lt;h1 id="logging-framework"&gt;Logging Framework&lt;a class="anchor" href="#logging-framework"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;Enterprise applications require structured, leveled, and contextual logging.&lt;/p&gt;&#10;&lt;p&gt;Rays provides a dedicated configurable, logging framework.&lt;/p&gt;&#10;&lt;h2 id="the-logging-interface"&gt;The &lt;code&gt;Logging&lt;/code&gt; Interface&lt;a class="anchor" href="#the-logging-interface"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;Rays logging is powered by Go&amp;rsquo;s standard &lt;code&gt;slog&lt;/code&gt; library under the hood, providing high-performance, structured logging.&#10;However, standard &lt;code&gt;slog&lt;/code&gt; natively lacks a &amp;ldquo;Trace&amp;rdquo; level for highly granular debugging.&lt;/p&gt;&#10;&lt;p&gt;Rays extends the standard implementation by adding full support for the &lt;code&gt;Trace&lt;/code&gt; level, including the corresponding &lt;code&gt;Trace()&lt;/code&gt; and &lt;code&gt;TraceContext()&lt;/code&gt; functions on the &lt;code&gt;Logging&lt;/code&gt; interface.&lt;/p&gt;</description></item><item><title>Configuration &amp; Profiles</title><link>https://rays.bfdy.dev/rays/docs/3-ioc-container/4-configuration-and-profiles/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rays.bfdy.dev/rays/docs/3-ioc-container/4-configuration-and-profiles/</guid><description>&lt;h1 id="configuration--profiles"&gt;Configuration &amp;amp; Profiles&lt;a class="anchor" href="#configuration--profiles"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;In enterprise applications, configuration and environment management go hand-in-hand.&lt;/p&gt;&#10;&lt;p&gt;Rays provides a unified system to bind YAML configurations directly to your structs,&#10;override them based on active profiles (e.g., &lt;code&gt;dev&lt;/code&gt;, &lt;code&gt;prod&lt;/code&gt;), and conditionally load&#10;specific components depending on the environment.&lt;/p&gt;&#10;&lt;h2 id="1-binding-data"&gt;1. Binding Data&lt;a class="anchor" href="#1-binding-data"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;Embed &lt;code&gt;ConfigurationProperties&lt;/code&gt; and define the YAML path via the &lt;code&gt;Name&lt;/code&gt; tag.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; &lt;em&gt;Rays strictly enforces a 1-to-1 parity between your&#10;YAML files and your Go code. The &lt;code&gt;yaml&lt;/code&gt; tag is &lt;strong&gt;not honored&lt;/strong&gt;. Only properties with&#10;the exact same case name as the Go struct field will be injected.&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Localized Struct Validation</title><link>https://rays.bfdy.dev/rays/docs/7-i18n/4-validation/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rays.bfdy.dev/rays/docs/7-i18n/4-validation/</guid><description>&lt;h1 id="localized-struct-validation"&gt;Localized Struct Validation&lt;a class="anchor" href="#localized-struct-validation"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;Web frameworks and API routers typically bind request payloads to structs and validate them using &lt;a href="https://github.com/go-playground/validator"&gt;Go-Playground Validator&lt;/a&gt;. However, default validation outputs suffer from two major problems:&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;Error descriptions are in English only.&lt;/li&gt;&#10;&lt;li&gt;Field names reflect raw Go struct fields (e.g., &lt;code&gt;&amp;quot;ConfirmPassword&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;user_email&amp;quot;&lt;/code&gt;) rather than user-friendly UI labels.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;Rays&amp;rsquo; &lt;strong&gt;&lt;code&gt;MessageSourceValidator&lt;/code&gt;&lt;/strong&gt; solves both problems by translating validation rules into the active request locale and replacing field names with localized labels defined in your message catalog.&lt;/p&gt;</description></item><item><title>Predefined Catalogs Reference</title><link>https://rays.bfdy.dev/rays/docs/7-i18n/5-catalogs-reference/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rays.bfdy.dev/rays/docs/7-i18n/5-catalogs-reference/</guid><description>&lt;h1 id="predefined-catalogs-reference"&gt;Predefined Catalogs Reference&lt;a class="anchor" href="#predefined-catalogs-reference"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;The &lt;code&gt;github.com/BeamFoundry/rays/pkg/i18n/locales&lt;/code&gt; package eliminates boilerplate by providing pre-instantiated singletons for standard locales and pre-registered validation translation functions.&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="predefined-locales"&gt;Predefined Locales&lt;a class="anchor" href="#predefined-locales"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;The &lt;code&gt;Locales&lt;/code&gt; struct contains pre-instantiated &lt;a href="https://github.com/go-playground/locales"&gt;Go-Playground Locales&lt;/a&gt; singletons for over 200 standard language and territory combinations.&lt;/p&gt;&#10;&lt;h3 id="common-locales"&gt;Common Locales&lt;a class="anchor" href="#common-locales"&gt;&lt;/a&gt;&lt;/h3&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;github.com/BeamFoundry/rays/pkg/i18n/locales&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// English&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;EN&lt;/span&gt; &lt;span style="color:#75715e"&gt;// English (base)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;EN_US&lt;/span&gt; &lt;span style="color:#75715e"&gt;// English (United States)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;EN_GB&lt;/span&gt; &lt;span style="color:#75715e"&gt;// English (United Kingdom)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;EN_CA&lt;/span&gt; &lt;span style="color:#75715e"&gt;// English (Canada)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;EN_AU&lt;/span&gt; &lt;span style="color:#75715e"&gt;// English (Australia)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// French&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;FR&lt;/span&gt; &lt;span style="color:#75715e"&gt;// French (base)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;FR_FR&lt;/span&gt; &lt;span style="color:#75715e"&gt;// French (France)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;FR_CA&lt;/span&gt; &lt;span style="color:#75715e"&gt;// French (Canada)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;FR_BE&lt;/span&gt; &lt;span style="color:#75715e"&gt;// French (Belgium)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;FR_CH&lt;/span&gt; &lt;span style="color:#75715e"&gt;// French (Switzerland)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// German&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;DE&lt;/span&gt; &lt;span style="color:#75715e"&gt;// German (base)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;DE_DE&lt;/span&gt; &lt;span style="color:#75715e"&gt;// German (Germany)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;DE_AT&lt;/span&gt; &lt;span style="color:#75715e"&gt;// German (Austria)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;DE_CH&lt;/span&gt; &lt;span style="color:#75715e"&gt;// German (Switzerland)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Spanish&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ES&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Spanish (base)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ES_ES&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Spanish (Spain)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ES_MX&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Spanish (Mexico)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Other European Languages&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;IT&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Italian&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;PT&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Portuguese&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;PT_BR&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Portuguese (Brazil)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;NL&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Dutch&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;PL&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Polish&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;RU&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Russian&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;UK&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Ukrainian&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Asian Languages&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;JA&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Japanese&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;KO&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Korean&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ZH&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Chinese (Simplified)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ZH_TW&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Chinese (Traditional)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;VI&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Vietnamese&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;TH&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Thai&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ID&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Indonesian&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Middle Eastern Languages&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;AR&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Arabic&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;FA&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Persian / Farsi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Locales&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;TR&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Turkish&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="usage-with-message-bundles"&gt;Usage with Message Bundles&lt;a class="anchor" href="#usage-with-message-bundles"&gt;&lt;/a&gt;&lt;/h3&gt;&#10;&lt;p&gt;Pass any &lt;code&gt;Locales&lt;/code&gt; singleton to &lt;code&gt;messageSource.NewMessageBundle()&lt;/code&gt; or &lt;code&gt;messageSource.FindMessageBundle()&lt;/code&gt;:&lt;/p&gt;</description></item><item><title>Prototypes &amp; Foundries</title><link>https://rays.bfdy.dev/rays/docs/3-ioc-container/5-prototypes/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rays.bfdy.dev/rays/docs/3-ioc-container/5-prototypes/</guid><description>&lt;h1 id="prototypes--foundries"&gt;Prototypes &amp;amp; Foundries&lt;a class="anchor" href="#prototypes--foundries"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;If you need a new instance of an object every time it is requested (e.g., per HTTP request, per GRPC stream), you cannot use a Singleton. You need a &lt;strong&gt;Prototype&lt;/strong&gt;.&lt;/p&gt;&#10;&lt;h2 id="foundryt"&gt;&lt;code&gt;Foundry[T]&lt;/code&gt;&lt;a class="anchor" href="#foundryt"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;A Foundry is a type-safe factory automatically provided by the container for any struct marked with &lt;code&gt;Prototype&lt;/code&gt;.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;context&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; . &lt;span style="color:#e6db74"&gt;&amp;#34;github.com/BeamFoundry/rays/pkg/core&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; . &lt;span style="color:#e6db74"&gt;&amp;#34;github.com/BeamFoundry/rays/pkg/lang&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SessionState&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Prototype&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;userID&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Optional: Initialize state when forged&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;SessionState&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;WithContext&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;context&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Context&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;Error&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;userID&lt;/span&gt; = &lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Value&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;userID&amp;#34;&lt;/span&gt;).(&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AuthMiddleware&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Service&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;sessionFactory&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Foundry&lt;/span&gt;[&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;SessionState&lt;/span&gt;] &lt;span style="color:#e6db74"&gt;`@:&amp;#34;Inject&amp;#34;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;logger&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Logging&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`@:&amp;#34;Inject&amp;#34;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;m&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;AuthMiddleware&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;HandleHTTP&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;req&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Request&lt;/span&gt;) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 1. Forge a brand new instance&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;session&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;m&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;sessionFactory&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Forge&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;req&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Context&lt;/span&gt;())&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 2. Use the isolated prototype&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;m&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;logger&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Info&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Handle HTTP connection&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;userID&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;session&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;userID&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>6. Testing Framework</title><link>https://rays.bfdy.dev/rays/docs/6-testing/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rays.bfdy.dev/rays/docs/6-testing/</guid><description>&lt;h1 id="testing"&gt;Testing&lt;a class="anchor" href="#testing"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;Rays eliminates the pain of testing singletons by integrating natively with Ginkgo and Gomega.&lt;/p&gt;&#10;&lt;p&gt;Import the testing package and testing suites directly into your test files.&lt;/p&gt;&#10;&lt;h2 id="automatic-container-isolation"&gt;Automatic Container Isolation&lt;a class="anchor" href="#automatic-container-isolation"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;The &lt;code&gt;TestingContainer&lt;/code&gt; hooks into Ginkgo&amp;rsquo;s lifecycle. After every &lt;code&gt;It()&lt;/code&gt; block, the container is &lt;strong&gt;wiped clean&lt;/strong&gt;. Singletons do not bleed between tests.&lt;/p&gt;&#10;&lt;h2 id="targeted-wiring"&gt;Targeted Wiring&lt;a class="anchor" href="#targeted-wiring"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;By&#10;Instead of scanning the whole application, you manually register exactly the Beams you need for the unit under test using &lt;code&gt;AddBeamFor()&lt;/code&gt;.&lt;/p&gt;</description></item></channel></rss>