<?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>Forem: Aurelie Verrot</title>
    <description>The latest articles on Forem by Aurelie Verrot (@aurelieverrot).</description>
    <link>https://forem.com/aurelieverrot</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%2F328873%2F4989d459-f96f-4b64-af25-4bd3716b6e8b.jpg</url>
      <title>Forem: Aurelie Verrot</title>
      <link>https://forem.com/aurelieverrot</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/aurelieverrot"/>
    <language>en</language>
    <item>
      <title>Let's Talk About Globalization</title>
      <dc:creator>Aurelie Verrot</dc:creator>
      <pubDate>Thu, 15 Dec 2022 06:49:53 +0000</pubDate>
      <link>https://forem.com/aurelieverrot/lets-talk-about-globalization-5c9k</link>
      <guid>https://forem.com/aurelieverrot/lets-talk-about-globalization-5c9k</guid>
      <description>&lt;p&gt;Your product works well in the country where you created it? Congratulations! You might think that you just need to translate it to expand your business internationally... unfortunately, it is not that simple.&lt;/p&gt;

&lt;p&gt;You probably noticed how weird translated content is when you use Google Translate. A lot of progress has been made these past years (I invite you to discover &lt;a href="https://ai.googleblog.com/2020/06/recent-advances-in-google-translate.html" rel="noopener noreferrer"&gt;how it works&lt;/a&gt;), but it is still not perfect. The main reason for this is the lack of context, lack of knowledge of culture and habits, lack of nuance, and other details about how languages are built.&lt;/p&gt;

&lt;p&gt;So, no, translating your app alone is not enough. There are many other things to consider when you want to go global.&lt;/p&gt;

&lt;p&gt;I am French, I live in the US, I am learning Spanish, and I see many things that are different in these languages. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For example:&lt;br&gt;
1,000.00 in the US and 1.000,00 in France are the same number, but decimals and separators for big numbers are not the same.&lt;br&gt;
03/04/2021 is March 4th in the US, and April 3rd in France.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you live in an occidental country, you probably design your app with content written from left to right. But in countries using the Arab language, the text is written from right to left. Will your design still be great when the content is written the other way?&lt;br&gt;
We can also talk about character encoding. Consider a text field in your frontend that accepts 256 characters. That seems enough... at least when you use most of the occidental alphabets. The English alphabet for example is a "single-byte language", meaning you can fit 256 characters in that field. Korean is a "double-byte language", so you will be able fit half as many characters. Think also about where you will store your translations: if you want to store them in a database, you’ll have to make sure you can store the strings for all the languages you target, whether their size once translated.&lt;/p&gt;

&lt;p&gt;I won't go too deep into technical details in this article, but I will explain the basic concepts that need to be known to turn your app into a worldwide product.&lt;br&gt;
So let's talk about Globalization.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flsteikstaxe9ti1x0ct6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flsteikstaxe9ti1x0ct6.jpg" title="the Earth from space" alt="The Earth"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Globalization (G11n)?
&lt;/h2&gt;

&lt;p&gt;G11n is the process of scaling a business, app, or software to meet international requirements and adapting your product to the country and/or language where it is used, and/or by whom it is used.&lt;br&gt;
Globalization is the common goal of Localization and Internationalization. These two concepts are often used interchangeably, but they are really two different components of the globalization process.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Localization (L10n)?
&lt;/h2&gt;

&lt;p&gt;Think about L10n as project management. It is at the crossroads of Design, Engineering, and Product. &lt;br&gt;
If your designers are deciding what traffic colors to use, L10n is the guardian who will know that colors that work in the US won’t work the same for Japanese customers (the US use green, yellow, red, while Japan has blue, yellow, and red traffic lights). They will know that the layout of the page might need to change as well (users from Japan tend to prefer longer pages). Additionally, L10n catches that a "submit" button will become too tiny once written in Japanese.&lt;br&gt;
L10n should be involved at the early stage of projects; they give guidelines to designers, support the project strategy with product managers, and do the QA with Engineering. &lt;br&gt;
They also manage translations - they know all the products, can provide useful usage context to give to the translators, and organize the process of translation (send content to vendors, follow-up, budget, etc...)&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Internationalization (I18n)?
&lt;/h2&gt;

&lt;p&gt;I18n enables L10n. It is what makes your application responsive to the long list of L10n requirements. It will manipulate the way the data is delivered, it will change the design in case of an RTL (Right-to-Left) language, will pluralize words, manage time zones, etc… &lt;br&gt;
You might know that there are libraries that can help with that, but are you sure it is 1/ well maintained, 2/ following the standards? &lt;br&gt;
Wait, what standards? Ha! Glad you asked! &lt;br&gt;
Have you heard about Unicode? I won’t explain everything Unicode manages, but let's say simply that it is a Worldwide organization that defines the standards for character encoding and localization data for the industry (standards like ICU and CLDR, which probably deserve a separate article). The main libraries for internationalization use these standards. For example, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl" rel="noopener noreferrer"&gt;Intl&lt;/a&gt; for front-end JS which is shipped with Node.JS, or &lt;a href="https://github.com/ruby-i18n/i18n" rel="noopener noreferrer"&gt;ruby-i18n&lt;/a&gt; which is shipped with Rails.&lt;br&gt;
And let's not forget about mobile development: Android (using Java) and iOS (using Swift) are also using these standards behind the scene.&lt;br&gt;
Though while it's a good thing that these libraries cover the essentials, you also sometimes need to add some logic specific to your business, product, and users.&lt;/p&gt;

&lt;p&gt;Let’s look at language fallback for example: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Your user is French and uses the locale &lt;code&gt;fr&lt;/code&gt;. Today for some reason your app can’t deliver French, so ideally it falls back to another one. What would be a good fallback language for you? Probably using the default &lt;code&gt;en-US&lt;/code&gt; (English - United States). &lt;br&gt;
But this user lives in &lt;a href="https://www.google.com/maps/place/66700+Argel%C3%A8s-sur-Mer,+France/@42.6597038,2.5213656,9z/data=!4m13!1m7!3m6!1s0xd54a02933785731:0x6bfd3f96c747d9f7!2sFrance!3b1!8m2!3d46.227638!4d2.213749!3m4!1s0x12b07ed5678ac6ed:0xbb4c16ee0221830!8m2!3d42.5462514!4d3.0229568" rel="noopener noreferrer"&gt;Argelès-sur-mer&lt;/a&gt;, near the border with Spain, and most importantly near &lt;a href="https://www.google.com/maps/place/Catalonia,+Spain/@41.688839,0.6247189,8z/data=!3m1!4b1!4m5!3m4!1s0x12a45bdc8530f5f3:0x100fae021a3c850!8m2!3d41.5911589!4d1.5208624" rel="noopener noreferrer"&gt;Catalonia&lt;/a&gt;. This user speaks fluently Catalan and not a single word of English. If they see the app suddenly written in English, they can’t use it anymore (and they might be super frustrated). &lt;br&gt;
This user is the only Catalan speaker you have in your user base though, so you decided to not provide translations in Catalan as it would be too expensive to maintain, but maybe Spanish would work, and yes, it’s close enough to Catalan for your user to continue to use the app until French comes back. Though for that you will need to enable the possibility of this specific type of fallback from &lt;code&gt;fr&lt;/code&gt; to &lt;code&gt;es&lt;/code&gt;.&lt;br&gt;
With the right language used, your user will finally be able to make their money transfers from Yen to US Dollar… but wait, how will currencies be displayed then?...&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;All this logic is made by i18n.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about Translation (T9n)?
&lt;/h2&gt;

&lt;p&gt;As mentioned above in the Localization paragraph, Translation is yet another part of Globalization that is often done by a third-party; professional translators usually translate the content of an app into their native language.&lt;br&gt;
Most of the time their work is managed by people taking care of the L10n part, they need not only the text to be translated but also the context in which the content is used.&lt;/p&gt;

&lt;p&gt;Here is one small example of why it is important to leave this part to professional translator, or native speakers:&lt;br&gt;
"Sign In" could be translated "Signez dans" in French if it was translated word by word, and if we didn't know that it was the content used to sign into an account in an app. In good "app-friendly" French, we preferably say "Se connecter" which would be translated word by word into "To connect" in English... &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo5q3g8w4ftj6itbqsknr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo5q3g8w4ftj6itbqsknr.png" title="screenshot of Sign In page in English from Google" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz39tqy5jp7r056lepmyr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz39tqy5jp7r056lepmyr.png" title="screenshot of Sign In page in French from Google" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Another example would be languages using gendered words. Latin languages use them a lot, French is no exception. &lt;code&gt;Developers&lt;/code&gt; in English includes all developers, no matter non-binary, female, or male. In French, the word is gendered (male and female), and by default, we say &lt;code&gt;un développeur&lt;/code&gt;, which is a male version of the word. The female version would be &lt;code&gt;une développeuse&lt;/code&gt;. And it's important to know that because it has consequences for how the strings will be translated. Verbs won't have the same endings, strings will be longer, etc... A translator can provide alternatives for non-gendered words, or give information to people in Localization that they might need to set up a specific mechanism in the app to manage this specificity. Or even apply an inclusive way of rendering the word, like &lt;code&gt;développeur·euse&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Languages are hard. So let professionals manage that part.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Notes
&lt;/h2&gt;

&lt;p&gt;I hope you now see the distinction between all the actors of Globalization with the little examples I gave you.&lt;br&gt;
The main concepts to remember are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We globalize a product to ensure our users have the same user experience no matter where they are in the world, though that doesn't mean they have to see the same thing.&lt;/li&gt;
&lt;li&gt;Globalization is the sum of Internationalization, Localization, and Translation.&lt;/li&gt;
&lt;li&gt;Think of Globalization the same way you think of Accessibility. You might need to enable features to ensure good navigation for some users.&lt;/li&gt;
&lt;li&gt;Libraries are your friends, but make sure they are well maintained and follow the Unicode standards.&lt;/li&gt;
&lt;li&gt;Translations should be made at the very least by native speakers and always with the context in mind. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;A special thank you to Danielle Thompson, Joshua Ocrah, and Lucas Welti for their feedback on this article.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>i18n</category>
      <category>globalization</category>
      <category>internationalization</category>
      <category>localization</category>
    </item>
    <item>
      <title>Be a Happy Coder</title>
      <dc:creator>Aurelie Verrot</dc:creator>
      <pubDate>Fri, 05 Nov 2021 23:23:34 +0000</pubDate>
      <link>https://forem.com/aurelieverrot/be-a-happy-coder-jjf</link>
      <guid>https://forem.com/aurelieverrot/be-a-happy-coder-jjf</guid>
      <description>&lt;p&gt;When starting my new coding journey I was hopeful, I remember telling myself that I would rock my bootcamp, that I would make this and that project, probably have a side project to have a side income, that I would go to many conferences, etc... etc...&lt;/p&gt;

&lt;p&gt;Truth is, frustration and deception arrived very quickly. I didn't rock my bootcamp, I finished it having learned many things for sure, I had miles and miles of opened tabs to tools, tutorials, discussions... everything to help me find answers to my questions. But I didn't reach the point where I could help someone or explain something because I wasn’t understanding anything well enough.&lt;/p&gt;

&lt;p&gt;For many months I was just telling myself that one of the reasons developers are well paid is that companies need to keep them on the job while unhappy because coding is just about negative feelings.&lt;br&gt;
These "HAAA" moments are not happening often enough to satisfy anybody, so yes of course companies need them to be well paid so they keep doing it.&lt;br&gt;
And I had proof to validate that theory: have you been on tech Twitter? Everybody is depressed, burned out, frustrated...&lt;/p&gt;

&lt;p&gt;I searched for a community of devs where I could find support not only on technical subjects but in general. We are not just devs, we are people with feelings, with stories. In the community I have found we are all different but we are searching for the same things: being happy with what we do, receiving support as much as providing it, promoting people, and having fun.&lt;br&gt;
Turns out our group is a magnet for very cool people. We are very lucky.&lt;/p&gt;

&lt;p&gt;I joined the community while I was in an internship, about to start my job search. I was miserable, I receive a lot of help, I got results, it made me more confident.&lt;br&gt;
And what helped a ton as well was to be in contact with people who were happy with their work, with their projects, who found that coding was something fun and was very motivated to share about it.&lt;/p&gt;

&lt;p&gt;There was one person in particular who was the happiest coder of all time. The kind of person who always shares the good stuff they find, always smiling, they know the cool tricks, and all of that is positively contagious!&lt;br&gt;
This person helped me and many others with coding challenges, learning, debugging, interview prep..., and was also a gaming buddy because remember: we are not just coders!&lt;/p&gt;

&lt;p&gt;This person left us today and will leave an empty hole behind them. It is a horrible and sad day for our community, and it will affect many many more when the news will spread.&lt;/p&gt;

&lt;p&gt;I guess my intention with this article was to give an homage to this happy person, I hope they knew the impact they had on so many people. I wish the tech community has more people like them.&lt;/p&gt;

&lt;p&gt;If you think you are a happy one too, remember that you can probably change someone's day by sharing a little bit of your shine.&lt;br&gt;
If you are not, find your happy coders and I hope they will help you go through your coding journey, and find some fun in your work.&lt;/p&gt;

&lt;p&gt;Goodbye friend, Docker doesn’t make me happy yet, but I am happy to have known you :)&lt;/p&gt;

</description>
    </item>
    <item>
      <title>The tale of the K combinator and the alias method</title>
      <dc:creator>Aurelie Verrot</dc:creator>
      <pubDate>Wed, 31 Mar 2021 03:05:34 +0000</pubDate>
      <link>https://forem.com/aurelieverrot/the-tale-of-the-k-combinator-and-the-alias-method-34nl</link>
      <guid>https://forem.com/aurelieverrot/the-tale-of-the-k-combinator-and-the-alias-method-34nl</guid>
      <description>&lt;p&gt;The other day after a good ol' code cleaning, the file I was working on seemed too long and repetitive. The reason to that was because of a set of four &lt;em&gt;different&lt;/em&gt; methods doing the exact same thing: returning an argument.&lt;/p&gt;

&lt;p&gt;More context:&lt;/p&gt;

&lt;p&gt;The goal was to create an export of a collection.&lt;br&gt;
For this I had two type of files:&lt;/p&gt;
&lt;h3&gt;
  
  
  application_exporter.rb
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;class ApplicationExporter&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It has all the necessary methods to create a .xlsx file. It's also in charge of grabbing all the records for a given Model and apply to it a method to prepare these records (check the policy, apply filters, ...).&lt;br&gt;
It looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;prepare_exported_data&lt;/span&gt;
  &lt;span class="vi"&gt;@data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model_name&lt;/span&gt;
  &lt;span class="vi"&gt;@data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;apply_policy_to_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;export_creator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="vi"&gt;@data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;apply_filters_to_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;export&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="vi"&gt;@data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;apply_scope_to_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;export&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;model_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;# takes the model name and returns Model.all in an array&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;apply_policy_to_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;# apply the policy to the data to make sure the user won't&lt;/span&gt;
  &lt;span class="c1"&gt;# export data they shouldn't have access to&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;apply_filters_to_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;export&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;# if the user asked to see only a certain type of data, &lt;/span&gt;
  &lt;span class="c1"&gt;# give them only what they asked&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;apply_scope_to_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;export&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;# in case there is a scope applied, let's apply it to the &lt;/span&gt;
  &lt;span class="c1"&gt;# collection&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  model_exporter.rb
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;class ModelExporter &amp;lt; ApplicationExporter&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is the file for the Model records (it can be User, Posts,...). As the dependent of ApplicationExporter, it inherits from it all its methods.&lt;br&gt;
This class will have all the necessary methods to fill the export, with the necessary attributes, and will define the columns, the headers, etc...&lt;/p&gt;

&lt;p&gt;If I want something basic like exporting all the records of a given model, the only method it needs is the one defining the columns of the spreadsheet.&lt;/p&gt;
&lt;h3&gt;
  
  
  So what's the problem here?
&lt;/h3&gt;

&lt;p&gt;My problem was that ApplicationExporter builds the export with a collection of records from the database by using the &lt;code&gt;model_name&lt;/code&gt; given to it when the process is fired. But this time the data came from a hash in the code base and only one attribute had to be fetched from the database.&lt;br&gt;
That means many methods from ApplicationExporter were useless and I had to override them in the class ModelExporter.&lt;/p&gt;

&lt;p&gt;First I had to create the collection of data I needed. For that I overrode the #model_name method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;model_name&lt;/span&gt;
  &lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;VERY_IMPORTANT_HASH&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&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;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;value: &lt;/span&gt;&lt;span class="n"&gt;whatever_info_in_the_hash_for_this&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="ss"&gt;default_value: &lt;/span&gt;&lt;span class="no"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;default_value&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, name and value are taken from the hash, but the default_value comes from the database. It returns an array (thanks to #map) which is great because this is the data type I need for the exporter process to work.&lt;/p&gt;

&lt;p&gt;Now comes the moment when the method &lt;code&gt;#prepare_exported_data&lt;/code&gt; that I have shown above is fired, &lt;em&gt;and also when the title of this post will finally make sense...&lt;/em&gt; (bear with me :) ) &lt;/p&gt;

&lt;p&gt;For this specific export I don't need any policies or filters applied, even if they exist. That means that every single method fired by &lt;code&gt;#prepare_exported_data&lt;/code&gt; has to return the collection without modifying it.&lt;/p&gt;

&lt;p&gt;I ended up having to override all the methods this way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;apply_policy_to_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;data&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;apply_filters_to_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_export&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;data&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;apply_scope_to_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_export&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;data&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can notice the underscores on all the arguments that doesn't concern the data. That means: "I know I am supposed to take 2 arguments, but I won't care about the second one &amp;lt;3".&lt;br&gt;
Then, the only thing all the methods do is to return the &lt;code&gt;data&lt;/code&gt; passed as argument.&lt;/p&gt;

&lt;p&gt;So how to avoid this 'repeat' mode? For that I used a concept from Calculus: Kestrel Combinator, also called K Combinator.&lt;br&gt;
It is a function taking two arguments and returning only the first one, considered as a constant.&lt;br&gt;
It is as simple as that!&lt;/p&gt;

&lt;p&gt;Let's take a look at how to use it in my case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;const&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;collection&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="kp"&gt;alias_method&lt;/span&gt; &lt;span class="ss"&gt;:apply_policy_to_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="ss"&gt;:const&lt;/span&gt;
&lt;span class="kp"&gt;alias_method&lt;/span&gt; &lt;span class="ss"&gt;:apply_filters_to_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:const&lt;/span&gt;
&lt;span class="kp"&gt;alias_method&lt;/span&gt; &lt;span class="ss"&gt;:apply_scope_to_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="ss"&gt;:const&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is nothing spectacular here: I achieved to have a cleaner and lighter code by using a little trick. &lt;br&gt;
It is just one example about how to use a mathematic concept in code.&lt;/p&gt;

&lt;p&gt;There are other kind of combinators, you can learn about them by taking a Calculus class... or reading &lt;a href="https://www.willtaylor.blog/combinators-and-church-encoding-in-javscript/"&gt;this great article with Javascript examples&lt;/a&gt;. And if you had to use one of them, please share!&lt;/p&gt;

</description>
      <category>ruby</category>
    </item>
    <item>
      <title>Create a chat in the command line with Ruby</title>
      <dc:creator>Aurelie Verrot</dc:creator>
      <pubDate>Tue, 12 Jan 2021 17:08:47 +0000</pubDate>
      <link>https://forem.com/aurelieverrot/create-a-chat-in-the-command-line-with-ruby-2po9</link>
      <guid>https://forem.com/aurelieverrot/create-a-chat-in-the-command-line-with-ruby-2po9</guid>
      <description>&lt;p&gt;Last weekend I learned how to create a chat application in the command line. The idea was to open at least 3 tabs in the terminal: one for the server that will handle the connexion between the users, and X number of tabs for the users to communicate, at least 2.&lt;/p&gt;

&lt;p&gt;This project made me discover two built-in classes in Ruby that we don't really use when we do a full stack application with Rails:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Socket&lt;/li&gt;
&lt;li&gt;Thread&lt;/li&gt;
&lt;li&gt;ARGV&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I will talk about them later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's talk about the server
&lt;/h2&gt;

&lt;p&gt;So what do we need exactly to create this chat? We talked about a server, so we will need a file for this that will be called server.rb&lt;br&gt;
What do we need to do here? We need to establish the connexion through the port of our choice. For this we will need the class Socket, and we have to require it at the beginning of the file.&lt;br&gt;
To understand what this method offers, make sure to understand what a socket is. Here is a definition provided by Oracle docs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"A socket is one endpoint of a two-way communication link between two programs running on the network. A socket is bound to a port number so that the TCP layer can identify the application that data is destined to be sent to."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Requiring Socket will give us access to other classes and methods to create our server (&lt;a href="https://ruby-doc.org/stdlib-2.7.0/libdoc/socket/rdoc/Socket.html" rel="noopener noreferrer"&gt;see the Ruby documentation for Socket&lt;/a&gt;).&lt;br&gt;
Our first line of command will be to create a TCP server on the port we want, and to make sure it's launched I will print a confirmation text:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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;'socket'&lt;/span&gt;

&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;TCPServer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt; &lt;span class="c1"&gt;# Server bound to port 2000&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"I'm ready to accept new clients on port 2000"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our server is working, now we need it to listen to whatever connexion is coming up from a client, and we need to do it constantly. So we need to create a loop. We also want the server to handle multiple clients, and give information to users. So we will create an array to store them, and append every new client to the array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;clients&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;span class="kp"&gt;loop&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# we wait for a client to connect, and assign it to client&lt;/span&gt;
  &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;accept&lt;/span&gt;
  &lt;span class="n"&gt;clients&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is now time to introduce Thread. We use a thread to split a program and have a tasks that will run simultaneously (or pseudo-simultaneously). Creating a thread will allow our program to run two processes in the same time (&lt;a href="https://ruby-doc.org/core-2.7.0/Thread.html" rel="noopener noreferrer"&gt;see documentation for Thread&lt;/a&gt;)&lt;br&gt;
We need it because while the server is waiting for a client to connect in the loop, we also need to constantly handle the messaging between the clients already connected. &lt;br&gt;
We do that by writing &lt;code&gt;Thread.new {}&lt;/code&gt;. The block will be used to tell the program what to do with this thread. &lt;br&gt;
So what do we need from it? We need to know who connects to it, to receive and display text to others. We also need to detect when a client disconnect and remove it from the &lt;code&gt;clients&lt;/code&gt; array.&lt;/p&gt;

&lt;p&gt;It's a lot, so let's create a method for this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clients&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# for this method I need the new client, and the list of existing clients.&lt;/span&gt;

  &lt;span class="c1"&gt;# client_name will take whatever name the client put when it will connect to the server. We will see later how it's sent from the client perspective.&lt;/span&gt;
  &lt;span class="n"&gt;client_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chomp&lt;/span&gt;

  &lt;span class="c1"&gt;# here we will display a welcome message and show how many clients are already connected&lt;/span&gt;
  &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Hello &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;client_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;! Clients connected: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;clients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

  &lt;span class="c1"&gt;# this method is described below. It announces to all clients who is the new client.&lt;/span&gt;
  &lt;span class="n"&gt;announce_to_everyone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clients&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;client_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; joined!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# this is another loop. gets will take any text coming from the client...&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gets&lt;/span&gt;
    &lt;span class="n"&gt;incoming_data_from_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chomp&lt;/span&gt;
    &lt;span class="c1"&gt;#... and this text will be shared to all the clients. A little bit of formatting to indicate who said what.&lt;/span&gt;
    &lt;span class="n"&gt;announce_to_everyone&lt;/span&gt; &lt;span class="n"&gt;clients&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;client_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;incoming_data_from_client&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# it will close the client connexion and remove it from the clients array. And other clients will receive a notification.&lt;/span&gt;
  &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;
  &lt;span class="n"&gt;clients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;announce_to_everyone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clients&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;client_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; left!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# this method takes the text sent by a client, and the clients connected. For each client from clients, the text will be displayed&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;announce_to_everyone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clients&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;clients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;text&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;We are done with &lt;code&gt;server.rb&lt;/code&gt;. The server is running, and waiting to get clients connexions. It will receive messages and display them to all connected clients, and give them cool info for a better user experience (well, from the terminal... for what it's worth).&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's talk about the client
&lt;/h2&gt;

&lt;p&gt;The idea here is to open let say 3 terminal tabs to simulate 3 clients / users, we will launch the client's program from each tab.&lt;br&gt;
For that we need to create a file that we will call &lt;code&gt;client.rb&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;First we need to make sure our client will create a connexion on the server. Previously, on server side, we used &lt;code&gt;TCPServer.new&lt;/code&gt;. This time, we will create an instance of &lt;code&gt;TCPSocket&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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;'socket'&lt;/span&gt;
&lt;span class="n"&gt;socket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;TCPSocket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;  
&lt;span class="c1"&gt;# bound to port 2000, like the server&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we connect to the chat, we want a way to enter the user name. There is a simple way to do that. &lt;br&gt;
From the terminal, we can write &lt;code&gt;$ruby client.rb Aurelie&lt;/code&gt;, where &lt;code&gt;Aurelie&lt;/code&gt; is an argument passed to the script.&lt;br&gt;
In our file, first thing to do is to grab this argument and assign it to a variable. For that we need to use the ARGV built-in class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ARGV&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shift&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ARGV takes all the arguments you pass to a script, and put them into an array in order of apparition. And #shift will use the first one of the array.&lt;/p&gt;

&lt;p&gt;Do you remember how we assigned the client's name in &lt;code&gt;server.rb&lt;/code&gt; above? &lt;br&gt;
Here we will use &lt;code&gt;name&lt;/code&gt;, and do a &lt;code&gt;puts&lt;/code&gt; applied to the socket. The first connexion to the server through the socket will be to send the name to the server, and that's how the server will pick-up &lt;code&gt;name&lt;/code&gt; with its &lt;code&gt;gets&lt;/code&gt; and assign it to &lt;code&gt;client_name&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we need a way to take what the user types in the client and send it to the server, but we also need to keep receiving whatever messages other clients send to us. Two processes at a time, it's time to use Thread again!&lt;/p&gt;

&lt;p&gt;We will create one thread for the local typing, and one for what the client receives from the server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;local_typing_thread&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;local_typing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;receive_from_server_thread&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;receive_from_server&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&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;Two things here, we assign each thread to a variable for a later use, and we pass in each thread a method to handle our processes.&lt;/p&gt;

&lt;p&gt;Let's talk about the &lt;code&gt;local_typing&lt;/code&gt; method.&lt;br&gt;
This method needs to know which socket to use to give information to the server. It also needs to constantly check for what to send, so we need a loop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;local_typing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kp"&gt;loop&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# when a user sends a message, this message will appear in the user client preceded by a little string that shows it's the user's message. For example: (me)&amp;gt; Hey it's me!&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"(me)&amp;gt; "&lt;/span&gt;
    &lt;span class="n"&gt;text_to_send&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;gets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chomp&lt;/span&gt;
    &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;text_to_send&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we need to tackle the &lt;code&gt;receive_from_server&lt;/code&gt; method.&lt;br&gt;
Again, it needs to know about the socket. And again, we want it to constantly capture all the messages sent to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;receive_from_server&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;# read the lines coming from the socket, and write them in the terminal&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gets&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, since we created two separate threads, we need to make them join, and we need to close the socket when we are done&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;local_typing_thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;
&lt;span class="n"&gt;receive_from_server_thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;

&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tadaa! We created a little chat in the terminal, on localhost.&lt;br&gt;
See what it looks like:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjjhm48b7otnpdbdx77zu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjjhm48b7otnpdbdx77zu.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find the files in my repo &lt;a href="https://github.com/aurelieverrot/ruby-chat" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>beginners</category>
    </item>
    <item>
      <title>My Bootcamp Journey As A Mom During the Pandemic</title>
      <dc:creator>Aurelie Verrot</dc:creator>
      <pubDate>Tue, 12 May 2020 00:03:40 +0000</pubDate>
      <link>https://forem.com/aurelieverrot/my-bootcamp-journey-as-a-mom-during-the-pandemic-ln2</link>
      <guid>https://forem.com/aurelieverrot/my-bootcamp-journey-as-a-mom-during-the-pandemic-ln2</guid>
      <description>&lt;p&gt;My coding journey started in May 2019. I was a total newbie, I tried to learn by myself at home, but I quickly discovered some challenges.&lt;/p&gt;

&lt;p&gt;First I didn't like the loneliness. Even if I like sometimes being isolated to focus on something tricky, or just because I need silence, I really enjoy having people around me, and the idea of team work. I like being able to share a purpose, an opinion, or even a little joke. I like helping people, I like knowing that I can count on someone else if I am stuck with something.&lt;/p&gt;

&lt;p&gt;Then I hated the tutorials we find online. They are fine to learn some vocabulary, to take the habit of writing pieces of code. To learn about ES6, to learn what is a For loop, but the transition between the tutorials and coding is hard mostly because tutorials give you the habit of telling you what to write and where, and also because coding is not about putting for loops everywhere!&lt;/p&gt;

&lt;p&gt;I thought learning at home was the better thing to do for me because I have a 9 and a 11 years old at home. I could learn code in the morning, be there for all the extra activities in the afternoon, and I wouldn't have to pay for child care during summer break. I knew my coding journey would be long, but I accepted it.&lt;/p&gt;

&lt;p&gt;At some point, I was forced to realize that my activities as a mom where taking too much of my daily time and I wasn't learning so much. Sometimes I had to review all the things I had learned the past few days because I didn't spend enough time practicing it to remember it.&lt;/p&gt;

&lt;p&gt;So in November 2019 I decided that I had to speed up my learning, and I enrolled in a bootcamp. &lt;/p&gt;

&lt;p&gt;When you enroll, they tell you that you have to spend 20 hours of solo work, that you have to breath and eat coding, and that you have sometimes forget that you need to sleep. Well, if you want to ultra perform your bootcamp, all of this is true. But let's face it: I am not that profile of person, I have the responsibility of little humans, I can't just eat chips 3 days in a row, I can't say "meh laundry can wait an other day". My kids and the chores I have have to be a priority, and my work needs to be organized around that. &lt;/p&gt;

&lt;p&gt;Did it work? Yes! I have put my kids in child care at school, find some support around me in case of a problem, and my husband changed his work schedule to pick up the kids before child care closed. I almost never stayed late at school, I did my commute to be able to eat with my family at night, talk a little bit, and put the kids into bed before starting my homework. And I used all my commute time in the mornings and evenings to read or review the lessons.&lt;/p&gt;

&lt;p&gt;The most challenging part of the immersive was during the group projects. When you work with people who don't understand what you are facing, it's easy to feel really guilty because you can't do as much as they do. But I have always been really honest with them, and I did my best to deliver what I had to. &lt;/p&gt;

&lt;p&gt;Well, it worked like that during 6 weeks... and then the pandemic happened! Suddenly all my organization was obsolete. &lt;br&gt;
I didn't have commute anymore, but I had school to organize, groceries to bleach, more cooking everyday, and I still had a regular day in front of my camera in the living room, with two crazy kiddos in desperate need to run, and jump, and yell, and fight, and cry, and come in front of my camera. &lt;/p&gt;

&lt;p&gt;The rest of the bootcamp has been emotionally intense, mostly because I felt like I was missing a lot. Every time I had to look at my kids, be the mediator, explain a math problem, I missed something important that was explained. These constant micro interruptions disturbed my learning flow. &lt;br&gt;
Hopefully our instructors were amazing. They managed to adapt to the remote mode quickly, we had pulse checks often, we were continuously adapting to the situation. I took advantage of the group projects to do remote pair programming and review important parts of the lessons that I missed, and I did what any Software Engineer do all day long: I stalked Stack Overflow, blogs, Youtube tutorials, and asked questions.&lt;/p&gt;

&lt;p&gt;My final project was a solo one, and I really wanted to do a MERN app, but React has been a little bit too picky with me. My MVP was 3 models, full CRUD on 2 of them, authentication, and use of a React CSS library. &lt;br&gt;
I thought I could do it, but I had to learn more about React and understand what I was missing. When it finally clicked, I had 4 days left to finish my app. Realistically I wouldn't reach MVP. Well... I could have done it, but remember, I am a mom, and there are things I just can't avoid, and there are only 24 hours in a day.&lt;/p&gt;

&lt;p&gt;In the end, I created my app, and it works, even if I didn't have all the features the day of the presentation. But when I look at my level back in January, and what I am capable of today, I am very proud of myself. Not only I can create an app from back end to front end, but I also know how to search for answers, I have opinions on what I like, I know what I want to learn, and I am capable of learning by myself and being dedicated to it, simply because I like it!&lt;/p&gt;

&lt;p&gt;And I graduated!! Yay!! It doesn't feel like it because I didn't have a graduation party with my cohort, but I have taped my Certificate and congratulation notes in the living room, to show off a little bit!&lt;/p&gt;

&lt;p&gt;I have also learned very important lessons from the strange situation we are living right now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sh*t happens. There is no such thing as a "better moment" to do your bootcamp. Even when everything is well aligned, a microcosmic creature can held hostage the entire planet. &lt;/li&gt;
&lt;li&gt;We are all in this mess together, everybody knows that you have a life, and that suddenly the line between work and life disappeared. Your kids appeared on the camera? So what? You won't be fired because of that. They showed up and talked too loud while you were presenting something? So what? Cut the mic, tell them to go away and come back later, and return to your presentation. Don't tell me you never got interrupted by a noisy siren or laughing colleagues while presenting something at the office...&lt;/li&gt;
&lt;li&gt;Your schedule isn't working anymore? Do an other one. Everybody, and especially your kids, benefits from having one, and having dead lines. And review it very often. &lt;/li&gt;
&lt;li&gt;You have to accept that your work might not be perfect. Don't expect to deliver as much as usual when you work in an altered mode. Set little milestones, and when you reach them, celebrate (you probably need to work on your happy dance if you don't have one!).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And these are my best advices for the bootcamp:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Have a journal. Write everything you liked or disliked, everything you want to learn about, all the things you have heard but didn't understand at the moment. The bootcamp pace is crazy fast, pandemic life makes it even faster. When the bootcamp is done you will love to have these notes, it will give you an idea of what you want to do as a Software Engineer, and the things you really want to learn.&lt;/li&gt;
&lt;li&gt;Communicate. You are not weak because you express your feelings. You are not weak because you ask for help. The purpose of the bootcamp is also to show you that you can code for 15 years and still search for answers on the web. You will always need help, need insight, need advice, so talk about it. And there will be moments when the impostor syndrome will kick in, and sometimes you can't face it alone.&lt;/li&gt;
&lt;li&gt;If you have kids, or are caring for someone at home, remember that sometimes it takes a village. Surround yourself with people you can count on. Student services from the bootcamp can also help in certain situations. Maybe you won't have to ask anything, but just in case it's good to have a back up.&lt;/li&gt;
&lt;li&gt;And finally: never ever compare yourself, your level, your work to others. The only person you have to be accountable to is yourself!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wrote this article just to talk about my experience and to show that it's possible. Uncertainty shouldn't stop you to move forward.&lt;br&gt;
I think my next article will be about the job search with kids during a pandemic. Spoiler alert: it's pretty much the same thing! :)&lt;/p&gt;

&lt;p&gt;Aurelie&lt;/p&gt;

</description>
      <category>bootcamp</category>
      <category>kids</category>
      <category>pandemic</category>
    </item>
  </channel>
</rss>
