<?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: Nissrine Canina</title>
    <description>The latest articles on DEV Community by Nissrine Canina (@nissrinecan).</description>
    <link>https://dev.to/nissrinecan</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%2F759997%2F310179b7-2c7f-4a9c-ad3c-4343a2d0e415.png</url>
      <title>DEV Community: Nissrine Canina</title>
      <link>https://dev.to/nissrinecan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nissrinecan"/>
    <language>en</language>
    <item>
      <title>Dynamics 365 Plug-in Step-by-Step</title>
      <dc:creator>Nissrine Canina</dc:creator>
      <pubDate>Thu, 13 Jul 2023 16:18:53 +0000</pubDate>
      <link>https://dev.to/nissrinecan/dynamics-365-plug-in-step-by-step-2ghn</link>
      <guid>https://dev.to/nissrinecan/dynamics-365-plug-in-step-by-step-2ghn</guid>
      <description>&lt;p&gt;Microsoft Dynamics 365 is a business agnostic product that provides a flexible and customizable platform for organizations across various industries. Plugins further enhance this agnostic nature by allowing businesses to tailor the platform to their specific requirements and extend its functionality beyond the out-of-the-box features.&lt;br&gt;
 Plugins are server-side custom components that interact with the platform's services and data. Plugins run within the Dynamics 365 server environment and can be triggered by events (also called messages) that occur within the platform. When a plugin is executed, it can utilize the Dynamics 365 platform's services, such as the Organization Service, to perform various operations, including but not limited to basic CRUD actions: retrieving, creating, updating, and deleting records. &lt;/p&gt;

&lt;p&gt;To develop a plugin for Microsoft Dynamics 365, you can follow these steps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Set up your development environment:&lt;/strong&gt;&lt;br&gt;
Install Visual Studio Community Edition for Dynamics 365 development.&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%2F6kj0ircsbbu0wqwk2m9i.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%2F6kj0ircsbbu0wqwk2m9i.png" alt="visual studio community edition"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Under Workloads select .NET desktop development:&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%2Ftek7aooehngw67wbw6z5.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%2Ftek7aooehngw67wbw6z5.png" alt="select .NET desktop development"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go to Individual Components tab, under development activities, select: Window Workflow Foundation&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%2F8c02oa9krlj3pauiliax.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%2F8c02oa9krlj3pauiliax.png" alt="select window workflow foundation under development activities"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, click install and select C# environment. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Create a new plugin project:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The next step is to create a new project and select Class Library (.NET Framework) and click Next:&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%2F1mltkl3ibib9ejgcl05l.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%2F1mltkl3ibib9ejgcl05l.png" alt="select class library .NET framework"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Configure project and solution names and click Create. The solution contains a collection of projects:&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%2F3s4p22mpgyoc6g42tr1a.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%2F3s4p22mpgyoc6g42tr1a.png" alt="cofigure name of project and solution"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use any meaningful name to Rename &lt;code&gt;class1.cs&lt;/code&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%2Fkerd22rnjhlp49fzk4g8.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%2Fkerd22rnjhlp49fzk4g8.png" alt="rename class1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Add references:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Go to tools -&amp;gt; NuGet Package Manger -&amp;gt; Manage NuGet Packages for Solutions. Then, browse (type Dynamics 365 in the search box), select, and install the following:&lt;br&gt;
Package1: &lt;code&gt;Microsoft.CrmSDK.CoreAssemblies&lt;/code&gt;&lt;br&gt;
package2: &lt;code&gt;Microsoft.CrmSDK.XrmTooling.PluginRegistrationTool&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Go to Solution Explorer -&amp;gt; right click on References -&amp;gt; Add Reference -&amp;gt; Browse -&amp;gt; Go to &lt;code&gt;solution name folder&lt;/code&gt; (ClassLibrary1 folder in this example) -&amp;gt; packages -&amp;gt; &lt;code&gt;Microsoft.CrmSDK.CoreAssemblies&lt;/code&gt; -&amp;gt; lib -&amp;gt; net462 -&amp;gt; add &lt;code&gt;Microsoft.Xrm.Sdk.dll&lt;/code&gt; -&amp;gt; Ok -&amp;gt; include &lt;code&gt;using Microsoft.Xrm.Sdk&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Add &lt;code&gt;System.ServiceModel&lt;/code&gt; from References:&lt;br&gt;
Go to Solution Explorer -&amp;gt; right click on References -&amp;gt; Add Reference -&amp;gt; Assemblies -&amp;gt; Framework -&amp;gt; type &lt;code&gt;System.ServiceModel&lt;/code&gt; in the search field -&amp;gt; select &lt;code&gt;System.ServiceModel&lt;/code&gt; -&amp;gt; Ok -&amp;gt; include &lt;code&gt;using System.ServiceModel&lt;/code&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%2Fi9qm6tkjotjeltdetinu.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%2Fi9qm6tkjotjeltdetinu.png" alt="include SDK and System.ServiceModel libraries"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Define the plugin class:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a new class that implements the &lt;code&gt;IPlugin&lt;/code&gt; interface provided by the Dynamics 365 SDK. Then, implement the &lt;code&gt;Execute&lt;/code&gt; method provided by &lt;code&gt;IPlugin&lt;/code&gt; interface, which will be called when the plugin is triggered. &lt;br&gt;
Go to &lt;a href="https://learn.microsoft.com/en-us/power-apps/developer/data-platform/write-plug-in" rel="noopener noreferrer"&gt;Microsoft Documentation&lt;/a&gt; and copy the Execute method logic template:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

public class MyPlugin : IPlugin
{
  public MyPlugin() {} // Constructor, does nothing

  public void Execute(IServiceProvider serviceProvider)
  {
    // Obtain the execution context
    IPluginExecutionContext context = (IPluginExecutionContext)
      serviceProvider.GetService(typeof(IPluginExecutionContext));

    // Obtain the Organization service reference 
    IOrganizationServiceFactory serviceFactory =
      (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
    IOrganizationService orgService = serviceFactory.CreateOrganizationService(context.UserId);

    // Obtain the Tracing service reference
    ITracingService tracingService =
      (ITracingService)serviceProvider.GetService(typeof(ITracingService));

    try
    {
      // TODO Plug-in business logic goes here. You can access data in the context,
      // and make calls to the Organization web service using the Dataverse SDK.
    }
    catch (FaultException&amp;lt;OrganizationServiceFault&amp;gt; ex)
    {
      throw new InvalidPluginExecutionException("The following error occurred in MyPlugin.", ex);
    }
    catch (Exception ex)
    {
        tracingService.Trace("MyPlugin: error: {0}", ex.ToString());
        throw;
    }
}


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

&lt;/div&gt;

&lt;p&gt;The execute method accepts a single &lt;code&gt;IServiceProvider&lt;/code&gt; parameter which has a single method &lt;code&gt;GetService&lt;/code&gt;. This method provides access to the execution context data (information about the entity and message request that caused the event and invoked the plugin). Also, &lt;code&gt;GetService&lt;/code&gt; method provides access to Organization Web Service to perform message request to the database (i.e. read, update, create, delete).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Handle plugin execution:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Entity is accessible via context that has &lt;code&gt;InputParameters&lt;/code&gt; collection which &lt;code&gt;Contains&lt;/code&gt; an object with a &lt;code&gt;Target&lt;/code&gt; key along with all data passed in the message request. Entity is a generic class that can represents any record (i.e. contact, account, task...). It provides a collection of the corresponding attributes of a given record on which the plugin is registered. These attributes are accessible using the logical names, not the display names.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

try
       {
         // Plug-in business logic goes here.  

 string firstName = entity.Attributes["firstname"].ToString();
                    }
 string lastName = entity.Attributes["lastname"].ToString();
         // Assign data to attributes

 entity.Attributes.Add("description", "Greetings! " +  firstName + " " + lastName);
                }


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

&lt;/div&gt;

&lt;p&gt;The next step is to Sign the assembly with an encrypted algorithm because only signed assemblies are allowed by the cloud platform:&lt;br&gt;
Right click on project -&amp;gt; properties -&amp;gt; signing -&amp;gt; check sign the assembly -&amp;gt; select New -&amp;gt; add key file name -&amp;gt; choose whether to add a password or not -&amp;gt; keep default or change algorithm -&amp;gt; Ok -&amp;gt; save -&amp;gt; build solution. &lt;br&gt;
After this step, the code is compiled and an assembly should be created in a form of &lt;code&gt;dll&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Register and deploy the plugin:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use the plugin registration tool downloaded in step 3 to upload the    &lt;code&gt;dll&lt;/code&gt; to the cloud file:&lt;br&gt;
Right click on project name -&amp;gt; open folder in explorer -&amp;gt; Go one step up in folder directory -&amp;gt; packages -&amp;gt; &lt;code&gt;Microsoft.CrmSdk.XrmTooling.PluginRegistrationTool&lt;/code&gt; -&amp;gt; tools -&amp;gt; open &lt;code&gt;PluginRegistration&lt;/code&gt; -&amp;gt; create new connection -&amp;gt; login using Dynamics 365 credentials, select Office 365, and region -&amp;gt; login:&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%2Fx8e1bgd6urmdnmrxaolj.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%2Fx8e1bgd6urmdnmrxaolj.png" alt="Plugin registration tool login"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go to Register -&amp;gt; Register new assembly -&amp;gt; browse to project -&amp;gt; bin -&amp;gt; debug -&amp;gt; select &lt;code&gt;filename.dll&lt;/code&gt; -&amp;gt; open -&amp;gt; select the assembly in step 2 -&amp;gt; keep default setting in steps 3 &amp;amp; 4 -&amp;gt; register -&amp;gt; Ok.&lt;/p&gt;

&lt;p&gt;The plugin is now uploaded to the list of assemblies. Next, we should configure when the plugin should be executed:&lt;br&gt;
Select plugin and right click -&amp;gt; click register new step:&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%2F5gtihdngfj5tbot9w1h8.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%2F5gtihdngfj5tbot9w1h8.png" alt="Register new step form"&gt;&lt;/a&gt;&lt;br&gt;
Message: Create -&amp;gt; Primary Entity: contact -&amp;gt; Event Pipeline Stage of Execution: PreOperation -&amp;gt; Register new step.&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%2F61x18sowp5bnijzcsmft.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%2F61x18sowp5bnijzcsmft.png" alt="Plugin Pipeline: what happens on server?"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Image by Paresh Sharma&lt;/em&gt; &lt;a href="https://dev.tourl"&gt;https://www.tech-quantum.com/d365-understanding-plug-in-pipeline/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The plugin will update the attribute collection of primary entity &lt;code&gt;contact&lt;/code&gt;which is being passed to the main event. When the user creates an account (first name and last name), the data goes through the pipeline to the Pre-Operation stage and in the &lt;code&gt;serviceProvider&lt;/code&gt; which will provides the contextual data. From that context, we can extract entity information. In this case, the entity represents &lt;code&gt;contact&lt;/code&gt; form.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Test the plugin:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a new contact in the Sales Hub:&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%2Femyfhqfam5e7cdz33ajk.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%2Femyfhqfam5e7cdz33ajk.png" alt="create test contact"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go to details and check Personal Notes:&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%2Fqymzgfwzaioltlck7ot2.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%2Fqymzgfwzaioltlck7ot2.png" alt="Personal Notes Greeting user"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Throughout this blog, we discussed the step-by-step process of developing a plugin, including setting up the development environment, defining the plugin logic, registering, deploying and testing the plugin.&lt;/p&gt;

&lt;p&gt;References:&lt;br&gt;
&lt;a href="https://learn.microsoft.com/en-us/power-apps/developer/data-platform/plug-ins" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/power-apps/developer/data-platform/plug-ins&lt;/a&gt;&lt;/p&gt;

</description>
      <category>microsoft365</category>
      <category>dynamics</category>
      <category>plugin</category>
      <category>crm</category>
    </item>
    <item>
      <title>Why Software Engineering?</title>
      <dc:creator>Nissrine Canina</dc:creator>
      <pubDate>Tue, 13 Dec 2022 03:02:39 +0000</pubDate>
      <link>https://dev.to/nissrinecan/why-software-engineering-1mn8</link>
      <guid>https://dev.to/nissrinecan/why-software-engineering-1mn8</guid>
      <description>&lt;p&gt;Software Engineering is a very rich field that satisfies a wide spectrum of skills. It can look different from one industry to another and even within the same field. This variety offers endless opportunities to learn and grow progressively. There are many reasons that make this career choice attractive other than the typical financial stability that makes this field stands out and attract fresh graduates as well as career switchers. Here are just a few reasons why:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The continuous learning aspect&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Software engineers are in a constant learning mode because this field is in constant renovation. This condition may not suit everyone but if you don't thrive in routine and dead-end jobs, programming is the way to go. Continuous learning makes the day interesting and exciting, especially with the little achievements that make you thirsty for more. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem-solving skills&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Software developers must think logically and solve problems ranging from quick fixes to more complex tasks. Additionally, finding optimum solutions via task analysis and making decisions about each step of the way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Team collaboration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It is not uncommon to assume that programmers work alone but being a team player is a crucial skill to collaborate with other developers. Everyone learns at different paces; therefore, every developer brings value to the team.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Access to learning resources&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are many educational pathways to pursue a career in software development ranging from a traditional Computer Science Degree to online programs(free and paid). Technology is changing and there will be always new resources available.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flexibility&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Another advantage of being a software engineer is that you can work remotely depending on the job requirements. Some positions even require traveling for conferences and networking.&lt;/p&gt;

&lt;p&gt;The software development field is definitely an exciting field of study that is worth exploring.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Building a Many-to-Many Association in Rails-React App</title>
      <dc:creator>Nissrine Canina</dc:creator>
      <pubDate>Sat, 10 Dec 2022 18:39:14 +0000</pubDate>
      <link>https://dev.to/nissrinecan/building-a-many-to-many-association-in-rails-react-app-3fe3</link>
      <guid>https://dev.to/nissrinecan/building-a-many-to-many-association-in-rails-react-app-3fe3</guid>
      <description>&lt;p&gt;One of my capstone project's features was categorizing posts by topics where the user is able to create topics, posts, and post to different topics. Also, displaying lists of posts in each topic category. To achieve this functionality, I have used Many-to-Many relationships where the topic has-many posts and the post-has-many topics through a join table topic-posts. There are various methods available when joining tables that will allow useful functionalities. In this blog, I will walk you through how I implemented this feature step by step.&lt;/p&gt;

&lt;p&gt;The user should be able to create a post via the form below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8tM47TtK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ul60id4mm775cumun0p0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8tM47TtK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ul60id4mm775cumun0p0.png" alt="post form" width="880" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that the topic is not a column in the post table, the topic has a separate model and linked to post via Many-to-Many association.&lt;/p&gt;

&lt;p&gt;First, we have to create the tables in the database. We need a topics table, a posts table, and a topic-posts join table.&lt;/p&gt;

&lt;p&gt;The Entity Relationship Diagram:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9UVOKulC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p5az1lwfwq8f3tpxba47.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9UVOKulC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p5az1lwfwq8f3tpxba47.png" alt="entity relationship diagram" width="880" height="985"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A snapshot of the schema:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uyTd_jiD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l9uuw4lb17iu7wjua9dq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uyTd_jiD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l9uuw4lb17iu7wjua9dq.png" alt="schema" width="880" height="648"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UYrJG8F9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gnhgni2ec9x5q2qnfzc8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UYrJG8F9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gnhgni2ec9x5q2qnfzc8.png" alt="schema" width="880" height="204"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, specify the has-many-through association:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iPlz6bny--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j06ah5yvufghy3utlt5o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iPlz6bny--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j06ah5yvufghy3utlt5o.png" alt="associations" width="880" height="239"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---kndYywf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ng38n098x4mp9dkpshj0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---kndYywf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ng38n098x4mp9dkpshj0.png" alt="associations" width="880" height="198"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kDvGDG5D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jnwok5y98bvh5lh6oizm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kDvGDG5D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jnwok5y98bvh5lh6oizm.png" alt="associations" width="880" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, create the necessary actions on the join table controller:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Oo9Z0kHs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wdsgivzax9tp9lgsm3e2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Oo9Z0kHs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wdsgivzax9tp9lgsm3e2.png" alt="index and show actions" width="880" height="484"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--w5gkLbPl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nfwp3w89wcplfl3m1gtd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--w5gkLbPl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nfwp3w89wcplfl3m1gtd.png" alt="create action" width="880" height="343"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_5kiv02g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tcvavy7vhuqom8xxj4p6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_5kiv02g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tcvavy7vhuqom8xxj4p6.png" alt="private methods" width="880" height="335"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Similarly, the &lt;code&gt;create&lt;/code&gt; action on the post-model controller should look like this: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YkHCGmef--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0pb82wz2djhvwi0ylco3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YkHCGmef--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0pb82wz2djhvwi0ylco3.png" alt="create post action" width="880" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The most important step in the &lt;code&gt;create&lt;/code&gt; action of the post is that we should create the corresponding join table before saving the post to the database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SerN7eP9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s4crfxob8atum6i2nwh7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SerN7eP9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s4crfxob8atum6i2nwh7.png" alt="post params" width="880" height="114"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Because of the Many-to-Many relationship, it is important to pluralize &lt;code&gt;topic_ids&lt;/code&gt; and represent it with an empty array &lt;code&gt;[]&lt;/code&gt;. In this case, we only need the first id index as shown in the create action above.&lt;/p&gt;

&lt;p&gt;Now, off to the front end, to see what the &lt;code&gt;fetch POST&lt;/code&gt; body sent with the request should look like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CbtcJ1cF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xh6b6nkxpvk2jv7uysgj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CbtcJ1cF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xh6b6nkxpvk2jv7uysgj.png" alt="fetch post body" width="880" height="271"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Select&lt;/code&gt; and &lt;code&gt;Option&lt;/code&gt; tags on the form were styled using &lt;code&gt;material-tailwind/react&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Pjpmk45B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vbq1qpcj4lz4tp7qat4i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Pjpmk45B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vbq1qpcj4lz4tp7qat4i.png" alt="select and option tags" width="880" height="248"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mistakes to learn from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using a styling library in the front end before configuring the functionality of the backend can lead to errors that are not obvious to detect. It is recommended to first use the basic &lt;code&gt;select&lt;/code&gt; and &lt;code&gt;option&lt;/code&gt; tags to ensure that the styling library requirements don't interfere with tag attributes. In my case, the Material-tailwind/React library documentation stated that the value attribute of the &lt;code&gt;Option&lt;/code&gt; tag should be a string whereas we need to send it as an integer to the backend.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is a snapshot of the documentation of the Material-tailwind/React library:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iDzVa0Pl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4k2knq46mpzvm2tgju7g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iDzVa0Pl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4k2knq46mpzvm2tgju7g.png" alt="material tailwind library docs" width="880" height="238"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since the value attribute datatype was an integer, interpolating the value was the way to fulfill the styling library requirements. Additionally, we should &lt;code&gt;parseInt(state value)&lt;/code&gt; to make sure we are sending an integer value to the backend.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Saving the post to the database without creating a corresponding join table was another mistake that I made that resulted in creating posts without being assigned to a specific topic category. Also, it is important to wrap &lt;code&gt;topic_ids&lt;/code&gt; in a string quote due to the styling library requirements discussed above. 
Creating the join table will only be necessary depending on the functionality we are looking for. For instance, in this project, the user can create many topics and topics have many users. For this type of behavior, I did not need to create the join table &lt;code&gt;topic-users&lt;/code&gt; before saving the topic to the database although the &lt;code&gt;topic-users&lt;/code&gt; join model is needed for Many-to-Many associations. The difference here is that I want my post to be specifically assigned to a topic at the time of creation, whereas that is not the case when a user creates a topic; there was no emphasis on which user creates the topic. &lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rails</category>
      <category>react</category>
      <category>tailwindcss</category>
    </item>
    <item>
      <title>Understanding Polymorphic Associations in Rails</title>
      <dc:creator>Nissrine Canina</dc:creator>
      <pubDate>Sat, 01 Oct 2022 15:59:56 +0000</pubDate>
      <link>https://dev.to/nissrinecan/understanding-polymorphic-associations-in-rails-jo7</link>
      <guid>https://dev.to/nissrinecan/understanding-polymorphic-associations-in-rails-jo7</guid>
      <description>&lt;p&gt;The Ruby on Rails documentation defines polymorphic associations (PA) as: "&lt;em&gt;A slightly more advanced twist on associations is the polymorphic association. With polymorphic associations, a model can belong to more than one other model, on a single association.&lt;/em&gt;". As I am researching this topic to implement it in my project, I have found that understanding what problems polymorphic associations solve makes learning this new concept much simpler.&lt;/p&gt;

&lt;p&gt;Another way to rephrase the Rails documentation definition is that PA is needed when multiple parent models use one child model. To understand how useful PA is in this case, we should investigate the issues that will arise without applying PAs. For demonstration purposes, let's create a simple Rails application with four models using conventional &lt;code&gt;has_many&lt;/code&gt; and &lt;code&gt;belongs_to&lt;/code&gt; associations. &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%2Ff8m0p7iar58accocadpf.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%2Ff8m0p7iar58accocadpf.png" alt="has_many and belongs_to associations of article, post, event, and comment models"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, let's check our comments in the schema:&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%2Fc2tt0jydy12janljilzh.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%2Fc2tt0jydy12janljilzh.png" alt="comments schema"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we can see in the comments schema, &lt;code&gt;event_id&lt;/code&gt;, &lt;code&gt;post_id&lt;/code&gt;, and &lt;code&gt;article_id&lt;/code&gt; are required even though the comment is meant to be assigned for one model at a time and not all in one instance. Let's hop on our console and see the flow of events:&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%2F3bjic11gs8hblkbw8qov.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%2F3bjic11gs8hblkbw8qov.png" alt="creating post comments in the console"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that the comment did not save to the database because it requires the existence of the event and the article (recall the &lt;code&gt;null: false&lt;/code&gt; property in the schema which means that all foreign keys must exist in order to create and save a comment to the database). There is a way around this issue even though it is definitely inefficient: &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%2Fbsrcfp85pg9uxv9antfg.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%2Fbsrcfp85pg9uxv9antfg.png" alt="creating a post comment with event and article ids in the console"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is clear how we had to build new columns in our comment table for the event and article when the main purpose was to create a comment for the post only. We can see how conventional associations were not helping the DRY principle (unnecessary rows in tables with null values) in this case. We can remove the constraint &lt;code&gt;null: false&lt;/code&gt; and add &lt;code&gt;optional:true&lt;/code&gt; in the comment class. This will allow us to create and save a comment successfully without manually assigning the unwanted foreign keys; however, they will be still parsed as nil in the comment table.&lt;/p&gt;

&lt;p&gt;The efficient solution for this example is PA. Let's update the migration to add PA and remove all the foreign keys for the article, event, and post models.&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%2Fbjjxsro0zb678ublg4y6.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%2Fbjjxsro0zb678ublg4y6.png" alt="migration add polymorphic to comments and remove foreign keys"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, we update all the models as shown below:&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%2F5cyhjw53z4474iv8qsap.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%2F5cyhjw53z4474iv8qsap.png" alt="add polymorphic association"&gt;&lt;/a&gt;&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%2Fuploads%2Farticles%2F6fc4bs0gb3nkf35jdi1p.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%2F6fc4bs0gb3nkf35jdi1p.png" alt="article as commentable"&gt;&lt;/a&gt;&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%2Fuploads%2Farticles%2Fv4nqxpyl1df5vm1okhbp.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%2Fv4nqxpyl1df5vm1okhbp.png" alt="event as commentable"&gt;&lt;/a&gt;&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%2Fuploads%2Farticles%2Ftcmhdnq7n6uovr9has4a.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%2Ftcmhdnq7n6uovr9has4a.png" alt="post as commentable"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;:commentable&lt;/code&gt; refers to the post, event, and article models. Let's comment on a post and an event in the console and pay close attention to &lt;code&gt;commentable_type&lt;/code&gt; and &lt;code&gt;commentable_id&lt;/code&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%2Fzy2pcsokywkpif8o5nvq.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%2Fzy2pcsokywkpif8o5nvq.png" alt="create a comment on a post using polymorphic associations"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we are creating a comment on a post using PA without wasting space in the database. We also follow the DRY principle by removing three &lt;code&gt;belongs_to&lt;/code&gt; associations from the comments model.  Also, we are able to link the behavior expected for a commentable component to any model. We are separating concerns and reusing code. Let's create another comment on an event and note the change in the &lt;code&gt;commentable-type&lt;/code&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%2Fd6b7kf9eju1mj6fvbuwf.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%2Fd6b7kf9eju1mj6fvbuwf.png" alt="create a comment on the event using polymorphic associations"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see that the comments were created without loading our tables with nil columns. The &lt;code&gt;commentable_type&lt;/code&gt; refers to the target model that is associated with the comment. Therefore, only the target model foreign key is created.&lt;br&gt;
 The comments are accessible using &lt;code&gt;has_many&lt;/code&gt; association: &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%2Fr720mdg2sir5lp96fpkz.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%2Fr720mdg2sir5lp96fpkz.png" alt="accessing post and event comments"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is important to know that accessing the parent model of a specific comment will require the use of &lt;code&gt;.commentable&lt;/code&gt; method. For instance we cannot use &lt;code&gt;comment.post&lt;/code&gt; or &lt;code&gt;comment.event&lt;/code&gt; to access the parent model otherwise we will get a &lt;code&gt;NoMethodError&lt;/code&gt;. Remember that we modified the &lt;code&gt;belongs_to&lt;/code&gt; associations with &lt;code&gt;as: :commentable&lt;/code&gt;. Where commentable refers to the parents' models. Check the console below:&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%2Fsbye5t8mbmlrnryhrk7u.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%2Fsbye5t8mbmlrnryhrk7u.png" alt="access the parent model of a specific comment"&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%2F6fpbgzv7k9xg52hvy8d7.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%2F6fpbgzv7k9xg52hvy8d7.png" alt="access the parent model of a specific comment"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Finally, we can think of PA anytime we are faced with the need to share a model property among other models. For instance, an image model can be used by other models such as products and categories. so, imageable is the way to go!&lt;/p&gt;

&lt;p&gt;I hope this walkthrough example is helpful for anyone learning PA for the first time.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Rails Join Table - Step by Step Guide to Create a Favoriting Feature in an Ecommerce App</title>
      <dc:creator>Nissrine Canina</dc:creator>
      <pubDate>Fri, 03 Jun 2022 02:20:16 +0000</pubDate>
      <link>https://dev.to/nissrinecan/rails-join-table-step-by-step-guide-to-create-a-favoriting-feature-in-an-ecommerce-app-ol3</link>
      <guid>https://dev.to/nissrinecan/rails-join-table-step-by-step-guide-to-create-a-favoriting-feature-in-an-ecommerce-app-ol3</guid>
      <description>&lt;p&gt;In a context of a basic e-commerce app where a user can buy, list, edit, and like an item. We are going to focus on the feature where the user can view item details and click the heart icon to save the item in the favorites list. The user can view or delete items from the favorite list. In this article, I am going to walk you through the steps to set up your backend and frontend to achieve this functionality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Entity Relationship Diagram (ERD)
&lt;/h2&gt;

&lt;p&gt;Create an ERD of three models: a user, an item, and a favorite_item where a user has many favorite_items and has many items through favorite_items. Similarly, an item has many favorites_items as well as many favorated_by (aliased users) through favorite_items. The first association (the user has many items as favorites) is what we need for the favoring feature. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xDkX6stX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ghr4f3osdy5qt2qs5tlf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xDkX6stX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ghr4f3osdy5qt2qs5tlf.png" alt="Entity Relationship Diagram showing 3 models: user, item, and join table (favorite_item)" width="880" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Generate Resource and Add Associations in Rails
&lt;/h2&gt;

&lt;p&gt;Use the resource command generator to create the join table of favorite items. The resource will generate the model, controller, serializer, and resource routes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; rails g resource favorite_item user:belongs_to item:belongs_to

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

&lt;/div&gt;



&lt;p&gt;Then, add has_many associations to both item and user models. Since the belongs_to association is already specified, it will be provided by rails in the favorite_item model. Then, add validations to assure that an item is only favored one time by the same user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class User &amp;lt; ApplicationRecord
 has_many :favorite_items, dependent: :destroy
 has_many :items, through: :favorite_items
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Item &amp;lt; ApplicationRecord
  has_many :favorite_items, dependent: :destroy
  has_many :favorited_by, through: :favorite_items, source: :user
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class FavoriteItem &amp;lt; ApplicationRecord
  belongs_to :user
  belongs_to :item

  validates :item_id, uniqueness: { scope: [:user_id], message: 'item is already favorited' }
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, update user and favorite_item serializers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class UserSerializer &amp;lt; ActiveModel::Serializer
  has_many :favorite_items
  has_many :items
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the favorite_item serializer, add &lt;code&gt;:item_id&lt;/code&gt; attribute. This will identify which item is favored by the user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class FavoriteItemSerializer &amp;lt; ActiveModel::Serializer
  attributes :id, :item_id
  has_one :user
  has_one :item
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Add Methods to Controller
&lt;/h2&gt;

&lt;p&gt;Add create and destroy actions to the favorite_item controller:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class FavoriteItemsController &amp;lt; ApplicationController
    def create 
       favorite_item = current_user.favorite_items.create(favorite_item_params)
        if favorite_item.valid?
            render json: favorite_item.item, status: :created
        else
            render json: favorite_item.errors, status: :unprocessable_entity
        end
    end



    def destroy 
        render json: FavoriteItem.find_by(item_id: Item.find(params[:id]).id, user_id: current_user.id).destroy
    end

    private

    def favorite_item_params
        params.require(:favorite).permit(:item_id, :user_id)
    end


end

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

&lt;/div&gt;



&lt;p&gt;Also, make sure to specify routes in the &lt;code&gt;routes.rb&lt;/code&gt; file as such: &lt;code&gt;resources :favorite_items, only: [:create, :destroy]&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Frontend React Side - Add Favorite
&lt;/h2&gt;

&lt;p&gt;The favoriting icon is showing when the user is viewing item details:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kU-c4FvY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ct66ohb5a2hf14i9txuh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kU-c4FvY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ct66ohb5a2hf14i9txuh.png" alt="heart icon is showing under image" width="880" height="1348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the selected item component, add the heart icon:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div &amp;gt;
 &amp;lt;Icon onClick={() =&amp;gt; addFavorite(selectedItem) } 
 color="red" name="heart outline" /&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;addFavorite(selectedItem)&lt;/code&gt; is a callback function defined at the highest level &lt;code&gt;App.jsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const addFavorite = (item) =&amp;gt; {
    const newFavorite = {
      favorite: {
        item_id: item.id, user_id: currentUser.id
      }
    }
    fetch("/favorite_items", { 
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(newFavorite),
    })
    .then(resp =&amp;gt; {
      if (resp.ok) {
        return resp.json()
      } else {
        return resp.json().then(errors =&amp;gt; Promise.reject(errors))
      }
    })
    .then((newFav) =&amp;gt; {
      setFavorites([...favorites, newFav])
      navigate("/items")
     })
  }

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

&lt;/div&gt;



&lt;p&gt;When you click on the heart icon, you will be redirected back to the main list of items for sale. The favored item/s can be viewed via the favorites button in the navigation bar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YR5K6iCI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bjgx8jn2fhjbetopksk2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YR5K6iCI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bjgx8jn2fhjbetopksk2.png" alt="list of favored items" width="880" height="765"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Frontend React Side - Remove Favorite
&lt;/h2&gt;

&lt;p&gt;Create the favorite items' container and reuse &lt;code&gt;ItemCard&lt;/code&gt; component when you map through favorite items:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react'
import ItemCard from '../components/ItemCard'
import { Container, Card } from 'semantic-ui-react'

const Favorites = ({ favorites, removeFavorite }) =&amp;gt; {

  return (
    &amp;lt;Container textAlign="center"&amp;gt;
      {favorites.length === 0 ? &amp;lt;h2 style={{ paddingTop: '50px' }}&amp;gt;You have no favorites!&amp;lt;/h2&amp;gt; :
      &amp;lt;&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;h1&amp;gt;The items you liked!&amp;lt;/h1&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div className="ui divider"&amp;gt;
        &amp;lt;Card.Group itemsPerRow={3}&amp;gt; 
          {favorites.map((item) =&amp;gt; (

            &amp;lt;ItemCard 
             key={item.id}
             item={item}
             removeFavorite={removeFavorite}
             redHeart={true}
            /&amp;gt;
          ))}

        &amp;lt;/Card.Group&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;/&amp;gt;
}
    &amp;lt;/Container&amp;gt;
  )
}

export default Favorite
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use props to display the red heart icon in &lt;code&gt;ItemCard&lt;/code&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react'
import { Card, Image, Icon } from 'semantic-ui-react'
import {useNavigate} from 'react-router-dom'
const ItemCard = ({ item, removeFavorite, redHeart }) =&amp;gt; {

  const navigate = useNavigate()

  const handleClick = () =&amp;gt; {
      navigate(`/items/${item.id}`)
  }

   return (
    &amp;lt;div className="item-card"&amp;gt;
        &amp;lt;Card color='blue' &amp;gt;

        &amp;lt;div onClick={handleClick} className="image" &amp;gt;
          &amp;lt;Image src={item.image} alt={item.name} wrapped /&amp;gt;     
         &amp;lt;/div&amp;gt;

           &amp;lt;Card.Content&amp;gt;
                &amp;lt;Card.Header&amp;gt;{item.name}&amp;lt;/Card.Header&amp;gt;
                &amp;lt;Card.Description&amp;gt;{item.price}&amp;lt;/Card.Description&amp;gt;

            &amp;lt;/Card.Content&amp;gt;
            &amp;lt;br /&amp;gt;
            {redHeart ? (
              &amp;lt;span onClick={() =&amp;gt; removeFavorite(item)}&amp;gt;
                &amp;lt;Icon color="red" name="heart" /&amp;gt;
              &amp;lt;/span&amp;gt;
            ) : null }
        &amp;lt;/Card&amp;gt;
    &amp;lt;/div&amp;gt;
  )
}

export default ItemCard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the user clicks the red heart icon, it will run the callback function &lt;code&gt;removeFavorite(item)&lt;/code&gt;. This function is defined in the highest level component &lt;code&gt;App.jsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const removeFavorite = (item) =&amp;gt; {
    const foundFavorite = favorites.find((fav) =&amp;gt; fav.id === item.id)

   return  fetch(`/favorite_items/${foundFavorite.id}`, {
      method: "DELETE"
    })
    .then(resp =&amp;gt; resp.json())
    .then(() =&amp;gt; {
      const filteredFavorites = favorites.filter((fav) =&amp;gt; fav.id !== foundFavorite.id)
        setFavorites(filteredFavorites)
    })
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 6: Update Login/Authentication State&lt;/p&gt;

&lt;p&gt;In this project, session cookies were used to log the user in. Therefore, you need to update the state when you sign up, log in, and refresh respectively:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function handleSubmit(e) {
    e.preventDefault();

    const userCreds = { ...formData }
    fetch("/signup", {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify(userCreds),
    })
    .then((resp) =&amp;gt; resp.json())
    .then((user) =&amp;gt; {
      console.log(user)
      setFormData({
        email: "",
        username: "",
        password: "",
        passwordConfirmation: ""
      })
      setCurrentUser(user)
      setAuthenticated(true)
      setFavorites(user.items)
      navigate("/items")
    })
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function handleSubmit(e) {
    e.preventDefault();

    const userCreds = { ...formData };

    fetch("/login", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(userCreds),
    })
      .then((r) =&amp;gt; r.json())
      .then((user) =&amp;gt; {
         setCurrentUser(user)
          setAuthenticated(true)
          setFavorites(user.items)
        setFormData({
          username: "",
          password: "",
        });
        navigate("/items")
      });
  }

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
    fetch("/me", {
      credentials: "include",
    })
    .then((res) =&amp;gt; {
      if (res.ok) {
        res.json().then((user) =&amp;gt;{ 
          setCurrentUser(user)
          setAuthenticated(true)
          setFavorites(user.items)
        });
      } else {
        setAuthenticated(true)
      }
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This example concludes one of the possible ways to implement favoring an object from a list and displaying a new list of favorite objects using rails join table associations.&lt;/p&gt;

</description>
      <category>react</category>
      <category>programming</category>
      <category>javascript</category>
      <category>rails</category>
    </item>
    <item>
      <title>Ruby Fundamentals, Compare and Contrast with Javascript</title>
      <dc:creator>Nissrine Canina</dc:creator>
      <pubDate>Thu, 10 Feb 2022 11:51:53 +0000</pubDate>
      <link>https://dev.to/nissrinecan/ruby-fundamentals-compare-and-contrast-with-javascript-3lfh</link>
      <guid>https://dev.to/nissrinecan/ruby-fundamentals-compare-and-contrast-with-javascript-3lfh</guid>
      <description>&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%2Fmhma51jjhrf7tos13ucu.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%2Fmhma51jjhrf7tos13ucu.png" alt="The picture is showing a ruby gem for Ruby and JS logo for Javascript"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Learning Ruby Coming from Javascript
&lt;/h1&gt;

&lt;p&gt;Novice programmers often get intimidated by the idea of learning a new language. That is where the idea of this blog comes from. As a student in the Flatiron School, I spent my first half of the program learning Javascript and its framework React (the front-end side). When the time comes to switch gears, Ruby comes into play to code the back-end side of our programs. It was natural to compare and contrast Ruby and Javascript along the way to understand their similarities and differences. The purpose of this blog is to help anyone, new to Ruby, learn its basic concepts and fundamentals. &lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction to Ruby
&lt;/h1&gt;

&lt;p&gt;It is important to note that Ruby is primarily an Object Oriented Language (OOP) whereas Javascript is not strictly OOP; however, Javascript provides features such as classes and objects which are inspired by OOP. So, what is OOP? OOP is a type of programming based on the concept of "objects" which can contain data in the form of fields (often known as attributes or properties), and code in the form of procedures (often known as methods).OOP is about structuring code so that its functionality can be shared throughout the application program. On the other hand, Javascript is procedural programming language by nature where programs are built in sequential order and functions are called to share their behavior. Javascript can be an OOP language but it was not originally designed as an OOP language. The OOP syntactic sugar was added later on. Understanding this concept will explain the key differences between Ruby and Javascript syntax.&lt;/p&gt;

&lt;h1&gt;
  
  
  Language Purpose
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Javascript
&lt;/h3&gt;

&lt;p&gt;build client-side applications that run in the browser.&lt;br&gt;
Work in the browser environment/sandbox where we can access:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make network requests&lt;/li&gt;
&lt;li&gt;Update the DOM&lt;/li&gt;
&lt;li&gt;Listen for events&lt;/li&gt;
&lt;li&gt;Debug our code in the browser's developer tools&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Ruby
&lt;/h3&gt;

&lt;p&gt;build server-side applications.&lt;br&gt;
take advantage from our computer system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read and write files&lt;/li&gt;
&lt;li&gt;Listen for network requests and send responses&lt;/li&gt;
&lt;li&gt;Connect to a database to access and update data
we can build all kinds of apps not just web apps
Command line interfaces
Web servers
Games
Web scrapers&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  Terminal Output Methods
&lt;/h1&gt;

&lt;p&gt;One of the main differences between Javascript and Ruby is that Ruby code run from the terminal using the Ruby interpreter whereas Javascript run code in the browser.&lt;/p&gt;

&lt;p&gt;The command &lt;code&gt;ruby -v&lt;/code&gt; is used to check which Ruby version is used in the system.&lt;/p&gt;

&lt;p&gt;To run Ruby application use the command &lt;code&gt;ruby some_file.rb&lt;/code&gt;, where &lt;code&gt;some_file&lt;/code&gt; is the name of the file where Ruby code is written.&lt;/p&gt;

&lt;p&gt;Any code written in &lt;code&gt;some_file.rb&lt;/code&gt; can be outputted to the terminal using Ruby's various methods for printing output: &lt;code&gt;puts&lt;/code&gt;, &lt;code&gt;print&lt;/code&gt;, &lt;code&gt;p&lt;/code&gt;, and &lt;code&gt;pp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;puts&lt;/code&gt; and &lt;code&gt;print&lt;/code&gt; are both used to print &lt;em&gt;strings&lt;/em&gt; to the terminal with a difference of a line break added at the end of each string when &lt;code&gt;puts&lt;/code&gt; is used.&lt;/p&gt;

&lt;p&gt;If we run this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;puts "I am learning Ruby!"
puts "I am learning Ruby!"
puts "I am learning Ruby!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will receive this output in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I am learning Ruby!
I am learning Ruby!
I am learning Ruby!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we run the same code using &lt;code&gt;print&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;print "I am learning Ruby!"
print "I am learning Ruby!"
print "I am learning Ruby!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will receive an output without a line break:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I am learning Ruby!I am learning Ruby!I am learning Ruby!%  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To inspect a non string data, &lt;code&gt;p&lt;/code&gt; would be a better choice compare to &lt;code&gt;puts&lt;/code&gt; because the latter one attempts to convert everything to a string by calling the &lt;code&gt;.to_s&lt;/code&gt; method. On the other hand, &lt;code&gt;p&lt;/code&gt; calls the &lt;code&gt;.inspect&lt;/code&gt; method which will present data in a nicer format.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;puts [1, 2, 3, 4]
1
2
3
4
 =&amp;gt; nil 

#`puts` will convert `nil` to an empty string

puts [1, 2, nil, nil, nil, 6]
1
2



6
 =&amp;gt; nil 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;p&lt;/code&gt; will return a raw version of an object (i.e including quotes and new line characters). &lt;code&gt;puts&lt;/code&gt; will always return &lt;code&gt;nil&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;p "Hello World!"
"Hello World!"
 =&amp;gt; "Hello World!" 

p "Hello World!\n"
"Hello World!\n"
 =&amp;gt; "Hello World!\n" 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;p&lt;/code&gt; is more useful for debugging purposes whereas &lt;code&gt;puts&lt;/code&gt; is useful for display to the user.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pp&lt;/code&gt; is used for printing nested and complicated arrays and hashes. &lt;code&gt;pp&lt;/code&gt; calls the &lt;code&gt;.pretty_inspect&lt;/code&gt; method to print the data in an organized and easy to read fashion.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[{:id=&amp;gt;1, :color=&amp;gt;"blue"},
 {:id=&amp;gt;2, :color=&amp;gt;"red"},
 {:id=&amp;gt;3, :color=&amp;gt;"yellow"}]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Javascript, &lt;code&gt;console.log&lt;/code&gt; would have the equivalent function to &lt;code&gt;puts&lt;/code&gt; in Ruby.&lt;/p&gt;

&lt;h1&gt;
  
  
  Data Types in Ruby
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Strings
&lt;/h2&gt;

&lt;p&gt;Strings in Ruby can be defined with single or double quotes similarly to Javascript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   "I am a string!"
   'I am also a string!!'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since Ruby is an OOP language, we can call several methods on string literals (i.e. &lt;code&gt;"hello"&lt;/code&gt;). Each string in ruby is actually an instance of the class &lt;code&gt;String&lt;/code&gt;. Therefore, class methods are available to its instances. We can check look up these methods via &lt;code&gt;"example".methods&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"hello".upcase
# =&amp;gt; "HELLO"
"hello".capitalize
# =&amp;gt; "Hello"
"hello".reverse
# =&amp;gt; "olleh"

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  String Interpolation
&lt;/h4&gt;

&lt;p&gt;String interpolation exists in both Ruby and Javascript; however, backticks have a different purpose in Ruby:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Ruby (comment in Ruby)
name = "Joe"
puts "Hello #{name}"

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// JavaScript (Comment in Javascript)
const name = "Joe";
console.log(`Hello ${dogName}`);

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Numbers
&lt;/h2&gt;

&lt;p&gt;There are two types of numbers in Ruby: integers as whole numbers and floats as decimal numbers. Ruby provides several methods to work on both types of numbers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; 2.3.floor
 =&amp;gt; 2
&amp;gt; 8.5.ceil
 =&amp;gt; 9

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

&lt;/div&gt;



&lt;p&gt;Also, we can convert strings to numbers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; "2.5".to_i
 =&amp;gt; 2 
&amp;gt; "2".to_i
 =&amp;gt; 2 
&amp;gt; "2".to_f
 =&amp;gt; 2.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unlike Javascript, Ruby will not convert an integer to a float during the process of arithmetic operations unless one of the sides is a float:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; 5/4
 =&amp;gt; 1 
&amp;gt; 5/4.to_f
 =&amp;gt; 1.25 
&amp;gt; 5/4.0
 =&amp;gt; 1.25 

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Nil
&lt;/h2&gt;

&lt;p&gt;In Ruby, there is only one case of absence of value which is represented by &lt;code&gt;nil&lt;/code&gt;. For example, &lt;code&gt;puts&lt;/code&gt; will always return &lt;code&gt;nil&lt;/code&gt;. On the other hand, Javascript has two different datatypes that represent the absence of a value &lt;code&gt;null&lt;/code&gt; and &lt;code&gt;undefined&lt;/code&gt;. The latter one is commonly seen when we create a variable and we do not assign a value to it. Ruby will not allow the creation of a variable without assigning a value to it. If we intent to create a variable and not assign it a value, we must explicitly assign &lt;code&gt;nil&lt;/code&gt; to declare an empty value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; puts "Return something"
 # Return something
 # =&amp;gt; nil
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; &amp;gt; name
 NameError (undefined local variable or method `name' for main:Object)

&amp;gt; name = nil
 =&amp;gt; nil 
&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; let someValue;
console.log(someValue);
// =&amp;gt; undefined
someValue = null;
console.log(someValue);
// =&amp;gt; null
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Booleans
&lt;/h2&gt;

&lt;p&gt;Booleans have two values: &lt;code&gt;true&lt;/code&gt; and &lt;code&gt;false&lt;/code&gt; like in Javascript. In Ruby, however, &lt;code&gt;true&lt;/code&gt; is an instance of &lt;code&gt;TrueClass&lt;/code&gt; and &lt;code&gt;false&lt;/code&gt; is an instance of &lt;code&gt;FalseClass&lt;/code&gt;.&lt;br&gt;
Additionally, only &lt;code&gt;nil&lt;/code&gt; and &lt;code&gt;false&lt;/code&gt; are falsy values. Everything else is truthy including &lt;code&gt;0&lt;/code&gt; and empty string&lt;code&gt;""&lt;/code&gt;. On the other hand, in Javascript, &lt;code&gt;null&lt;/code&gt;, &lt;code&gt;undefined&lt;/code&gt;, &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;false&lt;/code&gt;, &lt;code&gt;""&lt;/code&gt;, and &lt;code&gt;NaN&lt;/code&gt; are falsy values.&lt;/p&gt;
&lt;h2&gt;
  
  
  Symbols
&lt;/h2&gt;

&lt;p&gt;The symbol data type (&lt;code&gt;:symbol_example&lt;/code&gt;) exists in both Ruby and Javascript yet the use of symbols is more common in Ruby where symbols are used as keys on a hash (a hash is equivalent to an object in Javascript). While a symbol is a representation of data similar to a string, Ruby allocates the same space in memory for symbols versus a string which is allocated a different space in memory each time it is called:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; &amp;gt; :some_symbol.object_id
 =&amp;gt; 2077788 
 &amp;gt; :some_symbol.object_id
 =&amp;gt; 2077788 
 &amp;gt; "a string".object_id
 =&amp;gt; 260 
 &amp;gt; "a string".object_id
 =&amp;gt; 280 
 &amp;gt; 

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Arrays
&lt;/h2&gt;

&lt;p&gt;Arrays have similar functionality in both Ruby and Javascript. They can be created using literal or class constructors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; &amp;gt; [3, 6, 9]
 =&amp;gt; [3, 6, 9] 

 &amp;gt; Array.new
 =&amp;gt; [] 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Ruby documentation &lt;a href=""&gt;https://www.ruby-lang.org/en/documentation/&lt;/a&gt; provides a comprehensive list of methods to perform CRUD actions (create, read, update, delete) in addition to operating on arrays as well as elements within an array. Some of these methods can work for both Ruby and Javascript arrays, some methods in Javascript have equivalents methods in Ruby, and some others are exclusive to Ruby.&lt;br&gt;
Similarly to Javascript, we can check elements in an array by index in Ruby:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; #Ruby
 &amp;gt; my_array = [3, 6, 9, 12, 15]
 =&amp;gt; [3, 6, 9, 12, 15] 
 &amp;gt; my_array[0]
 =&amp;gt; 3 
 &amp;gt; my_array[-1]
 =&amp;gt; 15  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ruby has a wide selection of enumerable methods that allows us to traverse, search, and sort through arrays. Some enumerables are used interchangeably in Ruby as well as in Javascript to loop over elements of an array. Some examples consist of but not limited to &lt;code&gt;.map&lt;/code&gt;, &lt;code&gt;.filter&lt;/code&gt;. &lt;code&gt;.each&lt;/code&gt;, and &lt;code&gt;.find&lt;/code&gt;. Ruby has a version of &lt;code&gt;.map&lt;/code&gt; called &lt;code&gt;.collect&lt;/code&gt; and &lt;code&gt;.select&lt;/code&gt; which is equivalent to &lt;code&gt;.filter&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ruby has convenient methods to check first and last elements on a given array: &lt;code&gt;Array.first&lt;/code&gt; and &lt;code&gt;Array.last&lt;/code&gt; respectively compare to Javascript. For instance, to check the last element on an array with an unknown size we use: &lt;code&gt;Array[Array.length-1]&lt;/code&gt;. And, to check the the length of an array in Ruby we use &lt;code&gt;Array.size&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To extract a range of element from an array in Javascript, we can use the slice method. The slice method does not mutate the original array and it stops extracting elements before the last designated index. For instance: &lt;code&gt;slice(1,3)&lt;/code&gt; will extract the element with index 1 &lt;code&gt;[1]&lt;/code&gt; and exclude the element with index 3 &lt;code&gt;[3]&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; //Javascript
 someArray = [1, 2, 3, 4, 5, 6]
 (6) [1, 2, 3, 4, 5, 6]
 someArray.slice(1,3)
 (2) [2, 3]
 someArray
 (6) [1, 2, 3, 4, 5, 6]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Ruby, we can extract a range of elements from an array using &lt;code&gt;[0..2]&lt;/code&gt; which will return all the elements between index 0 and index 2 including the last one. But if we want to exclude last element we use the three dots method: &lt;code&gt;[0...2]&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; :006 &amp;gt; my_array = [3, 6, 9, 12, 15]
 =&amp;gt; [3, 6, 9, 12, 15] 
 &amp;gt; my_array[0..1]
 =&amp;gt; [3, 6] 
 &amp;gt; my_array[0...2]
 =&amp;gt; [3, 6] 
 &amp;gt; my_array[0..2]
 =&amp;gt; [3, 6, 9] 
 &amp;gt; my_array[0...2]
 =&amp;gt; [3, 6] 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To add an element to the end of an array in Javascript we use &lt;code&gt;push&lt;/code&gt; method whereas the shovel &lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt; method is more commonly used in Ruby:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; //Javascript
 someArray
 (6) [1, 2, 3, 4, 5, 6]
 someArray.push(9)
 7
 someArray
 (7) [1, 2, 3, 4, 5, 6, 9]

#Ruby
 011 &amp;gt; my_array = [3, 6, 9, 12, 15]
 =&amp;gt; [3, 6, 9, 12, 15] 
 2.7.4 :012 &amp;gt; my_array &amp;lt;&amp;lt; 10
 =&amp;gt; [3, 6, 9, 12, 15, 10] 
 2.7.4 :013 &amp;gt; 

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

&lt;/div&gt;



&lt;p&gt;Both languages have the ability to concatenate arrays, meaning combining multiple arrays, using &lt;code&gt;concat()&lt;/code&gt; method. In Ruby, we can combine arrays using &lt;code&gt;+&lt;/code&gt; as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//Javascript
 a = [1, 2, 3, 4]
 (4) [1, 2, 3, 4]
 b = [3, 6, 9]
 (3) [3, 6, 9]
 a + b 
 '1,2,3,43,6,9'
 a.concat(b)
 (7) [1, 2, 3, 4, 3, 6, 9]

#Ruby
 &amp;gt; a= [1, 2, 3, 4 , nil] 
 =&amp;gt; [1, 2, 3, 4, nil] 
 &amp;gt; b= [6, 7, 8, 9]
 =&amp;gt; [6, 7, 8, 9] 
 &amp;gt; a.concat(b)
 =&amp;gt; [1, 2, 3, 4, nil, 6, 7, 8, 9] 

 &amp;gt;a= [1, 2, 3, 4 , nil] 
 =&amp;gt; [1, 2, 3, 4, nil] 
 &amp;gt; b= [6, 7, 8, 9]
 =&amp;gt; [6, 7, 8, 9] 
 &amp;gt; a + b
 =&amp;gt; [1, 2, 3, 4, nil, 6, 7, 8, 9] 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To remove first and last elements from an array, both Ruby and Javascript use &lt;code&gt;shift&lt;/code&gt; and &lt;code&gt;pop&lt;/code&gt; respectively.&lt;/p&gt;

&lt;p&gt;In Ruby, there are some methods that has either a question or an exclamation mark (i.e. &lt;code&gt;include?&lt;/code&gt; and &lt;code&gt;reverse!&lt;/code&gt;). if a method includes a question mark, this means that the return will be a boolean value (&lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;). Any method with exclamation mark will change the original array. We can keep original array by omitting the exclamation point:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; #Ruby
 &amp;gt; a = [1, 2, 3, 4]
 =&amp;gt; [1, 2, 3, 4] 
 &amp;gt; a.reverse
 =&amp;gt; [4, 3, 2, 1] 
 &amp;gt; a
 =&amp;gt; [1, 2, 3, 4] 
 &amp;gt; a.reverse!
 =&amp;gt; [4, 3, 2, 1] 
 &amp;gt; a
 =&amp;gt; [4, 3, 2, 1] 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is also worth mentioning that some methods are simpler to use in Ruby compare to Javascript. For example, to add all elements in a given array we simply use &lt;code&gt;.sum&lt;/code&gt; whereas in Javascript we use the reduce method: &lt;code&gt;Array.reduce((sum, num) =&amp;gt; sum + num)&lt;/code&gt;. Another example of a simple method in Ruby is the &lt;code&gt;.uniq&lt;/code&gt; method which returns one version of each element in an array: &lt;code&gt;[1, 1, 2, 3].uniq =&amp;gt; [1, 2, 3]&lt;/code&gt;. To achieve the same results in Javascript, we use the filter method &lt;code&gt;array.filter((num, index, array) =&amp;gt; array.indexOf(num)===index)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In Ruby, we can create arrays of strings and symbols as such:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; #Ruby
  %w[word word]
 =&amp;gt; ["word", "word"] 
 &amp;gt; %i[word word]
 =&amp;gt; [:word, :word] 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Hashes
&lt;/h2&gt;

&lt;p&gt;Hashes in Ruby can be compared to a plain old Javascript object. However, the term object is used in Ruby to indicate an instance of a class. Hashes are composed of key/value pairs where each key points to a value: &lt;code&gt;{ key1: "value1", key2: "value2" }&lt;/code&gt;.&lt;br&gt;
Unlike Javascript, we cannot use use dot notation to access values within a hash, only bracket notation is valid with hashes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; some_hash = { key1: "value1", key2: "value2" }
 some_hash[:key2]
 # =&amp;gt; "value2"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also create hashes with strings instead of keys: &lt;code&gt;{ "string1" =&amp;gt; "value1", "string2" =&amp;gt; "value2" }&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A hash can be converted to an array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; &amp;gt; some_hash = { key1: "value1", key2: "value2" }
 =&amp;gt; {:key1=&amp;gt;"value1", :key2=&amp;gt;"value2"} 
 &amp;gt; some_hash.to_a
 =&amp;gt; [[:key1, "value1"], [:key2, "value2"]] 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are several methods that are available to the Hash class similarly to the Array class. The Ruby documentation &lt;a href=""&gt;https://www.ruby-lang.org/en/documentation/&lt;/a&gt; provides a list of method for every class.&lt;/p&gt;

&lt;h2&gt;
  
  
  Methods
&lt;/h2&gt;

&lt;p&gt;A method in Ruby is the equivalent of a function in Javascript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; //Javascript
 function someFunction(parameter) {
  console.log("Running someFunction");
  return parameter + 1;
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; #Ruby
 def some_method(parameter)
  puts "Running some_method"
  parameter + 1
 end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here are the key differences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;def&lt;/code&gt; keyword defines a method in Ruby just as &lt;code&gt;function&lt;/code&gt; in Javascript.&lt;/li&gt;
&lt;li&gt;By convention, the name of the method &lt;code&gt;some_method&lt;/code&gt; is in snake case whereas the name of the function in Javascript is in camel case &lt;code&gt;someFunction&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Parameters are defined in parentheses in both languages but we can omit the parentheses if the method has no parameter.&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;end&lt;/code&gt; keyword defines the method's body just as the curly parentheses do in Javascript.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;puts&lt;/code&gt; is equivalent to &lt;code&gt;console.log&lt;/code&gt;. It will output to the terminal but has a &lt;code&gt;nil&lt;/code&gt; return value. &lt;/li&gt;
&lt;li&gt;The return value in a Ruby method will be always the last line in the method's body. The &lt;code&gt;return&lt;/code&gt; keyword can be omitted and the method will implicitly return the last line.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Method Scope
&lt;/h2&gt;

&lt;p&gt;In Javascript, functions have access to variables defined in their parent scope whether the parent scope consists of another function or the global scope. In Ruby scope functions differently. Any variable defined outside of the &lt;code&gt;def&lt;/code&gt; and &lt;code&gt;end&lt;/code&gt; keywords is unreachable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; guest_name = "Joe"

 def say_hello_to_guest
  puts "Hello #{guest_name}!"
 end
 =&amp;gt; NameError (undefined local variable or method `guest_name' 
 for main:Object)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Calling the &lt;code&gt;guest_name&lt;/code&gt; variable from inside the method will throw an undefined local variable error. To solve the issue of an out of scope variable, we have to pass is as an argument:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; guest_name = "Joe"

 def say_hello_to_guest
  puts "Hello #{guest_name}!"
 end
 say_hello_to_guest(guest_name)
#=&amp;gt; "Hello Joe!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Variables
&lt;/h2&gt;

&lt;p&gt;In Javascript, declaring a variable require either &lt;code&gt;let&lt;/code&gt; or &lt;code&gt;const&lt;/code&gt; keywords preceding the variable name. A &lt;code&gt;let&lt;/code&gt; variable can be declared first before assigning a value to it whereas a &lt;code&gt;const&lt;/code&gt; variable hoists the declaration and the assignment at the same time. We cannot declare a &lt;code&gt;const&lt;/code&gt; without assigning a value to it. In Ruby, due to scoping issues as well as the concept of Object Oriented Programming, variables are treated differently.&lt;/p&gt;

&lt;p&gt;Variables in Ruby:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Local variables: start with a lower case or  an underscore(_), should snake case if more than one word is used to name the variable (i.e. name = "Sarah", pet_name = "Pup").&lt;/li&gt;
&lt;li&gt;Global variables: start with a dollar sign ($) and are available in the global scope. They are rarely used because of debugging issues:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; &amp;gt; $guest_name = "Joe"
 =&amp;gt; "Joe" 
 &amp;gt; def say_hello_to_guest
 &amp;gt;   puts "Hello #{$guest_name}!"
 &amp;gt; end
 =&amp;gt; :say_hello_to_guest 
 &amp;gt; say_hello_to_guest
 Hello Joe!
 =&amp;gt; nil 

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Instance variables: start with an at symbol (@) (i.e. &lt;a class="mentioned-user" href="https://dev.to/name"&gt;@name&lt;/a&gt; = "Sarah").&lt;/li&gt;
&lt;li&gt;class variables: start with double at symbol (i.e. @&lt;a class="mentioned-user" href="https://dev.to/name"&gt;@name&lt;/a&gt; = "Sarah").
Both instance and class variables are seen within the topic of Object Oriented Programming.&lt;/li&gt;
&lt;li&gt;Constant: holds data that does not change. Must be in all caps (i.e. NAME = "Sarah"). It is equivalent to &lt;code&gt;const&lt;/code&gt; in Javascript. Scope wise, a constant can also be accessed from outside of the class using: &lt;code&gt;book::GENRES&lt;/code&gt;. Unlike Javascript declaring a variable with a constant in Ruby does not prevent the variable from being reassigned though it will give a warning.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Debugging in Ruby
&lt;/h2&gt;

&lt;p&gt;Ruby comes with its own REPLs (Read, Evaluate, Print, Loop) when installed. The first REPL is IRB (Interactive Ruby) which is similar to  the browser's console in Javascript. IRB allows you to experiment some procedural programming. It is a completely new environment, separate from our code, where we have to copy and paste the blocks of code we want to test. The second REPL is &lt;code&gt;'Pry&lt;/code&gt; which offers more functionality than the previous one because it injects an interactive environment into our code. &lt;code&gt;Pry&lt;/code&gt; allows more flexibility in testing our code, we just have to add &lt;code&gt;binding.pry&lt;/code&gt; anywhere in our code similar to &lt;code&gt;debugger&lt;/code&gt; in Javascript. &lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Learning the syntax is the first step to learn a new language. It is also crucial to understand the concept the language is built around as well as its history &lt;a href="https://dev.tourl"&gt;https://www.ruby-lang.org/en/documentation/ruby-from-other-languages/&lt;/a&gt;. After mastering Ruby fundamentals, the next step is to learn about Macros(getters and setters methods), initialize method, public vs private methods, self, class variables and methods, instance variables and methods, and class inheritance.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>javascript</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>useEffect Hook</title>
      <dc:creator>Nissrine Canina</dc:creator>
      <pubDate>Wed, 24 Nov 2021 21:43:13 +0000</pubDate>
      <link>https://dev.to/nissrinecan/useeffect-hook-1i2k</link>
      <guid>https://dev.to/nissrinecan/useeffect-hook-1i2k</guid>
      <description>&lt;h2&gt;
  
  
  Definition
&lt;/h2&gt;

&lt;p&gt;The useEffect hook is used to handle the side effect of React functional components outside of returning JSX. For instance, fetch data from an API when a component loads. Another example consists of starting or stopping a timer. Also, the useEffect allows to make manual changes to the DOM.&lt;/p&gt;

&lt;p&gt;Any code defined inside the useEffect hook will run after React components finished the DOM updates. By default, useEffect runs both after the first render as well as whenever the component's state updates.&lt;/p&gt;

&lt;h2&gt;
  
  
  useEffect Dependencies Array
&lt;/h2&gt;

&lt;p&gt;The default behavior of useEffect does not always agree with the purpose of our code. To adjust this behavior, we can run useEffect hook functions conditionally using dependencies array. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Empty array of dependencies[]:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;for Example, we only need to run a fetch call to an API once after the JSX has completely loaded. Adding an empty dependencies array as a second argument to the useEffect function will stop the fetch call to API from happening with every re-render of the components. Therefore, the fetch call will only occur when the component renders for the first time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dependencies array with one or more elements [element1, element2,..]:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using the example of an incrementing counter running as a side effect. We can add the counter variable to the dependencies array. Therefore, the useEffect will run every time our counter state changes.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Using useEffect with no dependencies array means that the side effect will run every time the component renders and whenever state or props change.&lt;/li&gt;
&lt;li&gt;Using useEffect with an empty dependencies array means the side effect will only run the first time the component renders. No state is involved in this case.&lt;/li&gt;
&lt;li&gt;Using useEffect with dependencies with elements in it means that the side effect will run every time those elements/variables change. The side effect will be triggered by the state changes of the elements inside the dependencies array.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>react</category>
    </item>
    <item>
      <title>Client-Side Routing in React</title>
      <dc:creator>Nissrine Canina</dc:creator>
      <pubDate>Tue, 23 Nov 2021 02:56:33 +0000</pubDate>
      <link>https://dev.to/nissrinecan/client-side-routing-in-react-4c1o</link>
      <guid>https://dev.to/nissrinecan/client-side-routing-in-react-4c1o</guid>
      <description>&lt;h4&gt;
  
  
  Introduction
&lt;/h4&gt;

&lt;p&gt;On this blog post, I would like to share a general overview of the concept of client-side routing that I have learned through the React phase. It was very helpful to use React tools in one project to understand the hierarchy of the components as well as nested children.&lt;/p&gt;

&lt;h4&gt;
  
  
  Definition
&lt;/h4&gt;

&lt;p&gt;Client-side routing comes into place when building a single-page-application to separate its components onto different pages based on the endpoint of the URL of each page. The client-side routing is the internal handling of a route inside the Javascript file that is rendered to the client; without making additional Get requests for new HTML documents other than the initial and only Get request. &lt;/p&gt;

&lt;h4&gt;
  
  
  Pro
&lt;/h4&gt;

&lt;p&gt;The major benefit of client-side routing is speed. Since the client-side code is responsible for routing, fetching, and displaying data in the browser, the client side router swaps the components in response to the user clicks. &lt;/p&gt;

&lt;h4&gt;
  
  
  Limitations
&lt;/h4&gt;

&lt;p&gt;The limitations of client-side routing consist of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It takes a while to load all the CSS and Javascript on the initial GET especially if the application size is large.&lt;/li&gt;
&lt;li&gt;It is hard to track page views via analytic tools. &lt;/li&gt;
&lt;li&gt;Single-page applications are complicated design wise compare to multi-page applications.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  React Router
&lt;/h4&gt;

&lt;p&gt;React Router is the client-side library that enables two major features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Conditional rendering of components based on the endpoint of the URL.&lt;/li&gt;
&lt;li&gt;Programmatic navigation that updates the content of the page without making new GET requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  React Router Code for Main Routes
&lt;/h2&gt;

&lt;p&gt;The first step to start using React Router is to install react-router-dom in the terminal: &amp;lt;$npm install react-router-dom&amp;gt;.Then, import Browser Router from react-router-dom in index.js file:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aql_VWpv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qdq3reyjuwlktjho8gas.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aql_VWpv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qdq3reyjuwlktjho8gas.png" alt="import Browser Router from react-router-dom in index.js file" width="880" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, import Route from react-router-dom in the parent component "App":&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wNelABzR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oyf3348ruj0vs3ljltqu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wNelABzR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oyf3348ruj0vs3ljltqu.png" alt='import Route from react-router-dom in the parent component "App"' width="880" height="185"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We use a Switch component to give the routes more predictive behavior. The Switch component is also imported from react-router-dom:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MVo04ErK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a1r32h7ds2r0ecurvkgn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MVo04ErK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a1r32h7ds2r0ecurvkgn.png" alt="import Switch from react-router-dom" width="880" height="173"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VzLohb4H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4beuz9vjgx2l1u1zef29.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VzLohb4H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4beuz9vjgx2l1u1zef29.png" alt="wrap Routes with Switch components" width="880" height="1028"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we define our routes, we can manipulate them via the address bar; but there are more efficient ways to achieve that via other tools such as Link and NavLink provided by the React Library.&lt;/p&gt;

&lt;h4&gt;
  
  
  NavLink
&lt;/h4&gt;

&lt;p&gt;The NavLink renders an anchor tag &amp;lt; a &amp;gt; to the dom and is used as a navigation bar with built in and customizable styling. NavLink should be placed outside and above the switch component so it can be accessed and displayed in all the pages. An example of NavLink component:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IvDW9Ewj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/39g0emuh3um5l2a1n44r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IvDW9Ewj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/39g0emuh3um5l2a1n44r.png" alt="NavLink Navbar example" width="880" height="726"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Link
&lt;/h4&gt;

&lt;p&gt;Similarly to NavLink, Link also renders an anchor tag &amp;lt; a &amp;gt; to the dom. Link can be used within the application pages as buttons with links that takes you to specific routes. Example of Links:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dpTgT8Mu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ggokgcb75n97y24ar7cs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dpTgT8Mu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ggokgcb75n97y24ar7cs.png" alt="Example of Links with specific routes" width="880" height="74"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that routes are following RESTful conventions. &lt;/p&gt;

&lt;h2&gt;
  
  
  React Code for Nested Routes
&lt;/h2&gt;

&lt;h4&gt;
  
  
  useParams Hook
&lt;/h4&gt;

&lt;p&gt;React modular applications are perfect tool for displaying lists of items. Going back to the example of list of cars (see code snippets above), the user should be able to click a car card and be directed to car details. Since, we are fetching the data using a db-json server and each car in the list has its own unique id, we can use useParams() method to get dynamic params from the URLs and therefore display the correct item.&lt;br&gt;
First, we have to import useParams() method from react-router-dom. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5L74g9GR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/knvscqyezqhmx7g8zkfe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5L74g9GR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/knvscqyezqhmx7g8zkfe.png" alt="import useParams from react-router-dom" width="880" height="69"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we have to assign the useParams() method to a variable inside our ItemDetails (i.e. CarDetails) component.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zpqj6fsu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z8xbtv5qpfjjng6zw4hf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zpqj6fsu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z8xbtv5qpfjjng6zw4hf.png" alt="assign useParams to a variable" width="594" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The id variable can be used then to fetch that specific item:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YNbY_O-I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ya7yg9fqdhfqn08fggas.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YNbY_O-I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ya7yg9fqdhfqn08fggas.png" alt="fetch specific id using useParams variable" width="878" height="702"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Programmatic Navigation
&lt;/h2&gt;

&lt;p&gt;The purpose of programmatic navigation is to direct the user to different pages without the need to click on a link. For instance, when the user submit a form (a new item) and need to be directed to the list of items to see the newly created item displayed in the original list. Another example is when we perform a delete action and we need to direct the user back to the main list. One way to achieve that is via useHistory Hook. &lt;/p&gt;

&lt;h4&gt;
  
  
  useHisory Hook
&lt;/h4&gt;

&lt;p&gt;Fisrt, we import the useHistory Hook from react-router-dom.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IqMvTt9Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qf5p5w06qg2peukwgnbz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IqMvTt9Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qf5p5w06qg2peukwgnbz.png" alt="import useHistory hook from react-router-dom" width="880" height="58"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, assign it to a variable:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Dqcql6Cl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gp92gzn3j7ql20fvvqbp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Dqcql6Cl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gp92gzn3j7ql20fvvqbp.png" alt="assign a variable to useHisory hook" width="574" height="66"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is an example of Patch request of a form submit action where the user is directed to the main list after submitting the new item:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hDpcTWXz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/etfv2z6f94qk0lgkvhx7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hDpcTWXz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/etfv2z6f94qk0lgkvhx7.png" alt="patch request with useHisory hook" width="798" height="1048"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is another example of Delete request where the user will be directed to the main list of cars after deleting the a specific item (car):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IXhl00Aq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jqjojaz2b4qzvk8r6skg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IXhl00Aq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jqjojaz2b4qzvk8r6skg.png" alt="delete request with useHistory hook" width="880" height="688"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This was a general overview of the concept of client-side routing with some useful hooks from the react router library. &lt;/p&gt;

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