<?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: João Chitas</title>
    <description>The latest articles on DEV Community by João Chitas (@jpachitas).</description>
    <link>https://dev.to/jpachitas</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%2F131847%2F58732359-2336-4f42-932e-8ec5aa8af049.jpeg</url>
      <title>DEV Community: João Chitas</title>
      <link>https://dev.to/jpachitas</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jpachitas"/>
    <language>en</language>
    <item>
      <title>Saving data inside the browser’s storage — a summary</title>
      <dc:creator>João Chitas</dc:creator>
      <pubDate>Mon, 19 Aug 2019 20:11:02 +0000</pubDate>
      <link>https://dev.to/runtime-revolution/saving-data-inside-the-browser-s-storage-a-summary-1b4m</link>
      <guid>https://dev.to/runtime-revolution/saving-data-inside-the-browser-s-storage-a-summary-1b4m</guid>
      <description>&lt;h3&gt;
  
  
  Saving data inside the browser’s storage — a summary
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--m94xmI0Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2Akz4cKjgM2rdsLISh" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m94xmI0Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2Akz4cKjgM2rdsLISh" alt=""&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/@samuelzeller?utm_source=medium&amp;amp;utm_medium=referral"&gt;Samuel Zeller&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every time you visit a website you may have noticed that on repeated visits there are some elements that no longer appear or load faster. It could be cache working its magic or maybe there is something inside your browser that triggers these behaviors.&lt;/p&gt;

&lt;p&gt;A very simple example: modals asking for your consent about the use of cookies. After the EU approved the GDPR regulation, many websites started showing a modal warning the user that, to improve their experience navigating the page, they use &lt;em&gt;cookies.&lt;/em&gt; Accepting the use of these needs to be stored somewhere so that when you visit the site for a second time, it would behave in a different way (in this case, the consent modal would no longer appear). This could be stored inside a server database but that would be complex. Instead, the browser has its own storage and &lt;em&gt;cookies&lt;/em&gt; are just one storage type. Your choice is then stored inside your browser in the &lt;em&gt;cookies&lt;/em&gt; store.&lt;/p&gt;

&lt;p&gt;With this post, I’ll try to explain to you, in a very brief way, the different types of browser storage that you can use while providing some code snippets to illustrate their usage. In the end, I’ll list references to posts with more details about this topic!&lt;/p&gt;

&lt;h3&gt;
  
  
  Cookies
&lt;/h3&gt;

&lt;p&gt;Good old &lt;em&gt;cookie.&lt;/em&gt; This is probably the most famous browser storage. Everyone who surfs the internet has heard about it. From this &lt;a href="http://www.whatarecookies.com/"&gt;link&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Each cookie is effectively a small lookup table containing pairs of (key, data) values — for example (firstname, John) (lastname, Smith). Once the cookie has been read by the code on the server or client computer, the data can be retrieved and used to customise the web page appropriately.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is easy to create or get a &lt;em&gt;cookie&lt;/em&gt;. The document element contains an API to manipulate them. Here are some code examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// get all cookies
cookies = document.cookie;

// add a cookie
// must be a string with the format "key=value"
document.cookie = "pokemon=bulbasaur";
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Local Storage
&lt;/h3&gt;

&lt;p&gt;Local Storage is a type of web storage that stores data as a key/value pair structure and without expiration date. Even if the user ends their session, the data inside local storage will not disappear. The value stored can only be a string and if the user wants to store an object, they will need to &lt;em&gt;stringify it&lt;/em&gt; when storing and &lt;em&gt;JSON parse it&lt;/em&gt; when retrieving the value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// get the storage
pokedex = window.localStorage;

// insert into store
pokedex.setItem('1', 'Bulbasaur');
pokedex.setItem('25', 'Pikachu');

// get from store
let pikachu = pokedex.getItem('25');
console.log(pikachu); // _Pikachu_

// remove from store
pokedex.removeItem('1');
let bulbasaur = pokedex.getItem('1');
console.log(bulbasaur); // _null_

// clear the store _aka_ reset pokedex
pokedex.clear();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Session Storage
&lt;/h3&gt;

&lt;p&gt;Session storage is very similar to Local Storage. The main difference is that after the page session ends, the data inside the Session Storage is cleared. Both Local Storage and Session Storage have the same API. Just type pokedex = window.sessionStorage to access it.&lt;/p&gt;

&lt;h3&gt;
  
  
  IndexedDB
&lt;/h3&gt;

&lt;p&gt;IndexedDB is a more complex type of storage, useful for storing larger amounts of data and complex objects. The API is much more complicated to use, compared to the ones provided by Cookies and Local/Session Storages. Because of that, there are libraries that make it easier to use. Like the other types of storage, you can store and retrieve elements using a &lt;strong&gt;key&lt;/strong&gt;. For that, you’ll need to specify the database schema, open a connection and manipulate the data with &lt;strong&gt;transactions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here is a snippet of a very simple flow for using the browser IndexedDB:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// init IndexedDB
let request= window.indexedDB.open('POKEDEX', 1);

// to create an new object store, you must define
// a function to onupgradeneeded
request.onupgradeneeded = function(event) {
  let db = request.result;
  let store = db.createObjectStore('POKEMONS', { keyPath: 'pk'});
};

// store on DB
request= window.indexedDB.open('POKEDEX', 1);
request.onsuccess = function(event) {
  let db = request.result;
  let transaction = db.transaction('POKEMONS', 'readwrite');

  let store = transaction.objectStore('POKEMONS');

  store. **put** ({
   pk: 'pikachu',
   value: {
     number: 25,
     name: 'Pikachu',
     moves: {
       "move\_1": "Volt Tackle",
       "move\_2": "Tail Whip"
     }
   }
  });

  transaction.oncomplete = function() {
    db.close();
  }
}

// get object from the store
request= window.indexedDB.open('POKEDEX', 1);
request.onsuccess = function(event) {
  let db = request.result;
  let transaction = db.transaction('POKEMONS', 'read');
  let store = transaction.objectStore('POKEMONS');

  let pokemon = store.get('pikachu');
  pokemon.onsuccess = function(event) {
    console.log(pokemon.result.value);
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Because this is a complex process, even for small examples like the one above, there are libraries, like &lt;a href="https://dexie.org/"&gt;dexie.js&lt;/a&gt;, that help you use IndexedDB.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;As you can see, browsers provide a variety of tools to store data for very specific cases. There is also another one called Web SQL but this one has been deprecated for a quite few years.&lt;/p&gt;

&lt;p&gt;This is just a very small summary of those tools so please, take a look at some references below for more information.&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API"&gt;IndexedDB API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage"&gt;Window.sessionStorage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage#Syntax"&gt;Window.localStorage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.whatarecookies.com/"&gt;What are Cookies - Computer Cookies - What is a Cookie&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nolanlawson.com/tag/indexeddb/"&gt;indexeddb | Read the Tea Leaves&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Pokémon © 2002–2019 Pokémon. © 1995–2019 Nintendo/Creatures Inc./GAME FREAK inc. TM, ® and Pokémon character names are trademarks of Nintendo.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;No copyright or trademark infringement is intended in using Pokémon content on this post.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;I’m currently a Ruby-on-Rails developer at Runtime Revolution that still likes to play the good old Pokemon games for the GameBoy. Go check our&lt;/em&gt; &lt;a href="https://www.runtime-revolution.com/?source=post_page---------------------------"&gt;&lt;em&gt;website&lt;/em&gt;&lt;/a&gt; &lt;em&gt;to know us more.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>web</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>browsers</category>
    </item>
    <item>
      <title>Organize your translations using multiple locales files</title>
      <dc:creator>João Chitas</dc:creator>
      <pubDate>Mon, 06 May 2019 14:56:53 +0000</pubDate>
      <link>https://dev.to/runtime-revolution/organize-your-translations-using-multiple-locales-files-2kg4</link>
      <guid>https://dev.to/runtime-revolution/organize-your-translations-using-multiple-locales-files-2kg4</guid>
      <description>&lt;p&gt;Of course, this contains an example with Pokémon!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sql4z1Hc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AlwT3xnIqSotzB1Yj" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sql4z1Hc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AlwT3xnIqSotzB1Yj" alt=""&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/@kylejglenn?utm_source=medium&amp;amp;utm_medium=referral"&gt;Kyle Glenn&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Internationalization of a website's content is always something to have in mind. Although many countries have a second language, not everyone knows how to speak or write it. In my country, Portugal, only the latest couple of generations understand English, at least in a way that they can use it on a daily basis. Some older generations didn’t even know how to read and write in Portuguese; illiteracy in our country was a major concern.&lt;/p&gt;

&lt;p&gt;Because of these type of things, a website (in my opinion) should have at least 2 languages a user can select from, or enough languages to reach as many users as it can.&lt;/p&gt;

&lt;p&gt;Hard-coded text in an application is somewhat of a bad practice, but in a Rails application we can find inside the configs/locales a file with the name en.yml. This file is a place where we can set strings that may appear in different places, instead of hard coding them. But, they don’t need to be only in English. You can create other translations files for different languages for instance: fr.yml and es.yml (French and Spanish, respectively).&lt;/p&gt;

&lt;p&gt;To change which locale you are using, you can set I18n.locale with the language code, or even set the default language with I18n.default_locale.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I18n.locale = :pt

I18n.deafaul\_locale = :es
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Okay but, now imagine this case: you are a Pokémon fan like me and you would like to make a website with all the information about them (names, types, moves…). Yes, you could save everything in a database, but that’s not the point, I don’t want you to be that smart.&lt;/p&gt;

&lt;p&gt;Start by adding info about the first 151 inside en.yml… It is already a lot of information, so you’ll have a very big file. OK, now create a locales file for Portuguese, pt.yml. Now you have all the info for a Portuguese native to read.&lt;/p&gt;

&lt;p&gt;I said to start with the first 151… Now add the ones from the second generation and you get info about 251 Pokémon. Oh, but in generation two, the generation one Pokémon can learn new moves, so you’ll have to update that info going through the whole file.&lt;/p&gt;

&lt;p&gt;This is a big edge case but I think you already know where I want to go with this… In the future, changing a locale file could be hard to manage if you don’t structure it right from the beginning.&lt;/p&gt;

&lt;p&gt;If only we could organize them a little bitbetter.&lt;/p&gt;

&lt;p&gt;Well, you can! Rails lets you organize your translations in a way that’s much more suitable to your project. You can create multiple locales files for the same language and spread them into different folders, in a structure that makes sense to you or the project scope. This example was taken from the Ruby on Rails &lt;a href="https://guides.rubyonrails.org/i18n.html#organization-of-locale-files"&gt;Guides&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|-defaults
|---es.rb
|---en.rb
|-models
|---book
|-----es.rb
|-----en.rb
|-views
|---defaults
|-----es.rb
|-----en.rb
|---books
|-----es.rb
|-----en.rb
|---users
|-----es.rb
|-----en.rb
|---navigation
|-----es.rb
|-----en.rb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;(The file's extension is in &lt;em&gt;ruby&lt;/em&gt; but you can use _yml _inside.)&lt;/p&gt;

&lt;p&gt;To use a structure like this, you need to let Rails know where to look for the files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# config/application.rb

config.i18n.load\_path += Dir[Rails.root.join(_'config'_, _'locales'_, _'\*\*'_, _'\*.{rb,yml}'_)]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Going back to our example, we can now think of a possible structure to organize our Pokémon’s information. Here’s an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|-pokemons
|--models
|---en.yml
|---pt.yml
|--views
|---en.yml
|---pt.yml
|-moves
|--models
|---en.yml
|---pt.yml
|--...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Or you can do something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|-models
|--pokemons
|---en.yml
|---pt.yml
|--moves
|---en.yml
|---pt.yml
|--...
|-views
|--homepage
|---en.yml
|---pt.yml
|--...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And then, each file will be something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# config/locales/models/en.yml

en:
 models:
  pokemon:
   name: Name
   type: Type
   moves: Moves
...

# config/locales/models/pt.yml

pt:
 models:
  pokemon:
   name: Nome
   type: Tipo
   moves: Ataques
...

# config/locales/views/homepage/pt.yml

pt:
 views:
  homepage:
   title: Pokémon e Companhia
   main\_section: Vou apanhá-los todos!
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Always scope the translations by the name of the folder, to avoid overrides.&lt;/p&gt;

&lt;p&gt;With a structure like this, it is now easier for you or any developer on your project to add, change or remove a translation for a specific language. This is great if you need to refactor some code and delete some legacy references in the project. Trust me, refactoring a big and unique translations file is not a pleasant task at all.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pokémon © 2002–2018 Pokémon. © 1995–2018 Nintendo/Creatures Inc./GAME FREAK inc. TM, ® and Pokémon character names are trademarks of Nintendo.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No copyright or trademark infringement is intended in using Pokémon content on this post.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;I’m currently a Ruby-on-Rails developer at Runtime Revolution that still likes to play the good old Pokemon games for the GameBoy. Go check our&lt;/em&gt; &lt;a href="https://www.runtime-revolution.com/"&gt;&lt;em&gt;website&lt;/em&gt;&lt;/a&gt; &lt;em&gt;to know us more. Oh, and we’re hiring!&lt;/em&gt;&lt;/p&gt;




</description>
      <category>i18n</category>
      <category>rails</category>
      <category>locale</category>
      <category>pokemon</category>
    </item>
    <item>
      <title>Toilet Vacant: A Rails app which notifies you via Slack</title>
      <dc:creator>João Chitas</dc:creator>
      <pubDate>Fri, 15 Feb 2019 10:56:10 +0000</pubDate>
      <link>https://dev.to/runtime-revolution/toilet-vacant-a-rails-app-which-notifies-you-via-slack-3omf</link>
      <guid>https://dev.to/runtime-revolution/toilet-vacant-a-rails-app-which-notifies-you-via-slack-3omf</guid>
      <description>

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PK9CmGlc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2Abgo3ArdsI5ozVsWf" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PK9CmGlc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2Abgo3ArdsI5ozVsWf" alt=""&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/@gabor?utm_source=medium&amp;amp;utm_medium=referral"&gt;Gabor Monori&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every day, there’s that time when you need to go to the toilet. You get off your chair, start walking towards a door with a drawing of a gentleman or a lady and hope that it is vacant. If your prayers were answered, you can enter and do what you got to do.&lt;/p&gt;

&lt;p&gt;But here, at our office, sometimes you see people (me included), walking around the office. They are not walking because it is healthy. No. They are walking because they are looking for a toilet that is vacant. And sometimes, in the worst case scenario, they go back to their place without doing their business.&lt;/p&gt;

&lt;p&gt;It happens to me a lot and it really grinds my gears (insert Peter Griffin meme here)!&lt;/p&gt;

&lt;p&gt;If only there was a way we could be notified on Slack that a toilet was vacated…&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Solution&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The true purpose of this post is not to present a complex solution to check if a real toilet is vacant. It is to show you how to use Slack’s Incoming Webhooks API on your Rails application, in a funny way.&lt;/p&gt;

&lt;p&gt;The full app is available at &lt;a href="https://github.com/jpac-run/toilet-vacant-app"&gt;https://github.com/jpac-run/toilet-vacant-app&lt;/a&gt; for you to checkout and see the application working. There is a README file with instructions on how to run it. Because of this, I won’t get into too much details for some parts. The only outstanding requirement you’ll need is to create a Slack application and permit the Incoming Webhooks. You can see how in this link: &lt;a href="https://api.slack.com/incoming-webhooks"&gt;https://api.slack.com/incoming-webhooks&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ok, now for some code.&lt;/p&gt;

&lt;p&gt;You know the drill: create a fresh Rails application and add httparty and dotenv-rails gems to your Gemfile.&lt;/p&gt;

&lt;p&gt;Create a ToiletsController with the index method and set it to be the application root in routes.rb.&lt;/p&gt;

&lt;p&gt;In the application root folder, create a file called .env. This file is used to store your environment variables.&lt;/p&gt;

&lt;p&gt;After you go through the steps in the Slack Incoming Webhooks link mentioned above, you’ll now have a special URL to send a message via the API, that we will store in a .env file, along with the channel name, like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;Again, inside your routes.rb, add two new routes:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;And define the index and update actions inside ToiletsController.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;But wait… we need some toilets!!! So, on a command line, type:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails g model Toilet toilet_number:integer, open:boolean
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and after your toilet model is created, set the open column with a default value of true inside the migration.&lt;/p&gt;

&lt;p&gt;With a toilet model, you can now create thrones — I mean, more toilets! You can either use the seeds.rb file or just run the Rails console and create some.&lt;/p&gt;

&lt;p&gt;Create a view to index all the toilets and for each one add a button/link that will call either the get_in or the get_out actions, depending on the state of the toilet. Something like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;Yeah, it’s not pretty, but neither is your toilet when you use it…&lt;/p&gt;

&lt;p&gt;Ok, sorry. Each of the actions will change the state of the selected toilet (change the open value to true or false) and (here comes the cool part) it will trigger an event that takes care of sending a notification to the Slack channel.&lt;/p&gt;

&lt;p&gt;To do this, we will use the ActiveSupport::Notifications to treat the events logic. Create an events.rb file inside config/initializers and subscribe your app to an event that will send the notification:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;Every time the occupied.toilet event is triggered, the code inside the subscribe block is executed. This block uses the httparty gem to call the Slack API. Inside the body of the request, you have to specify the name of the channel and your username. The field text contains the message you want to appear on the channel. The 🚽 and 💩 strings will appear as an emoji!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RCCkm_QE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/596/1%2AVId3W8CrS-0x32vuVmfGvw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RCCkm_QE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/596/1%2AVId3W8CrS-0x32vuVmfGvw.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can send a more custom message, just follow the API documentation.&lt;/p&gt;

&lt;p&gt;Now try to use this same logic to create an event that notifies the channel when the toilet is vacant!&lt;/p&gt;

&lt;p&gt;With this, I hope you got motivated to develop your own notifier for your office toilets and avoid getting up from your chair and go around the office looking for an empty little room to do what you got to do.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I’m currently a Ruby-on-Rails developer at Runtime Revolution that still likes to play the good old Pokemon games for the GameBoy. Go check our&lt;/em&gt; &lt;a href="https://www.runtime-revolution.com/"&gt;&lt;em&gt;website&lt;/em&gt;&lt;/a&gt; &lt;em&gt;to know us more. Oh and we’re hiring!&lt;/em&gt;&lt;/p&gt;





</description>
      <category>webdev</category>
      <category>ruby</category>
      <category>rails</category>
      <category>slack</category>
    </item>
    <item>
      <title>React: passing data between components… with Pokemon as an example!</title>
      <dc:creator>João Chitas</dc:creator>
      <pubDate>Tue, 20 Nov 2018 14:32:12 +0000</pubDate>
      <link>https://dev.to/runtime-revolution/react-passing-data-between-components-with-pokemon-as-an-example-37n0</link>
      <guid>https://dev.to/runtime-revolution/react-passing-data-between-components-with-pokemon-as-an-example-37n0</guid>
      <description>

&lt;h3&gt;
  
  
  React - Passing data between components… with Pokemon as an example!
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yHYBvLeU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AvWDGffKyCg5E2Lhz" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yHYBvLeU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AvWDGffKyCg5E2Lhz" alt=""&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/@unlesbar?utm_source=medium&amp;amp;utm_medium=referral"&gt;Stephan Henning&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Passing data between react components can be simple, but in some occasions, it can be very tricky. While from parent to child, and &lt;em&gt;vice-versa&lt;/em&gt;, can be a straightforward process, you’ll need to use the tools that react and javascript give you, in order to pass data to-and-from siblings (that is why Redux was invented).&lt;/p&gt;

&lt;p&gt;Let us focus first on the most simple ways of passing data from one component to another. And, to make it more fun, we’ll use Pokemon!&lt;/p&gt;

&lt;p&gt;How? To explain this concept, we are going to create/simulate a Pokemon battle, just like the good old first generation games for the GameBoy!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: you can find the source code inside this &lt;a href="https://github.com/jpac-run/pokemon-battle-blog-post"&gt;repository&lt;/a&gt;, with instructions on how to run and install the app, if you missed something or got stuck.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;p&gt;First, let us create a new react application. Click &lt;a href="https://github.com/facebook/create-react-app"&gt;here&lt;/a&gt; and it will send you to the create-react-app repository, a tool that let you create a new react application in no time. All the instructions can be found there. Then, create a react application (you can call it pokemon-battle). After that, inside the src folder, create a components folder and inside of it, a Pokemon and a GameManager folder. Each one must have an index.jsx file, where our components will be written.&lt;/p&gt;

&lt;p&gt;Start your app, open your browser and go to localhost:3000 to see your app running! (port 3000 is the default one, but it can be different in your case)&lt;/p&gt;

&lt;p&gt;After checking if everything is running, replace your App.js file with this one:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;Your application will break because you don’t have the GameManager component. But if you put the next code samples inside each corresponding index.jsx , the application will start running again.&lt;/p&gt;

&lt;h3&gt;
  
  
  Parent-to-Child
&lt;/h3&gt;

&lt;p&gt;A Pokemon battle consists of a fight between two Pokemon, selected by each trainer. The first Pokemon to attack is the one with &lt;em&gt;normal&lt;/em&gt; status and with the higher speed (there are other variables to take into account, but let’s keep it simple). If the HP of a Pokemon reaches 0 (zero), the Pokemon faints, and the one that is left standing wins the battle. For a Pokemon to attack, the trainer must choose one of the attacks/moves from the list of moves learned by the Pokemon.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9iTtD2HF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/540/1%2Av-fqtPahJ_Ur_KAgPr973Q.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9iTtD2HF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/540/1%2Av-fqtPahJ_Ur_KAgPr973Q.jpeg" alt=""&gt;&lt;/a&gt;Blast From The Past | Pokemon Red &amp;amp; Blue — taken from the website &lt;a href="http://www.dealspwn.com/blast-pokemon-red-blue-126035"&gt;&lt;/a&gt;&lt;a href="http://www.dealspwn.com/blast-pokemon-red-blue-126035"&gt;http://www.dealspwn.com/blast-pokemon-red-blue-126035&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Passing values from a parent component to a child component is easy. You just need to pass the values as props of the child element. To demonstrate that, the code below represents the part where the trainers choose the Pokemon they are going to send to battle. In this case, a Squirtle and a Charmander.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;When we get to the render function of the GameManager component, you can see that the information about Charmander is passed on to the first instance of the Pokemon component. Each prop is set one-by-one.&lt;/p&gt;

&lt;p&gt;On the other hand, the information about Squirtle is passed through a javascript object (the constant at the start of the code), using the &lt;em&gt;spread&lt;/em&gt; operator (ES6). Each key-value of the object will be treated as a prop of the child component.&lt;/p&gt;

&lt;p&gt;Now that we have passed the information about our two Pokemon, let’s extract that information inside the Pokemon component. We do this by accessing the &lt;em&gt;props&lt;/em&gt; attribute of the component. You can see that in the code below.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;As you can see, by accessing the props attribute of the component, we are able to render each Pokemon information inside the render method. Note that the props of a component are not limited to the render method, they can be accessed within any other method that you create!&lt;/p&gt;

&lt;h3&gt;
  
  
  Child-to-Parent
&lt;/h3&gt;

&lt;p&gt;Remember, for a Pokemon to attack, its trainer must choose a move from the ones that it has learned. When the trainer decides which moves the Pokemon should use, that information must be passed to the GameManager component. But how can the Pokemon component pass the data about the move to the parent component?&lt;/p&gt;

&lt;p&gt;A &lt;em&gt;direct-ish&lt;/em&gt; way of doing this (and the most common), is to pass a function that will work as a callback. This method must receive the child data that needs to pass to the parent as arguments. Take a look at the &lt;em&gt;getAttack&lt;/em&gt; method. The method signature tells us that it has 2 parameters. We then pass that same method as a &lt;em&gt;prop&lt;/em&gt; of the child component, with no arguments.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;Seems weird, right? Let’s look at the new Pokemon component.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;A wild &lt;em&gt;attack&lt;/em&gt; method appeared! If you notice, this method, when executed, calls the same method we have passed as a &lt;em&gt;prop&lt;/em&gt; of the Pokemon component. And this time, it takes 2 arguments. In this case, Pokemon name (which is a &lt;em&gt;prop&lt;/em&gt; of the component) and the selected attack/move object.&lt;/p&gt;

&lt;p&gt;To make this more interactive, the attack method is used as the callback method of the &lt;em&gt;onClick&lt;/em&gt; event, used in the buttons below. When we click on the button to choose a move, it calls the attached method, in this case, &lt;em&gt;attack&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;What &lt;em&gt;attack&lt;/em&gt; really does is simply calling the &lt;em&gt;getAttack&lt;/em&gt; of the GameManager component. This way, the Pokemon name and the move selected, are passed to the parent through that function!&lt;/p&gt;

&lt;p&gt;We then store that information in the GameManager state. By changing the state, the render method will be triggered again, thus showing the message created by the &lt;em&gt;showMessage&lt;/em&gt; method. Because we stored the passed data into the state, all methods that use it can have access to the Pokemon name and the attack/move selected.&lt;/p&gt;

&lt;p&gt;For simplicity, the &lt;em&gt;showMessage&lt;/em&gt; only shows a message with the name of the Pokemon that performed the attack and that same attack name. By passing other methods to the child component and store to the parent's state the data passed from the child, we can make more complex operations. An example was passing the information about the attack to Pokemon that will receive it and determine the hit points it would lose. Or determine if the receiver would evade the attack.&lt;/p&gt;

&lt;p&gt;And that’s it! The Pokemon component (child) passed data to the GameManager (parent).&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;These are just two quick examples to show you how components pass information between each other. There are other ways to do this, and other situations for each case to be used, but this is the basic logic for when it comes to passing data.&lt;/p&gt;

&lt;p&gt;You can make a mix of these two ways for siblings to communicate or if they don’t have any relation between them (a parent component), you can create a solution using &lt;em&gt;Redux&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Well, that’s all for now! Now go &lt;em&gt;catch’em all&lt;/em&gt;!&lt;/p&gt;

&lt;p&gt;If you want to know more about React, look at the library docs (they are very good), or read some of my colleague’s posts below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://revs.runtime-revolution.com/introduction-to-react-where-to-start-6edc5d3d5aff"&gt;Introduction to React — where to start?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://revs.runtime-revolution.com/implementing-conways-game-of-life-with-react-part-1-c0b974ae33eb"&gt;Implementing Conway’s Game of Life With React — Part 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://revs.runtime-revolution.com/implementing-conways-game-of-life-with-react-part-2-e2f68fee52e8"&gt;Implementing Conway’s Game of Life With React — Part 2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://revs.runtime-revolution.com/everything-redux-part-1-1d390fd51898"&gt;Everything Redux — Part 1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pokémon © 2002–2018 Pokémon. © 1995–2018 Nintendo/Creatures Inc./GAME FREAK inc. TM, ® and Pokémon character names are trademarks of Nintendo.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No copyright or trademark infringement is intended in using Pokémon content on this post.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;I’m currently a Ruby-on-Rails developer at Runtime Revolution that still likes to play the good old Pokemon games for the GameBoy. Go check our&lt;/em&gt; &lt;a href="https://www.runtime-revolution.com/"&gt;&lt;em&gt;website&lt;/em&gt;&lt;/a&gt; &lt;em&gt;to know us more. Oh and we’re hiring!&lt;/em&gt;&lt;/p&gt;





</description>
      <category>softwaredevelopment</category>
      <category>webdev</category>
      <category>react</category>
    </item>
  </channel>
</rss>
