<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Thomas Brennetot]]></title><description><![CDATA[10+ years experienced software engineer living in Tokyo.]]></description><link>https://blog.brennetot.com</link><generator>RSS for Node</generator><lastBuildDate>Wed, 15 Apr 2026 21:43:10 GMT</lastBuildDate><atom:link href="https://blog.brennetot.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Rspec and Capybara: how to use regex or stop caring about whitespaces]]></title><description><![CDATA[I recently updated from Slim template to ERB to use Herb (Thanks Marco).
I had to update a test that was very strict on the format. I realized that Capybara::Node::Simple doesn’t provide a selector for regex.
The page object doesn’t have a match? met...]]></description><link>https://blog.brennetot.com/rspec-and-capybara-how-to-use-regex-or-stop-caring-about-whitespaces</link><guid isPermaLink="true">https://blog.brennetot.com/rspec-and-capybara-how-to-use-regex-or-stop-caring-about-whitespaces</guid><category><![CDATA[#rspec]]></category><category><![CDATA[capybara]]></category><category><![CDATA[Rails]]></category><dc:creator><![CDATA[Thomas Brennetot]]></dc:creator><pubDate>Tue, 25 Nov 2025 09:19:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1764061990404/ea863cea-64a5-4333-b638-b26e146d7591.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I recently updated from Slim template to ERB to use Herb (Thanks Marco).</p>
<p>I had to update a test that was very strict on the format. I realized that <code>Capybara::Node::Simple</code> doesn’t provide a selector for regex.</p>
<p>The <code>page</code> object doesn’t have a <code>match?</code> method</p>
<pre><code class="lang-ruby">expect(page).to have_content(<span class="hljs-string">'Name:Foobar'</span>) <span class="hljs-comment"># ✅</span>
expect(page).to match(<span class="hljs-regexp">/Name:Foobar/</span>) <span class="hljs-comment"># ❌</span>
</code></pre>
<p>I needed to use the underlying object which isn’t <code>body</code> or <code>content</code>, this time it’s <code>text</code>, cool, cool, cool, coooool</p>
<pre><code class="lang-ruby">expect(page.text).to match(<span class="hljs-regexp">/Name:\W+Foobar/</span>) <span class="hljs-comment"># ✅</span>
</code></pre>
<h3 id="heading-the-full-diff">The full diff:</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764062001817/f3611415-d53e-4e6b-92be-d80288b56f2b.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-edit-a-better-solution-for-whitespaces-normalizews">[EDIT] A better solution for whitespaces <code>normalize_ws</code></h2>
<pre><code class="lang-ruby">expect(page).to have_content(<span class="hljs-string">'Name: Foobar'</span>, <span class="hljs-symbol">normalize_ws:</span> <span class="hljs-literal">true</span>)
</code></pre>
<p>I still need to update the string to include a space but it feels a lot cleaner that way. Thanks to my coworker for the hint.</p>
]]></content:encoded></item><item><title><![CDATA[Rust, cargo with ZSH (auto complete)]]></title><description><![CDATA[It is as simple as:
rustup completions zsh > ~/.zfunc/_rustup
rustup completions zsh cargo > ~/.zfunc/_cargo

With a TAB you get the auto-complete or the options available:
❯ cargo b
b      -- alias: build
bench  -- Execute all benchmarks of a local ...]]></description><link>https://blog.brennetot.com/rust-cargo-with-zsh-auto-complete</link><guid isPermaLink="true">https://blog.brennetot.com/rust-cargo-with-zsh-auto-complete</guid><category><![CDATA[Rust]]></category><category><![CDATA[zsh]]></category><category><![CDATA[Autocomplete]]></category><category><![CDATA[autocompletion]]></category><dc:creator><![CDATA[Thomas Brennetot]]></dc:creator><pubDate>Fri, 15 Aug 2025 09:06:10 GMT</pubDate><content:encoded><![CDATA[<p>It is as simple as:</p>
<pre><code class="lang-bash">rustup completions zsh &gt; ~/.zfunc/_rustup
rustup completions zsh cargo &gt; ~/.zfunc/_cargo
</code></pre>
<p>With a <code>TAB</code> you get the auto-complete or the options available:</p>
<pre><code class="lang-bash">❯ cargo b
b      -- <span class="hljs-built_in">alias</span>: build
bench  -- Execute all benchmarks of a <span class="hljs-built_in">local</span> package
build  -- Compile a <span class="hljs-built_in">local</span> package and all of its dependencies
</code></pre>
<p>If ZSH isn’t yet configured, create the folder <code>mkdir ~/.zfunc</code> and in <code>~/.zshrc</code>:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> FPATH=<span class="hljs-string">"<span class="hljs-variable">$HOME</span>/.zfunc:<span class="hljs-variable">${FPATH}</span>"</span>
compinit
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Configuration in Rails app]]></title><description><![CDATA[Let’s not re-write a good article, go to: https://joyofrails.com/articles/mastering-custom-configuration-in-rails
I mostly used config.x configuration that loads a yaml file with config_for that do the multi-environment by default:
module YourApp
  c...]]></description><link>https://blog.brennetot.com/configuration-in-rails-app</link><guid isPermaLink="true">https://blog.brennetot.com/configuration-in-rails-app</guid><category><![CDATA[Ruby]]></category><category><![CDATA[Ruby on Rails]]></category><category><![CDATA[Rails]]></category><dc:creator><![CDATA[Thomas Brennetot]]></dc:creator><pubDate>Tue, 22 Jul 2025 16:39:24 GMT</pubDate><content:encoded><![CDATA[<p>Let’s not re-write a good article, go to: <a target="_blank" href="https://joyofrails.com/articles/mastering-custom-configuration-in-rails">https://joyofrails.com/articles/mastering-custom-configuration-in-rails</a></p>
<p>I mostly used <code>config.x</code> configuration that loads a yaml file with <code>config_for</code> that do the multi-environment by default:</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">module</span> <span class="hljs-title">YourApp</span></span>
  <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Application</span> &lt; Rails::Application</span>
    config.x.external_service_xyz = config_for(<span class="hljs-symbol">:xyz_config</span>) <span class="hljs-comment"># loading the `xyz_config.yml` file</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>This technique is also explained in the above article, check it out.</p>
]]></content:encoded></item><item><title><![CDATA[Rails load_defaults 6.1 explained]]></title><description><![CDATA[No need to re-write the wheel, let me redirect to this great article from Lily Reile. Obviously still up-to-date and really useful as the official Rails doc is mostly showing the value before and after.
https://lilyreile.medium.com/rails-6-1-new-fram...]]></description><link>https://blog.brennetot.com/rails-loaddefaults-61-explained</link><guid isPermaLink="true">https://blog.brennetot.com/rails-loaddefaults-61-explained</guid><category><![CDATA[Rails]]></category><category><![CDATA[Ruby]]></category><category><![CDATA[Ruby on Rails]]></category><category><![CDATA[rails upgrade]]></category><dc:creator><![CDATA[Thomas Brennetot]]></dc:creator><pubDate>Tue, 29 Oct 2024 04:06:41 GMT</pubDate><content:encoded><![CDATA[<p>No need to re-write the wheel, let me redirect to this great article from Lily Reile. Obviously still up-to-date and really useful as the <a target="_blank" href="https://guides.rubyonrails.org/configuring.html#default-values-for-target-version-6-1">official Rails doc</a> is mostly showing the value before and after.</p>
<p><a target="_blank" href="https://lilyreile.medium.com/rails-6-1-new-framework-defaults-what-they-do-and-how-to-safely-uncomment-them-c546b70f0c5e">https://lilyreile.medium.com/rails-6-1-new-framework-defaults-what-they-do-and-how-to-safely-uncomment-them-c546b70f0c5e</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730175057619/37010a7a-11d7-4ca6-bb5e-44a64c7a697c.jpeg" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[Appsignal V4 Ruby client changes]]></title><description><![CDATA[I came around to update Appsignal gem to the new major version of Appsignal released at the end of August 2024: https://rubygems.org/gems/appsignal/versions/4.0.0
The upgrade was smooth. The real change for my application was to remove the parameter ...]]></description><link>https://blog.brennetot.com/appsignal-v4-ruby-client-changes</link><guid isPermaLink="true">https://blog.brennetot.com/appsignal-v4-ruby-client-changes</guid><category><![CDATA[Ruby]]></category><category><![CDATA[AppSignal]]></category><category><![CDATA[upgrade]]></category><dc:creator><![CDATA[Thomas Brennetot]]></dc:creator><pubDate>Fri, 13 Sep 2024 06:32:21 GMT</pubDate><content:encoded><![CDATA[<p>I came around to update Appsignal gem to the new major version of Appsignal released at the end of August 2024: <a target="_blank" href="https://rubygems.org/gems/appsignal/versions/4.0.0">https://rubygems.org/gems/appsignal/versions/4.0.0</a></p>
<p>The upgrade was smooth. The real change for my application was to remove the parameter to block to <code>.report_error</code> and use the <code>Appsignal</code> name instead. See for yourself:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726189231877/b0870697-38a6-4ea4-969a-6105225c9c3d.png" alt class="image--center mx-auto" /></p>
<p>There are more changes. In my case, it was the only one needed.</p>
]]></content:encoded></item><item><title><![CDATA[Rails 7.0 schema.rb changes]]></title><description><![CDATA[During a recent (and first) upgrade of Rails to 7.0, I found a lot of changes in the schema.rb file.
There is the self explanatory one: add versioning to the schema file.

And the noisy change of every single datatime field's precision attribute.

Lo...]]></description><link>https://blog.brennetot.com/rails-70-schemarb-changes</link><guid isPermaLink="true">https://blog.brennetot.com/rails-70-schemarb-changes</guid><category><![CDATA[rails upgrade]]></category><category><![CDATA[rails 7.0]]></category><category><![CDATA[schema.rb]]></category><category><![CDATA[Rails]]></category><dc:creator><![CDATA[Thomas Brennetot]]></dc:creator><pubDate>Tue, 03 Sep 2024 06:35:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1725345318962/627c133b-4cbc-45d9-ba42-3bef4a6bd653.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>During a recent (and first) upgrade of Rails to 7.0, I found a lot of changes in the <code>schema.rb</code> file.</p>
<p>There is the self explanatory one: add versioning to the schema file.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725344489375/e7bfc949-9c57-4756-8f92-c89c7a637619.png" alt class="image--center mx-auto" /></p>
<p>And the noisy change of every single <code>datatime</code> field's <code>precision</code> attribute.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725344657574/0d52722f-8f41-4fc5-afe9-c0f3d7479b96.png" alt class="image--center mx-auto" /></p>
<p>Looking at this, I find out that the <code>precision</code> default to <code>6</code>. It explains why some attributes got <code>precision: nil</code> and some other got their <code>precision: 6</code> removed.</p>
<p><a target="_blank" href="https://github.com/rails/rails/blob/aed8feae3b7a3f7df59de69355cc3bda1d5479d6/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb#L1322">https://github.com/rails/rails/blob/aed8feae3b7a3f7df59de69355cc3bda1d5479d6/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb#L1322</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725345398419/29fa49a5-ed60-4cbf-bce9-458fc00d8acc.png" alt class="image--center mx-auto" /></p>
<p>This was a change made in 2019 and released from Rails 7.0 in December 2021. So, 2.5 years after but I'm happy to discover that and sharing it.</p>
<p><a target="_blank" href="https://github.com/rails/rails/commit/57015cdfa2083351f64a82f7566965172a41efcb#diff-868f1dccfcbed26a288bf9f3fd8a39c863a4413ab0075e12b6805d9798f556d1R714-R716">https://github.com/rails/rails/commit/57015cdfa2083351f64a82f7566965172a41efcb#diff-868f1dccfcbed26a288bf9f3fd8a39c863a4413ab0075e12b6805d9798f556d1R714-R716</a></p>
<p>For people following here, Rails 7.1 is already planned and is already passing the entire test suite. Hopefully, it won't take long.</p>
<p>Cheers!</p>
]]></content:encoded></item><item><title><![CDATA[AppSignal logs from AWS CloudWatch: CloudFormation template!]]></title><description><![CDATA[Don't you think the documentation for forwarding the logs from AWS CloudWatch to AppSignal lengthy?
Doc: https://docs.appsignal.com/logging/platforms/cloudwatch.html
Same here! But you are in luck, here's the script I used to do all steps at once!
Yo...]]></description><link>https://blog.brennetot.com/appsignal-logs-from-aws-cloudwatch-cloudformation-template</link><guid isPermaLink="true">https://blog.brennetot.com/appsignal-logs-from-aws-cloudwatch-cloudformation-template</guid><category><![CDATA[AppSignal]]></category><category><![CDATA[cloudformation]]></category><category><![CDATA[#CloudWatch]]></category><category><![CDATA[AWS]]></category><dc:creator><![CDATA[Thomas Brennetot]]></dc:creator><pubDate>Fri, 16 Aug 2024 03:03:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1723777351502/85f81463-24fa-4aaa-b7f1-18d845d89fab.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Don't you think the documentation for forwarding the logs from AWS CloudWatch to AppSignal lengthy?</p>
<p>Doc: <a target="_blank" href="https://docs.appsignal.com/logging/platforms/cloudwatch.html">https://docs.appsignal.com/logging/platforms/cloudwatch.html</a></p>
<p>Same here! But you are in luck, here's the script I used to do all steps at once!</p>
<p>You only need the AppSignal token (given after you created a new CloudWatch source) and the CloudWatch group log name (not the ARN).</p>
<p>The CloudWatch template: <a target="_blank" href="https://gist.github.com/D-system/6dc155100de058b8a7c4c58b136d5bf1">https://gist.github.com/D-system/6dc155100de058b8a7c4c58b136d5bf1</a></p>
<p>I provided their support with the template and invited them to add the CloudFormation template to their doc 😀 Let's see if it'll be added.</p>
]]></content:encoded></item><item><title><![CDATA[Git rename branch on remote]]></title><description><![CDATA[It's impossible ... but, you can copy a branch then delete the old one.
On the remote named origin (the default name), copy the master branch in new main branch.
git push origin origin/master:refs/heads/main

To delete the old master branch (the : me...]]></description><link>https://blog.brennetot.com/git-rename-branch-on-remote</link><guid isPermaLink="true">https://blog.brennetot.com/git-rename-branch-on-remote</guid><category><![CDATA[Git]]></category><category><![CDATA[GitHub]]></category><dc:creator><![CDATA[Thomas Brennetot]]></dc:creator><pubDate>Thu, 25 Jul 2024 06:49:53 GMT</pubDate><content:encoded><![CDATA[<p>It's impossible ... but, you can copy a branch then delete the old one.</p>
<p>On the remote named <code>origin</code> (the default name), copy the <code>master</code> branch in new <code>main</code> branch.</p>
<pre><code class="lang-bash">git push origin origin/master:refs/heads/main
</code></pre>
<p>To delete the old <code>master</code> branch (the <code>:</code> means delete)</p>
<pre><code class="lang-bash">git push origin :master
</code></pre>
<p>FYI: the <code>:master</code> part, from the second command, can be put at the end of the first command to have a one line command.</p>
]]></content:encoded></item><item><title><![CDATA[Rails database replica setup]]></title><description><![CDATA[While reading the official documentation, I did not understand some parts of the set up. Let's me explain here.
My setup:

1 main database

1 replica


What I did not understand:

Where to put the connects_to setting

Proper/clean configuration in da...]]></description><link>https://blog.brennetot.com/rails-database-replica-setup</link><guid isPermaLink="true">https://blog.brennetot.com/rails-database-replica-setup</guid><category><![CDATA[Rails]]></category><category><![CDATA[Ruby]]></category><category><![CDATA[Ruby on Rails]]></category><category><![CDATA[replication]]></category><category><![CDATA[replica]]></category><dc:creator><![CDATA[Thomas Brennetot]]></dc:creator><pubDate>Mon, 10 Jun 2024 03:03:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1717988569500/6c98869a-1389-4d93-9869-da25f2a0202f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>While reading the official <a target="_blank" href="https://edgeguides.rubyonrails.org/active_record_multiple_databases.html">documentation</a>, I did not understand some parts of the set up. Let's me explain here.</p>
<h3 id="heading-my-setup">My setup:</h3>
<ul>
<li><p>1 main database</p>
</li>
<li><p>1 replica</p>
</li>
</ul>
<h3 id="heading-what-i-did-not-understand">What I did not understand:</h3>
<ul>
<li><p>Where to put the <code>connects_to</code> setting</p>
</li>
<li><p>Proper/clean configuration in <code>database.yml</code></p>
</li>
</ul>
<h3 id="heading-the-databaseyml">The <code>database.yml</code></h3>
<p>Notes:</p>
<ul>
<li><p>All environment needs <code>primary</code> and <code>primary_replica</code> otherwise Rails will raise an exception (at boot).</p>
</li>
<li><p>The <code>*_replica</code> needs <code>replica: true</code></p>
</li>
<li><p>I did not put <code>primary</code> and <code>primary_replica</code> inside <code>default</code> because any change in a sub-object will erase all properties (I think)</p>
</li>
<li><p>In that example, only production has a proper replica with different settings</p>
</li>
</ul>
<pre><code class="lang-yaml"><span class="hljs-attr">default:</span> <span class="hljs-meta">&amp;default</span>
  <span class="hljs-attr">adapter:</span> <span class="hljs-string">trilogy</span>
  <span class="hljs-attr">encoding:</span> <span class="hljs-string">utf8mb4</span>
  <span class="hljs-attr">pool:</span> <span class="hljs-number">5</span>
  <span class="hljs-attr">database:</span> &lt;%=<span class="ruby"> ENV.fetch(<span class="hljs-string">'DB_NAME'</span>) { <span class="hljs-string">'db_name'</span> } </span>%&gt;
  <span class="hljs-attr">username:</span> &lt;%=<span class="ruby"> ENV.fetch(<span class="hljs-string">'DB_USER'</span>) { <span class="hljs-string">'user'</span> } </span>%&gt;
  <span class="hljs-attr">password:</span> &lt;%=<span class="ruby"> ENV.fetch(<span class="hljs-string">'DB_PASS'</span>) { <span class="hljs-string">'password'</span> } </span>%&gt;
  <span class="hljs-attr">host:</span> &lt;%=<span class="ruby"> ENV.fetch(<span class="hljs-string">'DB_HOST'</span>) { <span class="hljs-string">'db.example.com'</span> } </span>%&gt;
  <span class="hljs-attr">port:</span> &lt;%=<span class="ruby"> ENV.fetch(<span class="hljs-string">'DB_PORT'</span>) { <span class="hljs-string">'3306'</span> } </span>%&gt;

<span class="hljs-attr">development:</span>
  <span class="hljs-attr">primary:</span>
    <span class="hljs-string">&lt;&lt;:</span> <span class="hljs-meta">*default</span>
  <span class="hljs-attr">primary_replica:</span>
    <span class="hljs-string">&lt;&lt;:</span> <span class="hljs-meta">*default</span>
    <span class="hljs-attr">replica:</span> <span class="hljs-literal">true</span>

<span class="hljs-attr">test:</span>
  <span class="hljs-attr">primary:</span>
    <span class="hljs-string">&lt;&lt;:</span> <span class="hljs-meta">*default</span>
  <span class="hljs-attr">primary_replica:</span>
    <span class="hljs-string">&lt;&lt;:</span> <span class="hljs-meta">*default</span>
    <span class="hljs-attr">replica:</span> <span class="hljs-literal">true</span>

<span class="hljs-attr">staging:</span>
  <span class="hljs-attr">primary:</span>
    <span class="hljs-string">&lt;&lt;:</span> <span class="hljs-meta">*default</span>
  <span class="hljs-attr">primary_replica:</span>
    <span class="hljs-string">&lt;&lt;:</span> <span class="hljs-meta">*default</span>
    <span class="hljs-attr">replica:</span> <span class="hljs-literal">true</span>

<span class="hljs-attr">production:</span>
  <span class="hljs-attr">primary:</span>
    <span class="hljs-string">&lt;&lt;:</span> <span class="hljs-meta">*default</span>
  <span class="hljs-attr">primary_replica:</span>
    <span class="hljs-string">&lt;&lt;:</span> <span class="hljs-meta">*default</span>
    <span class="hljs-attr">username:</span> &lt;%=<span class="ruby"> ENV.fetch(<span class="hljs-string">'DB_USER_REPLICA'</span>) { <span class="hljs-string">'user_replica'</span> } </span>%&gt;
    <span class="hljs-attr">password:</span> &lt;%=<span class="ruby"> ENV.fetch(<span class="hljs-string">'DB_PASS_REPLICA'</span>) { <span class="hljs-string">'password_replica'</span> } </span>%&gt;
    <span class="hljs-attr">host:</span> &lt;%=<span class="ruby"> ENV.fetch(<span class="hljs-string">'DB_HOST_REPLICA'</span>) { <span class="hljs-string">'db-replica.example.com'</span> } </span>%&gt;
    <span class="hljs-attr">replica:</span> <span class="hljs-literal">true</span>
</code></pre>
<h3 id="heading-model-set-up-connectsto">Model set-up: <code>connects_to</code></h3>
<p>I thought I could use <code>connects_to</code> directly on a model (eg: <code>User</code>) but no, it should be on <code>an abstract_class or ActiveRecord::Base</code> (what the exception says) but I didn't understand it. I thought I should put <code>abstract_class</code> on the <code>User</code> but no, it should the parent class <code>ApplicationRecord</code> or anything other parent class (eg: <code>AdminApplicationRecord</code> for admin user).</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ApplicationRecord</span> &lt; ActiveRecord::Base</span>
  <span class="hljs-keyword">self</span>.abstract_class = <span class="hljs-literal">true</span>
  connects_to <span class="hljs-symbol">database:</span> {
    <span class="hljs-symbol">writing:</span> <span class="hljs-symbol">:primary</span>,
    <span class="hljs-symbol">reading:</span> <span class="hljs-symbol">:primary_replica</span>
  }
<span class="hljs-keyword">end</span>
</code></pre>
<p>If it helped, please share it.</p>
<p>Have fun, bye.</p>
]]></content:encoded></item><item><title><![CDATA[Ruby 3.3 shipped in prod]]></title><description><![CDATA[On 2024-04-30, I released the Ruby 3.3.1 (from 3.2.3) with success. It been 10 days since, no problem in production or local environments.
The main reason to wait for the x.y.1 was due to some issues with 1 or 2 bugs in the arm64 implementation.

The...]]></description><link>https://blog.brennetot.com/ruby-33-shipped-in-prod</link><guid isPermaLink="true">https://blog.brennetot.com/ruby-33-shipped-in-prod</guid><category><![CDATA[shipped]]></category><category><![CDATA[Ruby]]></category><category><![CDATA[Rails]]></category><dc:creator><![CDATA[Thomas Brennetot]]></dc:creator><pubDate>Thu, 09 May 2024 05:27:25 GMT</pubDate><content:encoded><![CDATA[<p>On 2024-04-30, I released the Ruby 3.3.1 (from 3.2.3) with success. It been 10 days since, no problem in production or local environments.</p>
<p>The main reason to wait for the x.y.1 was due to some issues with 1 or 2 bugs in the arm64 implementation.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715231457936/b3594704-1e83-43a9-bd11-b774b1157d60.png" alt class="image--center mx-auto" /></p>
<p>The real change for my company is the memory usage on our staging environment.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715231746722/7d4d8215-b75a-41e6-98e8-cb29359fdbe8.png" alt class="image--center mx-auto" /></p>
<p>There's also a decrease in the CPU in prod too</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715233019650/9218dd46-e2c1-438e-9395-1f9ee7c5b753.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-if-you-are-in-the-ruby-kaigi-2024-next-week-ill-see-you-there">If you are in the Ruby Kaigi 2024 next week, I'll see you there!</h2>
]]></content:encoded></item><item><title><![CDATA[Japanese characters transcoding: stop using Shift-JIS for the source]]></title><description><![CDATA[So, last day I got an encoding error. The data is what I though was in Shift-JIS but it could not be converted to UTF-8 because in Shift-JIS ‡ U+0087 does not exists.

It's is multiple used as title like so:

https://www.htmlsymbols.xyz/unicode/U+008...]]></description><link>https://blog.brennetot.com/japanese-characters-transcoding-stop-using-shift-jis-for-the-source</link><guid isPermaLink="true">https://blog.brennetot.com/japanese-characters-transcoding-stop-using-shift-jis-for-the-source</guid><category><![CDATA[japanese encosing]]></category><category><![CDATA[charset]]></category><category><![CDATA[Shift-JIS]]></category><category><![CDATA[utf8]]></category><dc:creator><![CDATA[Thomas Brennetot]]></dc:creator><pubDate>Wed, 17 Apr 2024 06:20:00 GMT</pubDate><content:encoded><![CDATA[<p>So, last day I got an encoding error. The data is what I though was in Shift-JIS but it could not be converted to UTF-8 because in Shift-JIS <code>‡</code> U+0087 does not exists.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713333976175/9ff3e163-0418-444f-a1d9-5e3dbc06c526.png" alt class="image--center mx-auto" /></p>
<p>It's is multiple used as title like so:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713334233487/584977da-86eb-404b-91b9-55d392b40f37.png" alt class="image--center mx-auto" /></p>
<p><a target="_blank" href="https://www.htmlsymbols.xyz/unicode/U+0087">https://www.htmlsymbols.xyz/unicode/U+0087</a></p>
<h1 id="heading-solution">Solution:</h1>
<p>In Windows, apparently, instead of the strict Shift-JIS, they are using CP932 which is superset of Shift-JIS (meaning it's Shift-JIS with additional characters).</p>
<h3 id="heading-please-use-cp932-encoding-when-dealing-with-japanese-characters">Please use <code>CP932</code> encoding when dealing with Japanese characters.</h3>
<p>The Rubyist out there, it will be:</p>
<pre><code class="lang-ruby">CSV.read(<span class="hljs-string">"csvfile.csv"</span>, <span class="hljs-symbol">encoding:</span> <span class="hljs-string">"CP932:UTF-8"</span>)
</code></pre>
]]></content:encoded></item><item><title><![CDATA[[Quicky] Unused routes for Rails 7.0 below]]></title><description><![CDATA[With Rails 7.1, you can list unused routes with:
./bin/rails routes --unused

For Rails 6.0, 6.1 and 7.0, below is a script I used in my project to find out unused routes. Apparently, I barrow it from ShakaCode. Thanks to them.
In conjunction with th...]]></description><link>https://blog.brennetot.com/quicky-unused-routes-for-rails-70-below</link><guid isPermaLink="true">https://blog.brennetot.com/quicky-unused-routes-for-rails-70-below</guid><category><![CDATA[unused-routes]]></category><category><![CDATA[unused-code]]></category><category><![CDATA[Ruby]]></category><category><![CDATA[Ruby on Rails]]></category><category><![CDATA[unused]]></category><dc:creator><![CDATA[Thomas Brennetot]]></dc:creator><pubDate>Wed, 13 Mar 2024 08:46:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1710319543816/fa4fc33e-503e-42e8-bbda-8f93a8244578.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>With <a target="_blank" href="https://github.com/rails/rails/pull/45701">Rails 7.1</a>, you can list unused routes with:</p>
<pre><code class="lang-plaintext">./bin/rails routes --unused
</code></pre>
<p>For Rails 6.0, 6.1 and 7.0, below is a script I used in my project to find out unused routes. Apparently, I barrow it from <a target="_blank" href="https://www.shakacode.com/blog/identify-unused-routes-in-rails-7/">ShakaCode</a>. Thanks to them.</p>
<p>In conjunction with the <a target="_blank" href="https://blog.brennetot.com/quicky-self-contained-rails-script">self contained rails script shown before</a>, here's the full modified script:</p>
<pre><code class="lang-ruby"><span class="hljs-comment">#!/usr/bin/env ruby</span>
APP_PATH = File.expand_path(<span class="hljs-string">"../../config/application"</span>,  __FILE_<span class="hljs-number">_</span>)
<span class="hljs-keyword">require</span> File.expand_path(<span class="hljs-string">"../../config/boot"</span>,  __FILE_<span class="hljs-number">_</span>)
<span class="hljs-keyword">require</span> APP_PATH

Rails.application.require_environment!

unused_routes = {}

Rails.application.routes.routes.each <span class="hljs-keyword">do</span> <span class="hljs-params">|r|</span>
  name = r.requirements[<span class="hljs-symbol">:controller</span>].to_s.camelize
  action = r.requirements[<span class="hljs-symbol">:action</span>].to_s
  controller = <span class="hljs-string">"<span class="hljs-subst">#{name}</span>Controller"</span>

  <span class="hljs-keyword">if</span> Object.const_defined?(controller) &amp;&amp; !controller.constantize.new.respond_to?(action)
    <span class="hljs-keyword">unless</span> Dir.glob(Rails.root.join(<span class="hljs-string">"app"</span>, <span class="hljs-string">"views"</span>, name.downcase, <span class="hljs-string">"<span class="hljs-subst">#{action}</span>.*"</span>)).any?
      unused_routes[controller] = [] <span class="hljs-keyword">if</span> unused_routes[controller].<span class="hljs-literal">nil</span>?
      unused_routes[controller] &lt;&lt; action
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>

pp unused_routes
</code></pre>
<p>The script is in the file <code>bin/unused_routes</code>. And it's an executable (<code>chmod +x bin/unused_routes</code>).</p>
<p>With that, you only need to run the command below. No more need to remember or search for it, everything lives in your repository.</p>
<pre><code class="lang-plaintext">./bin/unused_routes
</code></pre>
<h3 id="heading-magical">Magical!</h3>
]]></content:encoded></item><item><title><![CDATA[[Quicky] Self contained Rails script]]></title><description><![CDATA[To run a script with your Rails application setup use rails runner https://guides.rubyonrails.org/command_line.html#bin-rails-runner
# inline script
./bin/rails runner "puts Rails.env"

# file
./bin/rails runner path/to/file.rb

If you want to have a...]]></description><link>https://blog.brennetot.com/quicky-self-contained-rails-script</link><guid isPermaLink="true">https://blog.brennetot.com/quicky-self-contained-rails-script</guid><category><![CDATA[Rails]]></category><category><![CDATA[Ruby on Rails]]></category><category><![CDATA[Script]]></category><dc:creator><![CDATA[Thomas Brennetot]]></dc:creator><pubDate>Wed, 13 Mar 2024 08:33:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1710318775142/e0d2022e-d354-4a20-beaa-be398dda5cc6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>To run a script with your Rails application setup use <code>rails runner</code> <a target="_blank" href="https://guides.rubyonrails.org/command_line.html#bin-rails-runner">https://guides.rubyonrails.org/command_line.html#bin-rails-runner</a></p>
<pre><code class="lang-scala"># inline script
./bin/rails runner <span class="hljs-string">"puts Rails.env"</span>

# file
./bin/rails runner path/to/file.rb
</code></pre>
<p>If you want to have a self container, here's what you need (eg: filename <code>bin/puts_env</code>):</p>
<pre><code class="lang-ruby"><span class="hljs-comment">#!/usr/bin/env ruby</span>
APP_PATH = File.expand_path(<span class="hljs-string">"../../config/application"</span>,  __FILE_<span class="hljs-number">_</span>)
<span class="hljs-keyword">require</span> File.expand_path(<span class="hljs-string">"../../config/boot"</span>,  __FILE_<span class="hljs-number">_</span>)
<span class="hljs-keyword">require</span> APP_PATH

Rails.application.require_environment!


<span class="hljs-comment">###### Your script below</span>
puts Rails.env
</code></pre>
<p>Don't forget to make the file executable:</p>
<pre><code class="lang-plaintext">chmod +x bin/puts_env
</code></pre>
<p>Now you can run the script, no more need to remember how to run it, just do:</p>
<pre><code class="lang-plaintext">./bin/puts_env
</code></pre>
<h2 id="heading-magical">Magical!</h2>
]]></content:encoded></item><item><title><![CDATA[[Quicky] Easy Ruby regexp to split string]]></title><description><![CDATA[Are you good at regexp? I'm not and I found an extremely easy way to update a regexp to split a string in Ruby.
Input
abc,abc
abc abc
abc

I just want to split on , , a space ... and a new line. Great
I won't show you an horrible .split with a .map t...]]></description><link>https://blog.brennetot.com/quicky-easy-ruby-regexp-to-split-string</link><guid isPermaLink="true">https://blog.brennetot.com/quicky-easy-ruby-regexp-to-split-string</guid><category><![CDATA[Ruby]]></category><category><![CDATA[Ruby on Rails]]></category><category><![CDATA[Regex]]></category><category><![CDATA[Regexp]]></category><category><![CDATA[regex basics]]></category><dc:creator><![CDATA[Thomas Brennetot]]></dc:creator><pubDate>Tue, 12 Mar 2024 01:09:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1710205737600/94b9203f-e3b5-4dc2-a35f-6a8d7785fb77.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Are you good at regexp? I'm not and I found an extremely easy way to update a regexp to split a string in Ruby.</p>
<h4 id="heading-input">Input</h4>
<pre><code class="lang-plaintext">abc,abc
abc abc
abc
</code></pre>
<p>I just want to split on <code>,</code> , a space ... and a new line. Great</p>
<p>I won't show you an horrible <code>.split</code> with a <code>.map</code> then redo a <code>.split</code> again.</p>
<h4 id="heading-use-regexp">Use regexp</h4>
<pre><code class="lang-ruby">regexp = <span class="hljs-regexp">/[ ,\n]/</span>
input.split(regexp)
</code></pre>
<p>It is annoying to read (even that simple) and it did not work for what I wanted. Remember the "new line", as a html input/textarea is not an <code>\n</code> but an <code>\r\n</code> .</p>
<p>You can change the regexp to <code>/[ ,\r\n]/</code> but it split twice, once for <code>\r</code> then once more for <code>\n</code>. And the readability is lower.</p>
<h4 id="heading-solution-union">Solution: Union!</h4>
<pre><code class="lang-ruby">regexp = Regexp.union([<span class="hljs-string">" "</span>, <span class="hljs-string">"\r\n"</span>, <span class="hljs-string">"\n"</span>, <span class="hljs-string">","</span>])
input.split(regexp)
</code></pre>
<p>You give the string you want the regexp to split on and it generates the proper Regexp for you.</p>
<p>It won't solve all but for me, it solve most of my simple cases with code that I use everyday: a dead simple list of string.</p>
<p>Share it!</p>
<p>Cheers, Thomas</p>
]]></content:encoded></item><item><title><![CDATA[Devise logout after 1 day or 30 minutes inactive]]></title><description><![CDATA[The gem Devise is great for authentication for Rails applications.
https://github.com/heartcombo/devise
For some sensitive application, you want to logout the user aggressively.
For example: a banking app. You want users to re-login if inactive for m...]]></description><link>https://blog.brennetot.com/devise-logout-after-1-day-or-30-minutes-inactive</link><guid isPermaLink="true">https://blog.brennetot.com/devise-logout-after-1-day-or-30-minutes-inactive</guid><category><![CDATA[login-timeout]]></category><category><![CDATA[Rails]]></category><category><![CDATA[devise]]></category><category><![CDATA[gem]]></category><category><![CDATA[login]]></category><category><![CDATA[timeout]]></category><dc:creator><![CDATA[Thomas Brennetot]]></dc:creator><pubDate>Mon, 04 Mar 2024 09:38:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1709542157049/d73a1d2d-9d3f-4eae-bcf3-3ce95f4035b5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The gem Devise is great for authentication for Rails applications.</p>
<p><a target="_blank" href="https://github.com/heartcombo/devise">https://github.com/heartcombo/devise</a></p>
<p>For some sensitive application, you want to <strong>logout the user aggressively</strong>.</p>
<p>For example: <strong>a banking app</strong>. You want users to <strong>re-login if inactive</strong> for more then 30 minutes but keep them logged in if active.</p>
<p>Add <code>:rememberable</code> and <code>:timeoutable</code> to the <code>devise</code> method on the model.</p>
<pre><code class="lang-ruby"><span class="hljs-comment"># app/models/user.rb</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> &lt; ActiveRecord::Base</span>
  devise <span class="hljs-symbol">:database_authenticatable</span>,
         <span class="hljs-symbol">:rememberable</span>,
         <span class="hljs-symbol">:timeoutable</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>The main configuration to change are: <code>remember_for</code> and <code>timeout_in</code>.</p>
<pre><code class="lang-ruby"><span class="hljs-comment"># config/initializers/devise.rb</span>

Devise.setup <span class="hljs-keyword">do</span> <span class="hljs-params">|config|</span>
  <span class="hljs-comment"># [...]</span>

  <span class="hljs-comment"># ==&gt; Configuration for :rememberable</span>
  <span class="hljs-comment"># The time the user will be remembered without asking for credentials again.</span>
  config.remember_for = <span class="hljs-number">1</span>.day

  <span class="hljs-comment"># Invalidates all the remember me tokens when the user signs out.</span>
  config.expire_all_remember_me_on_sign_out = <span class="hljs-literal">true</span>

  <span class="hljs-comment"># ==&gt; Configuration for :timeoutable</span>
  <span class="hljs-comment"># The time you want to timeout the user session without activity. After this</span>
  <span class="hljs-comment"># time the user will be asked for credentials again. Default is 30 minutes.</span>
  config.timeout_in = <span class="hljs-number">30</span>.minutes

  <span class="hljs-comment"># [...]</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>That's all 🎉</p>
<p>Please share. If you have any suggestions, please comment.</p>
]]></content:encoded></item><item><title><![CDATA[My configuration for IRB: highlight Rails.env]]></title><description><![CDATA[Never forget the environment you are in.

# .irbrc
module ColorString
  refine String do
    def cyan = "\e[36m#{self}\e[0m"
    def bg_red = "\e[41m#{self}\e[0m"
    def bg_yellow = "\e[43m#{self}\e[0m"
    def bg_green = "\e[42m#{self}\e[0m"
  end
...]]></description><link>https://blog.brennetot.com/my-configuration-for-irb-highlight-railsenv</link><guid isPermaLink="true">https://blog.brennetot.com/my-configuration-for-irb-highlight-railsenv</guid><category><![CDATA[Ruby]]></category><category><![CDATA[Ruby on Rails]]></category><category><![CDATA[irb]]></category><category><![CDATA[console]]></category><dc:creator><![CDATA[Thomas Brennetot]]></dc:creator><pubDate>Wed, 28 Feb 2024 04:51:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1709097795583/b9258938-782d-46d3-8de2-e2e7a300df8a.avif" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Never forget the environment you are in.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1709095760666/c8d2eb68-5895-49ca-b8c7-3aea2ed13521.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-ruby"><span class="hljs-comment"># .irbrc</span>
<span class="hljs-class"><span class="hljs-keyword">module</span> <span class="hljs-title">ColorString</span></span>
  refine String <span class="hljs-keyword">do</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">cyan</span> = "\<span class="hljs-title">e</span>[36<span class="hljs-title">m</span><span class="hljs-comment">#{self}\e[0m"</span></span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">bg_red</span> = "\<span class="hljs-title">e</span>[41<span class="hljs-title">m</span><span class="hljs-comment">#{self}\e[0m"</span></span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">bg_yellow</span> = "\<span class="hljs-title">e</span>[43<span class="hljs-title">m</span><span class="hljs-comment">#{self}\e[0m"</span></span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">bg_green</span> = "\<span class="hljs-title">e</span>[42<span class="hljs-title">m</span><span class="hljs-comment">#{self}\e[0m"</span></span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>

<span class="hljs-keyword">if</span> <span class="hljs-keyword">defined</span>?(Rails)
  using ColorString

  <span class="hljs-keyword">if</span> Rails.env.production? <span class="hljs-params">||</span> Rails.env.staging?
    IRB.conf[<span class="hljs-symbol">:SAVE_HISTORY</span>] = <span class="hljs-literal">false</span>
  <span class="hljs-keyword">end</span>

  project_name = File.basename(Dir.pwd).cyan
  environment = <span class="hljs-keyword">case</span> Rails.env
                <span class="hljs-keyword">when</span> <span class="hljs-string">"development"</span>
                  Rails.env.bg_green
                <span class="hljs-keyword">when</span> <span class="hljs-string">"staging"</span>
                  Rails.env.bg_yellow
                <span class="hljs-keyword">when</span> <span class="hljs-string">"production"</span>
                  Rails.env.bg_red
                <span class="hljs-keyword">end</span>
  prompt = <span class="hljs-string">"<span class="hljs-subst">#{project_name}</span> [<span class="hljs-subst">#{environment}</span>]"</span>

  IRB.conf[<span class="hljs-symbol">:PROMPT</span>] <span class="hljs-params">||</span>= {}
  IRB.conf[<span class="hljs-symbol">:PROMPT</span>][<span class="hljs-symbol">:RAILS</span>] = {
    <span class="hljs-symbol">PROMPT_I:</span> <span class="hljs-string">"<span class="hljs-subst">#{prompt}</span> %03n &gt; "</span>,
    <span class="hljs-symbol">PROMPT_S:</span> <span class="hljs-string">"<span class="hljs-subst">#{prompt}</span> %03n * "</span>,
    <span class="hljs-symbol">PROMPT_C:</span> <span class="hljs-string">"<span class="hljs-subst">#{prompt}</span> %03n ? "</span>,
    <span class="hljs-symbol">RETURN:</span> <span class="hljs-string">"=&gt; %s\n"</span>
  }

  IRB.conf[<span class="hljs-symbol">:PROMPT_MODE</span>] = <span class="hljs-symbol">:RAILS</span>
<span class="hljs-keyword">end</span>

<span class="hljs-keyword">begin</span>
  <span class="hljs-keyword">require</span> <span class="hljs-string">"awesome_print"</span>
  AwesomePrint.irb!
  <span class="hljs-keyword">rescue</span>
<span class="hljs-keyword">end</span>
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Tagged logs in Rails/ActiveSupport]]></title><description><![CDATA[What's tags in logs?
It's from Rails' ActiveSupport to prepend automatically the logs with a parameter.
https://api.rubyonrails.org/classes/ActiveSupport/TaggedLogging.html
Rails.logger.tagged("background_job_number_1") do
 Rails.logger.error("Thing ...]]></description><link>https://blog.brennetot.com/tagged-logs-in-railsactivesupport</link><guid isPermaLink="true">https://blog.brennetot.com/tagged-logs-in-railsactivesupport</guid><category><![CDATA[Rails]]></category><category><![CDATA[logging]]></category><dc:creator><![CDATA[Thomas Brennetot]]></dc:creator><pubDate>Tue, 20 Feb 2024 04:43:24 GMT</pubDate><content:encoded><![CDATA[<h3 id="heading-whats-tags-in-logs">What's tags in logs?</h3>
<p>It's from Rails' ActiveSupport to prepend <strong>automatically</strong> the logs with a parameter.</p>
<p><a target="_blank" href="https://api.rubyonrails.org/classes/ActiveSupport/TaggedLogging.html">https://api.rubyonrails.org/classes/ActiveSupport/TaggedLogging.html</a></p>
<pre><code class="lang-ruby">Rails.logger.tagged(<span class="hljs-string">"background_job_number_1"</span>) <span class="hljs-keyword">do</span>
 Rails.logger.error(<span class="hljs-string">"Thing went wrong for user XXX"</span>)
<span class="hljs-keyword">end</span>
<span class="hljs-comment">#=&gt; [background_job_number_1] Thing went wrong for user XXX</span>
</code></pre>
<p>It's very useful in many cases, specially in a background system or a shared code that method:</p>
<pre><code class="lang-ruby"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">shared_method</span></span>
  <span class="hljs-keyword">if</span> <span class="hljs-literal">true</span>
    Rails.logger.info(<span class="hljs-string">"User XXX: done"</span>)
  <span class="hljs-keyword">else</span>
    Rails.logger.error(<span class="hljs-string">"User XXX: failure"</span>)
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">user_update_flow</span></span>
  Rails.logger.tagged(<span class="hljs-string">"user_update_flow"</span>) <span class="hljs-keyword">do</span>
    shared_method
    <span class="hljs-comment"># Log: [user_update_flow] User <span class="hljs-doctag">XXX:</span> done</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">user_create_flow</span></span>
  Rails.logger.tagged(<span class="hljs-string">"user_create_flow"</span>) <span class="hljs-keyword">do</span>
     shared_method
    <span class="hljs-comment"># Log: [user_create_flow] User <span class="hljs-doctag">XXX:</span> done</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>In that example, depending on the caller, the logs will be prepend with the expected tag or tags.</p>
<p>Feel free to shared and comment.</p>
]]></content:encoded></item><item><title><![CDATA[[Quicky] VScode: stickyScroll]]></title><description><![CDATA[On a long file or method, it is nice to see where you are at a glance (see the discontinued line number).

It's possible with stickyScroll. The default contrast is low but you can change them in colorCustomizations.
// settings.json
    "editor.stick...]]></description><link>https://blog.brennetot.com/quicky-vscode-stickyscroll</link><guid isPermaLink="true">https://blog.brennetot.com/quicky-vscode-stickyscroll</guid><category><![CDATA[VSCode Tips]]></category><category><![CDATA[vscode]]></category><dc:creator><![CDATA[Thomas Brennetot]]></dc:creator><pubDate>Thu, 15 Feb 2024 00:43:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1709097858787/0b6d5d0c-5b59-40c7-b0f1-c5daa95f7209.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>On a long file or method, it is nice to see where you are at a glance (see the discontinued line number).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707956969064/6e03b65f-4285-44af-9146-64870af75c44.png" alt class="image--center mx-auto" /></p>
<p>It's possible with <code>stickyScroll</code>. The default contrast is low but you can change them in <code>colorCustomizations</code>.</p>
<pre><code class="lang-json"><span class="hljs-comment">// settings.json</span>
    <span class="hljs-string">"editor.stickyScroll.enabled"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-string">"workbench.colorCustomizations"</span>: {
        <span class="hljs-attr">"editorStickyScroll.background"</span>: <span class="hljs-string">"#5d5252"</span>,
        <span class="hljs-attr">"scrollbar.shadow"</span>: <span class="hljs-string">"#fcfcfc"</span>
    }
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Sprockets 4: `url(relative.css)` issue]]></title><description><![CDATA[Disclaimer: sprockets in general is phased out in the Rails community, still some people need the fix ... I needed a fix today.
Issue: I have an old gem that reference an relative image in the CSS background-image: url("icon.png")) which once compile...]]></description><link>https://blog.brennetot.com/sprockets-4-urlrelativecss-issue</link><guid isPermaLink="true">https://blog.brennetot.com/sprockets-4-urlrelativecss-issue</guid><category><![CDATA[sprockets]]></category><category><![CDATA[Rails]]></category><category><![CDATA[assets]]></category><dc:creator><![CDATA[Thomas Brennetot]]></dc:creator><pubDate>Fri, 02 Feb 2024 10:22:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1709097896135/ab28e3ff-7bd2-4928-99a6-3d43ce108021.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Disclaimer</strong>: sprockets in general is phased out in the Rails community, still some people need the fix ... I needed a fix today.</p>
<p><strong>Issue</strong>: I have an old gem that reference an relative image in the CSS <code>background-image: url("icon.png"))</code> which once compile it become:</p>
<ul>
<li><p>Sprockets 3: <code>background-image: url("icon.png"))</code> (it's a relative URL)</p>
</li>
<li><p>Sprockets 4: <code>background-image: url("/icon.png"))</code> (the <code>/</code> means root URL, eg <code>http://example.org/icon.png</code>)</p>
</li>
<li><p>With the fix below: <code>background-image: url("./icon.png"))</code> (<code>./</code> is also a relative URL)</p>
</li>
</ul>
<p>Notes about relative URL:</p>
<ul>
<li><p>If the CSS file is <code>http://example.com/application.css</code></p>
<ul>
<li>then the <code>icon.png</code> is also at the root: <code>http://example.com/icon.png</code></li>
</ul>
</li>
<li><p>If the CSS file is in a gem (for me it was CKeditor), the CSS file is <code>http://example.com/assets/ckeditor/skins/moono-lisa/editor.css</code></p>
<ul>
<li>then the <code>icon.png</code> is resolved as <code>http://example.com/assets/ckeditor/skins/moono-lisa/icon.png</code></li>
</ul>
</li>
</ul>
<pre><code class="lang-ruby"><span class="hljs-comment"># config/initializers/sprockets.rb</span>

<span class="hljs-comment"># Issue exists: https://github.com/rails/sprockets-rails/issues/507</span>
<span class="hljs-comment"># Fix from PR: https://github.com/rails/sprockets-rails/pull/511</span>
<span class="hljs-comment"># It will not get merge as Sprockets is phased out.</span>
<span class="hljs-class"><span class="hljs-keyword">module</span> <span class="hljs-title">Sprockets</span></span>
  <span class="hljs-class"><span class="hljs-keyword">module</span> <span class="hljs-title">Rails</span></span>
    <span class="hljs-comment"># Resolve assets referenced in CSS `url()` calls and replace them with the digested paths</span>
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AssetUrlProcessor</span></span>
      REGEX = <span class="hljs-regexp">/url\(\s*["']?(?!(?:\#|data|http))(?&lt;relativeToCurrentDir&gt;\.\/)?(?&lt;path&gt;[^"'\s)]+)\s*["']?\)/</span>
      <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">self</span>.<span class="hljs-title">call</span><span class="hljs-params">(input)</span></span>
        context = input[<span class="hljs-symbol">:environment</span>].context_class.new(input)
        data    = input[<span class="hljs-symbol">:data</span>].gsub(REGEX) <span class="hljs-keyword">do</span> <span class="hljs-params">|_match|</span>
          path = Regexp.last_match[<span class="hljs-symbol">:path</span>]
          <span class="hljs-comment"># Prevent non-digest relative path from being converted to root absolute path</span>
          orig_path = path
          path = context.asset_path(path)
          path = (path == <span class="hljs-string">"/<span class="hljs-subst">#{orig_path}</span>"</span>) ? <span class="hljs-string">".<span class="hljs-subst">#{path}</span>"</span> : path
          <span class="hljs-string">"url(<span class="hljs-subst">#{path}</span>)"</span>

        <span class="hljs-keyword">end</span>

        context.metadata.merge(<span class="hljs-symbol">data:</span> data)
      <span class="hljs-keyword">end</span>
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p><strong>Caveat:</strong> the original file did not change therefore the digest did not either, until the browser invalid the the cache and download the new CSS, users will have the old CSS cached by the browser</p>
<p>Please share and comment on how I can write it better.</p>
]]></content:encoded></item><item><title><![CDATA[[Quicky] Github Action: cache Ruby's gems]]></title><description><![CDATA[You just need bundler-cache: true
# .github/workflows/my_very_special_job.yml
jobs:
  my_very_special_job:
    steps:
      - name: Setup Ruby
        uses: ruby/setup-ruby@v1
        with:
          bundler-cache: true    ###### That's the line]]></description><link>https://blog.brennetot.com/quicky-github-action-cache-ruby-gems</link><guid isPermaLink="true">https://blog.brennetot.com/quicky-github-action-cache-ruby-gems</guid><category><![CDATA[Ruby]]></category><category><![CDATA[gem]]></category><category><![CDATA[github-actions]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[Gemfile]]></category><dc:creator><![CDATA[Thomas Brennetot]]></dc:creator><pubDate>Wed, 24 Jan 2024 03:55:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1706068331029/ba17c768-ab31-483b-8b3e-dcd5ad229327.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You just need <code>bundler-cache: true</code></p>
<pre><code class="lang-yaml"><span class="hljs-comment"># .github/workflows/my_very_special_job.yml</span>
<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">my_very_special_job:</span>
    <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Setup</span> <span class="hljs-string">Ruby</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">ruby/setup-ruby@v1</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">bundler-cache:</span> <span class="hljs-literal">true</span>    <span class="hljs-comment">###### That's the line</span>
</code></pre>
]]></content:encoded></item></channel></rss>