<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Michael Monerau</title>
    <description>The latest articles on DEV Community by Michael Monerau (@qortex).</description>
    <link>https://dev.to/qortex</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F169290%2F9d963a11-5532-4508-adfa-018c7c1ec02f.png</url>
      <title>DEV Community: Michael Monerau</title>
      <link>https://dev.to/qortex</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/qortex"/>
    <language>en</language>
    <item>
      <title>Ruby - suppress those warnings you can't do anything about</title>
      <dc:creator>Michael Monerau</dc:creator>
      <pubDate>Wed, 29 Apr 2020 08:59:14 +0000</pubDate>
      <link>https://dev.to/qortex/ruby-suppress-those-warnings-you-can-t-do-anything-about-6ie</link>
      <guid>https://dev.to/qortex/ruby-suppress-those-warnings-you-can-t-do-anything-about-6ie</guid>
      <description>&lt;p&gt;Ever encountered a situation where you get warnings from code in gems you are requiring?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
/home/qortex/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/amazing_print-1.0.0/lib/amazing_print/formatter.rb:29: warning: mismatched indentations at 'end' with 'else' at 27
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It doesn't feel good, right? Depending on your toolchain and CI/CD pipelines, it can lead to annoying noise.&lt;/p&gt;

&lt;p&gt;I started encountering some of those warnings when running RSpec with the &lt;code&gt;warnings&lt;/code&gt; flag on (which is useful because it helps catching some smells in code).&lt;/p&gt;

&lt;h1&gt;
  
  
  Fix them?
&lt;/h1&gt;

&lt;p&gt;In those cases, you do not own the codebase the warnings originate from. So you are out of luck because you &lt;em&gt;can't&lt;/em&gt; fix them by yourself. You have to submit a PR, and/or wait for the maintainers to release a fix - if they ever do. It can take time.&lt;/p&gt;

&lt;p&gt;Sometimes, the warnings are &lt;a href="https://github.com/jeremyevans/sequel/issues/1686"&gt;just expected&lt;/a&gt; and should be silenced.&lt;/p&gt;

&lt;h1&gt;
  
  
  Suppress them!
&lt;/h1&gt;

&lt;p&gt;So now you think the warnings can be safely ignored, and you would like to suppress them.&lt;/p&gt;

&lt;p&gt;A gem does exactly that, it's called &lt;a href="https://github.com/jeremyevans/ruby-warning"&gt;warnings&lt;/a&gt; and has been made by the well-known and amazing rubyist &lt;a href="http://code.jeremyevans.net/"&gt;Jeremy Evans&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Just put &lt;code&gt;gem 'warning'&lt;/code&gt; in your Gemfile, and silence warnings from all your required gems with a simple snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'warning'&lt;/span&gt;
&lt;span class="no"&gt;Gem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="no"&gt;Warning&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ignore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;//&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In a RSpec context, you typically put that at the top of your &lt;code&gt;spec_helper.rb&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;In any other context, just put that before requiring the gems that output warnings.&lt;/p&gt;

&lt;p&gt;You can also be more precise in the warnings you'd like to ignore, by targeting them specifically. For example, to silence the exact warning shown above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# first param is a regexp matching the message&lt;/span&gt;
&lt;span class="c1"&gt;# second param is a regexp matching the file path&lt;/span&gt;
&lt;span class="no"&gt;Warning&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ignore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/.*mismatched indentations.*/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;/.*amazing_print.*/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



</description>
      <category>ruby</category>
      <category>inthirtyseconds</category>
      <category>testing</category>
    </item>
    <item>
      <title>Compute MD5 checksum hash for a File in Typescript</title>
      <dc:creator>Michael Monerau</dc:creator>
      <pubDate>Sat, 18 Jan 2020 09:56:22 +0000</pubDate>
      <link>https://dev.to/qortex/compute-md5-checksum-for-a-file-in-typescript-59a4</link>
      <guid>https://dev.to/qortex/compute-md5-checksum-for-a-file-in-typescript-59a4</guid>
      <description>&lt;p&gt;When implementing a file uploader component in your webapp, you may need to compute the MD5 checksum of a file.&lt;/p&gt;

&lt;p&gt;It is typically useful when your frontend uploads a file to some cloud storage and needs to make your backend aware of the file that was just uploaded. Armed with the MD5 hash of the file, the backend can then validate the integrity of the file when accessing it later on.&lt;/p&gt;

&lt;p&gt;At least, that's the way it works in Ruby on Rails &amp;amp; &lt;a href="https://edgeguides.rubyonrails.org/active_storage_overview.html"&gt;Active Storage&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Quite surprisingly though, there is no easy straightforward way to get the MD5 checksum for a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/File"&gt;File&lt;/a&gt; object in Typescript / Javascript.&lt;/p&gt;

&lt;p&gt;Building on this &lt;a href="https://stackoverflow.com/questions/768268/how-to-calculate-md5-hash-of-a-file-using-javascript?noredirect=1&amp;amp;lq=1"&gt;SO post&lt;/a&gt;, the great &lt;a href="https://github.com/satazor/js-spark-md5"&gt;Spark-MD5 library&lt;/a&gt; and its test examples, here is a simple solution.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/satazor/js-spark-md5"&gt;spark-md5&lt;/a&gt; package needs to be installed in your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add spark-md5
&lt;span class="c"&gt;# or npm install --save spark-md5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then the following function does the computation itself, returning a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise"&gt;Promise&lt;/a&gt; of the MD5 hash as a base64 encoded string. It reads the file in chunks to avoid loading the whole file into memory at once, which could be a performance disaster.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;SparkMD5&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;spark-md5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="nx"&gt;computeChecksumMd5&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;File&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chunkSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2097152&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Read in chunks of 2MB&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;spark&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;SparkMD5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;ArrayBuffer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileReader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;FileReader&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;cursor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// current cursor in file&lt;/span&gt;

    &lt;span class="nx"&gt;fileReader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onerror&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MD5 computation failed - error reading the file&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c1"&gt;// read chunk starting at `cursor` into memory&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;processChunk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;chunk_start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chunk_end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;chunk_start&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;chunkSize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;fileReader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readAsArrayBuffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk_start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;chunk_end&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// when it's available in memory, process it&lt;/span&gt;
    &lt;span class="c1"&gt;// If using TS &amp;gt;= 3.6, you can use `FileReaderProgressEvent` type instead &lt;/span&gt;
    &lt;span class="c1"&gt;// of `any` for `e` variable, otherwise stick with `any`&lt;/span&gt;
    &lt;span class="c1"&gt;// See https://github.com/Microsoft/TypeScript/issues/25510&lt;/span&gt;
    &lt;span class="nx"&gt;fileReader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;spark&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Accumulate chunk to md5 computation&lt;/span&gt;
      &lt;span class="nx"&gt;cursor&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;chunkSize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Move past this chunk&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cursor&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Enqueue next chunk to be accumulated&lt;/span&gt;
        &lt;span class="nx"&gt;processChunk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Computation ended, last chunk has been processed. Return as Promise value.&lt;/span&gt;
        &lt;span class="c1"&gt;// This returns the base64 encoded md5 hash, which is what&lt;/span&gt;
        &lt;span class="c1"&gt;// Rails ActiveStorage or cloud services expect&lt;/span&gt;
        &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;btoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spark&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;

        &lt;span class="c1"&gt;// If you prefer the hexdigest form (looking like&lt;/span&gt;
        &lt;span class="c1"&gt;// '7cf530335b8547945f1a48880bc421b2'), replace the above line with:&lt;/span&gt;
        &lt;span class="c1"&gt;// resolve(spark.end());&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nx"&gt;processChunk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, profit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// your_file_object: File&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="nx"&gt;computeChecksumMd5Hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;your_file_object&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;md5&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`The MD5 hash is: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;md5&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Output: The MD5 hash is: fPUwM1uFR5RfGkiIC8Qhsg==&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
