<?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: newAlicorn</title>
    <description>The latest articles on DEV Community by newAlicorn (@newalicorn0128).</description>
    <link>https://dev.to/newalicorn0128</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%2F600181%2F6eb55b75-3ffb-430d-9967-b8089ac50d4a.png</url>
      <title>DEV Community: newAlicorn</title>
      <link>https://dev.to/newalicorn0128</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/newalicorn0128"/>
    <language>en</language>
    <item>
      <title>Intro to Linked List</title>
      <dc:creator>newAlicorn</dc:creator>
      <pubDate>Wed, 06 Apr 2022 22:26:31 +0000</pubDate>
      <link>https://dev.to/newalicorn0128/intro-to-linked-list-5553</link>
      <guid>https://dev.to/newalicorn0128/intro-to-linked-list-5553</guid>
      <description>&lt;p&gt;&lt;strong&gt;1. What is a Node?&lt;/strong&gt;&lt;br&gt;
We can think of a node as a container for some data. It can be conceptually visualized as a circle that we can put some data inside. We can store any data type in a node. Each node has two attributes: value and next.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;tail&lt;/code&gt; - the very last node that has its next pointer pointing to nothing or has its next set to &lt;code&gt;null&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;head&lt;/code&gt; - the very first node. A head has a position of 0. As long as we know where the list starts, we can always traverse it to access all other nodes in the list by using the next property.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. What is a Linked List?&lt;/strong&gt;&lt;br&gt;
A linked list contains a bunch of nodes linked together. We can consider a linked list ordered data structure. The &lt;code&gt;head&lt;/code&gt; node denotes the start of the list.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Linked Lists &amp;amp; Arrays&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An array must be stored contiguously (right next to each other) in memory.&lt;/li&gt;
&lt;li&gt;An linked list does not require its nodes stored contiguously in memory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Linked List Traversal&lt;/strong&gt;&lt;br&gt;
If I want to traverse through a linked list and print out the value of every node, I would need to continually update a &lt;code&gt;current&lt;/code&gt; pointer. In the context of my function, the only important variable I am going to track is &lt;code&gt;current&lt;/code&gt;, which starts at the &lt;code&gt;head&lt;/code&gt; of my linked list.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Iterative Traversal
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const printLinkedList = (head) =&amp;gt; { 
  let current = head; 

  while (current !== null) { 
    console.log(current.val); 
    current = current.next; 
  }

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Recursive Traversal
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const printRecursive = (head) =&amp;gt; { 
  let current = head; 
  if (current === null) return;

  console.log(current.val);

  printRecursive(current.next);
} 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Building a CRUD SPA with Ruby on Rails and React</title>
      <dc:creator>newAlicorn</dc:creator>
      <pubDate>Sat, 22 Jan 2022 20:26:58 +0000</pubDate>
      <link>https://dev.to/newalicorn0128/building-a-crud-spa-with-ruby-on-rails-and-react-35ng</link>
      <guid>https://dev.to/newalicorn0128/building-a-crud-spa-with-ruby-on-rails-and-react-35ng</guid>
      <description>&lt;p&gt;For my React project, I built a simple CRUD SPA called the Eat Here React App. This App allows users to explore the most unusual restaurants around the world. Besides reading all restaurants, users can add new restaurants, or like and make reviews of any of them. Searching by name functionality is also implemented in the application. Here is the &lt;a href="https://youtu.be/gSNX57lDtQg"&gt;demo&lt;/a&gt; video.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a RESTful JSON API with Rails
&lt;/h2&gt;

&lt;p&gt;In this project, I continued utilizing the Ruby on Rails framework for my backend API construction. I had two related models set up: a restaurant model that &lt;code&gt;has_many&lt;/code&gt; reviews, a review that &lt;code&gt;belongs_to&lt;/code&gt; a restaurant. I also defined a couple of &lt;code&gt;before_validation&lt;/code&gt; methods for data validation. Below is the basic flow of how I built out the Rails API step by step :  &lt;/p&gt;

&lt;p&gt;Step 1 - Create a new Rails API using the command line below. Don’t forget to add the API flag at the end.&lt;br&gt;
&lt;code&gt;rails new eat-here-rails-backend --api&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Step 2 - Specify the attributes and datatypes of both models and utilize rails g resource command to create corresponding models, controllers, database migration tables, and routes.&lt;br&gt;
&lt;code&gt;rails g resource Restaurant name country image gif description address&lt;/code&gt;&lt;br&gt;
&lt;code&gt;rails g resource Review nickname comment restaurant:belongs_to&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Step 3 - Define index, show, create, update, and destroy actions and serialize data in relative controllers’ actions.  &lt;/p&gt;

&lt;p&gt;Step 4 - Define necessary validation and helper methods in models’ files. &lt;/p&gt;

&lt;p&gt;Step 5 -  Don’t forget to install the CORS gem and enable the CORS file to allow our server to specify from what origins it will permit. &lt;/p&gt;

&lt;p&gt;Here is my backend &lt;a href="https://github.com/lena0128/eat-here-rails-api-backend"&gt;repo&lt;/a&gt; on GitHub.&lt;/p&gt;
&lt;h2&gt;
  
  
  Building the Frontend App with React using Hooks
&lt;/h2&gt;

&lt;p&gt;Since this was my first React project, I spent a lot of time understanding a couple of core concepts before coding. For example, the difference between props &amp;amp; state, React lifecycle, virtual DOM, controlled components, Redux, and React-Redux. It helped me better structure and re-factor my codes. &lt;/p&gt;

&lt;p&gt;During the coding process, I found the most challenging part was how to utilize react redux to read state from the store and how to update state by dispatching actions. The basic flow of using react redux is: (1) We build up our actions; (2) We dispatch the actions to the reducer; (3) The reducer returns our state. &lt;/p&gt;
&lt;h4&gt;
  
  
  1. Create a Store
&lt;/h4&gt;

&lt;p&gt;When finishing the basic installation of all necessary dependencies, the first step is to set up the global state. Calling the &lt;code&gt;createStore&lt;/code&gt; method provided by redux will return us the store object. Since I also incorporated asynchronous requests in this application, I used redux thunk as the middleware to handle all the asynchronous actions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { createStore, applyMiddleware, compose } from 'redux';
import rootReducer from '../reducers/rootReducer';
import thunk from 'redux-thunk';


const store = createStore(rootReducer, compose(applyMiddleware(thunk), window.__REDUX_DEVTOOLS_EXTENSION__ &amp;amp;&amp;amp; window.__REDUX_DEVTOOLS_EXTENSION__()))

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Define Reducers
&lt;/h4&gt;

&lt;p&gt;Reducers are functions that accept the previous state as the first argument and an action object as the second argument and return the newly updated state. Note that reducers do not mutate the state directly. They return an entirely new state to replace the old one. Whatever the reducer returns will be our current state; The default action returns the initial state. Since I had two reducers created in my application, I utilized the &lt;code&gt;combineReducers()&lt;/code&gt; function to delegate different pieces of state to each reducer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { combineReducers } from 'redux';
import restaurantsReducer from './restaurantsReducer';
import reviewsReducer from  './reviewsReducer';

const rootReducer = combineReducers({
    restaurants: restaurantsReducer,
    reviews: reviewsReducer
})

export default rootReducer

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

&lt;/div&gt;



&lt;p&gt;Below contains the code snippet of my &lt;code&gt;restaurantReducer&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 initState = {
    restaurants: [], 
    loading: false 
}

const restaurantsReducer = (state = initState, action) =&amp;gt; {
    switch(action.type){
        case "LOADING":
            return {
                ...state,
                loading: true
            }

        case "ADD_RESTAURANT":
            return {
                ...state,
                restaurants: [...state.restaurants, action.payload]
            }

        case "FETCH_RESTAURANTS":
            return {
                ...state,
                restaurants: [...state.restaurants, ...action.payload],
                loading: false
            }

        case "UPDATE_RESTAURANT":
            const idx = state.restaurants.findIndex((restaurant) =&amp;gt; restaurant.id === action.payload.id)
            const restaurant = action.payload
                    return {
                        ...state,
                        restaurants: [...state.restaurants.slice(0, idx), restaurant, ...state.restaurants.slice(idx + 1) ]
                    }

        default:
            return state    
    } 
}

export default restaurantsReducer

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. Define All Actions
&lt;/h4&gt;

&lt;p&gt;An action is an object that has a type and a payload. We can imagine the payload as objects/data that we want to send to our reducer. Also, since I made fetch requests in my action creator, the thunk middleware enabled me to return functions from my action creators and pass &lt;code&gt;dispatch&lt;/code&gt; as an argument to the returned functions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const baseUrl = "http://localhost:5000/restaurants"

export const addRestaurant = (restaurantObj) =&amp;gt; {
    return {
        type: "ADD_RESTAURANT",
        payload: restaurantObj
    }
}

export const fetchRestaurants = () =&amp;gt; {
     return (dispatch) =&amp;gt; {
         dispatch({type: "LOADING"})

         fetch(baseUrl)
           .then(resp =&amp;gt; resp.json())
           .then(data =&amp;gt; {
               dispatch({
                   type: "FETCH_RESTAURANTS",
                   payload: data
               })
           })
     }     
}

export const createRestaurant = (restaurant) =&amp;gt; {
    return (dispatch) =&amp;gt; {
    const configObj = {
        method: "POST",
        headers: {
            "Content-Type": "application/json",
            "Accept": "application/json"
        },
        body:JSON.stringify({restaurant})
    }
        fetch(baseUrl, configObj)
          .then(resp =&amp;gt; resp.json())
          .then(restaurant =&amp;gt; dispatch(addRestaurant(restaurant)))
    }
}

export const updateRestaurant = (newObject) =&amp;gt; {
    return {
        type: "UPDATE_RESTAURANT",
        payload: newObject
    }
}

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  4. Read and Update State in Relative Components
&lt;/h4&gt;

&lt;p&gt;Since I used react hooks in this project, I imported &lt;code&gt;useSelector&lt;/code&gt; hook to connect to the store, and imported &lt;code&gt;useDispatch&lt;/code&gt; and &lt;code&gt;useEffect&lt;/code&gt; hooks to read and update the state in the components. &lt;/p&gt;

&lt;p&gt;Feel free to check my frontend &lt;a href="https://github.com/lena0128/eat-here-react-app"&gt;repo&lt;/a&gt; on GitHub.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further Thoughts
&lt;/h2&gt;

&lt;p&gt;For further development, I want to add the user authentication system to this project. The challenge is how to implement the jwt auth in both Redux and Rails. I will start researching and coding this topic from this &lt;a href=""&gt;article&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>rails</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Tasty Meals App - a SPA with a Ruby API backend and JS frontend</title>
      <dc:creator>newAlicorn</dc:creator>
      <pubDate>Mon, 01 Nov 2021 15:51:28 +0000</pubDate>
      <link>https://dev.to/newalicorn0128/tasty-meals-app-a-spa-with-a-ruby-api-backend-and-js-frontend-i0b</link>
      <guid>https://dev.to/newalicorn0128/tasty-meals-app-a-spa-with-a-ruby-api-backend-and-js-frontend-i0b</guid>
      <description>&lt;p&gt;My Tasty Meals App is a SPA application built with a Ruby API backend and JavaScript frontend. Besides reading meal recipes from around the world, this app allows users to create, update or delete their recipes. Users can also search a meal by name and filter meals by category. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The Backend&lt;/strong&gt;&lt;br&gt;
The app contains a Rails API backend that follows RESTful convention. When I created the backend folder in the terminal, I used &lt;code&gt;api&lt;/code&gt; flag to leave out the unnecessary features. Below is the command to create the API backend for the application:&lt;br&gt;&lt;br&gt;
&lt;code&gt;rails new tasty-meals-app-backend --api&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;I have two models for this project, a &lt;code&gt;category&lt;/code&gt; model and a &lt;code&gt;meal&lt;/code&gt; model. The relationship between the two models is:&lt;br&gt;
category: &lt;code&gt;has_many :meals&lt;/code&gt;&lt;br&gt;
meal: &lt;code&gt;belongs_to :category&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;There are some new takeaways I've gained from this project when creating the backend:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Adding model relationship when using &lt;code&gt;resource&lt;/code&gt; generator&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Below are the command lines I used to generate all the resources.&lt;br&gt;
&lt;code&gt;rails g resource Category name&lt;/code&gt;&lt;br&gt;
&lt;code&gt;rails g resource Meal name thumb ingredients instruction category:belongs_to&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We can omit the data type if it's a string. Also, we can specify the model relationship by adding &lt;code&gt;belongs_to&lt;/code&gt; or &lt;code&gt;references&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Since I already included --api flag, when I used the &lt;code&gt;resource&lt;/code&gt; generator it would skip generating views and helpers for us. Also it will have the controllers inherit from &lt;code&gt;ActionController::API&lt;/code&gt; instead of &lt;code&gt;ActionController::Base&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zXJLSTAz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ugl5pg66svln5u76fbaq.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zXJLSTAz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ugl5pg66svln5u76fbaq.JPG" alt="Image description" width="641" height="146"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Using Serializer to format data&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
There are mainly three ways to translate our Ruby objects into JSON format when our backend communicates with the frontend. We can directly include the format in the &lt;code&gt;render&lt;/code&gt; method in the controller. We can also include the Serializer in the model class. In this project, I implemented the data translation by adding the &lt;code&gt;active_model_serializers&lt;/code&gt; gem. Here is how:&lt;/p&gt;

&lt;p&gt;In the gemfile, add &lt;code&gt;gem 'active_model_serializers', '~&amp;gt; 0.10.2'&lt;/code&gt; and run &lt;code&gt;bundle install&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After running &lt;code&gt;rails g serializer category&lt;/code&gt; and &lt;code&gt;rails g serializer meal&lt;/code&gt; in the terminal, set up the attributes in the files: &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_Us7Qr5F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tc53xmbezvjpj69sk1ui.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_Us7Qr5F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tc53xmbezvjpj69sk1ui.JPG" alt="Image description" width="791" height="197"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--F1n6UUCs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jcnvvffvo8yuwz13n7a6.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--F1n6UUCs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jcnvvffvo8yuwz13n7a6.JPG" alt="Image description" width="582" height="188"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Upon setting things up as above, when we invoke the #index action in the &lt;code&gt;Category&lt;/code&gt; controller, Rails will recognize automatically the serializer we include, instead of calling &lt;code&gt;Category.all&lt;/code&gt;, we are actually calling the serialized data of categories using the &lt;code&gt;attribute&lt;/code&gt; method we specified.   &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;CORS&lt;/em&gt;&lt;/strong&gt; &lt;br&gt;
Since browsers do not allow unwanted HTTP requests from being sent to a server, they would restrict requests from a different origin. That's why we need enable CORS (Cross Origin Resource Sharing) to allow our server to specify from what origins it will permit. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The Frontend&lt;/strong&gt;&lt;br&gt;
On the frontend side, this app contains a single HTML page, styling with Bootstrap along with plain CSS. The app also uses Vanilla JavaScript codes to implement all the user interactions. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using Classes&lt;/strong&gt;&lt;br&gt;
I created four classes for my project: the &lt;code&gt;CategoryApi&lt;/code&gt; class and the &lt;code&gt;MealApi&lt;/code&gt; class are responsible for handling all fetch requests for the categories and meals; the &lt;code&gt;Meal&lt;/code&gt; class and the &lt;code&gt;Category&lt;/code&gt; class enable to create an category or an meal object that encapsulates both data and behaviors. &lt;/p&gt;

&lt;p&gt;Here is how I built out the &lt;code&gt;Meal&lt;/code&gt; class to create an meal object and attach it to the DOM. &lt;/p&gt;

&lt;p&gt;First I had the constructor prototypal method that was triggered every time when I invoked the &lt;code&gt;new&lt;/code&gt; keyword to create a new &lt;code&gt;meal&lt;/code&gt; object. The &lt;code&gt;meal&lt;/code&gt; backend object was passed into the constructor as the argument of the constructor. Here I used the destructuring method (cleaner and more easily to read) to assign the values. Besides the properties of each meal, I also set up the HTML element that would contain this meal object, and attached event listeners particular to each meal object. Then, I created &lt;code&gt;static all = []&lt;/code&gt; to save all the meal objects. Every newly created meal object would be pushed into this array.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sU0xHszb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xqp419i2u7z08lbxfs3g.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sU0xHszb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xqp419i2u7z08lbxfs3g.JPG" alt="Image description" width="716" height="499"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Static methods VS Instance methods&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Most of the time, if I was dealing with a specific meal object, it’s gonna be a instance method. For example, below are two instance methods for rendering an single meal object and attaching it to the DOM.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MTBWcD3d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sg2ldw4dpveraffgq184.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MTBWcD3d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sg2ldw4dpveraffgq184.JPG" alt="Image description" width="880" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When dealing with the collection of meal objects, I defined the static method as below. &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mZ4TX14Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/udx3qefasnqoe9pbzzdd.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mZ4TX14Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/udx3qefasnqoe9pbzzdd.JPG" alt="Image description" width="477" height="136"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Communication Between Backend and Frontend&lt;/strong&gt;&lt;br&gt;
All the interactions between the users and the server are handled  asynchronously on my app. I included at least 4 AJAX calls that covers full CRUD functionality - create, read, update and delete a meal object. JSON is used as the communication format for my app.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Qd9p7xnT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3sq0t86u5u5rn14j7hjb.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Qd9p7xnT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3sq0t86u5u5rn14j7hjb.JPG" alt="Image description" width="605" height="250"&gt;&lt;/a&gt;&lt;br&gt;
The above code shows how I handles the meal collection sent back from the API using the &lt;code&gt;fetch&lt;/code&gt; method. The flow is after I make a fetch request, I take the &lt;code&gt;meal&lt;/code&gt; object from the backend and create a frontend &lt;code&gt;meal&lt;/code&gt; object immediately. The newly created &lt;code&gt;meal&lt;/code&gt; frontend object has a bunch of prototype methods and static methods we can call on and manipulate with, for example, the &lt;code&gt;render&lt;/code&gt; method the &lt;code&gt;attachToDom&lt;/code&gt; method.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Further Thoughts&lt;/strong&gt;&lt;br&gt;
This project has a lot room for improvement. For example, I still need to work on optimizing the search functionality. I also want to add a user login system to my project.  &lt;/p&gt;

</description>
      <category>beginners</category>
      <category>javascript</category>
      <category>ruby</category>
      <category>rails</category>
    </item>
    <item>
      <title>Intro to JavaScript Variables</title>
      <dc:creator>newAlicorn</dc:creator>
      <pubDate>Sun, 05 Sep 2021 22:22:36 +0000</pubDate>
      <link>https://dev.to/newalicorn0128/intro-to-javascript-variables-17f6</link>
      <guid>https://dev.to/newalicorn0128/intro-to-javascript-variables-17f6</guid>
      <description>&lt;p&gt;&lt;strong&gt;1. Using reserved keywords&lt;/strong&gt;&lt;br&gt;
In JavaScript, we use one of the three reserved keywords - &lt;code&gt;var&lt;/code&gt;, &lt;code&gt;let&lt;/code&gt;, &lt;code&gt;const&lt;/code&gt; - to declare and assign a variable.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--d2NZEgK_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6eo85qgztu4l0shwfynr.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d2NZEgK_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6eo85qgztu4l0shwfynr.JPG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;br&gt;
(1). If the const value is an array or an object, we can modify the properties or the elements.&lt;br&gt;
(2). When to use:&lt;br&gt;
DO NOT use &lt;code&gt;var&lt;/code&gt;&lt;br&gt;
Use &lt;code&gt;let&lt;/code&gt; for variables where the value may change&lt;br&gt;
Use &lt;code&gt;const&lt;/code&gt; whenever possible &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Without reserved keywords&lt;/strong&gt;&lt;br&gt;
If we assign a variable without using any of the keywords, the variable will be a global variable. We should avoid defining global variables because they can be accessed and changed EVERYWHERE. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Fun Drink Recipes App</title>
      <dc:creator>newAlicorn</dc:creator>
      <pubDate>Fri, 03 Sep 2021 22:48:03 +0000</pubDate>
      <link>https://dev.to/newalicorn0128/fun-drink-recipes-app-4l7d</link>
      <guid>https://dev.to/newalicorn0128/fun-drink-recipes-app-4l7d</guid>
      <description>&lt;p&gt;The Fun Drink Recipe App is built with Ruby on Rails framework. This web application is for drink lovers to find and create ingredients and recipes from cocktails to milkshakes. Users can also comment and rating on any ingredient. Besides CRUD operations, the app also provides name search and filter functionality. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Models and Associations&lt;/strong&gt;&lt;br&gt;
There are five models in my project - a &lt;code&gt;User&lt;/code&gt; model, an &lt;code&gt;Ingredient&lt;/code&gt; model, a &lt;code&gt;Drink&lt;/code&gt; model, a &lt;code&gt;Measurement&lt;/code&gt; model and a &lt;code&gt;Review&lt;/code&gt; model. The associations among these models are shown as below (created with &lt;a href="https://app.diagrams.net/"&gt;Draw.io&lt;/a&gt;):&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qxKeebsS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2v00iuxbdu0ytrkf95kf.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qxKeebsS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2v00iuxbdu0ytrkf95kf.JPG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data Validations&lt;/strong&gt;&lt;br&gt;
Besides built-in validation methods, I wrote custom validation methods the attributes in my models. For example: the user's input of a drink name will be automatically title cased before the data saved into the database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/models/drink.rb

class Drink &amp;lt; ApplicationRecord
  before_validation :make_title_case, :set_defalut_thumb

  def make_title_case
        self.drink_name = drink_name.titlecase
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, if users do not provide an image URL, they would be given a default one by the system.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/models/drink.rb

    def set_defalut_thumb
        if self.drink_thumb == nil || self.drink_thumb == ""
            self.drink_thumb = "https://www.thecocktaildb.com/images/media/drink/mrz9091589574515.jpg"
        end
    end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Scope Methods to Query Data&lt;/strong&gt;&lt;br&gt;
A scope is an efficient way to filter an application using ActiveRecord queries or SQL. It's also easy to write a WHERE, ORDER, LIMIT, etc. with just one line. &lt;/p&gt;

&lt;p&gt;In my project, I defined several scope methods for querying data from the database to implement search and filter functionality. Below is an example of how I implemented name search with a scope method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/models/item.rb

scope :item_search, -&amp;gt;(name) { where("name LIKE ?", "%#{name.titlecase}%") } 

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

&lt;/div&gt;



&lt;p&gt;On the homepage, the data of latest alcoholic and nonalcoholic drinks are also found with two scope methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/models/drink.rb

scope :alcohol_drink_filter, -&amp;gt; { Drink.joins(:item). where(item: {alcohol: "yes"}).last(3) }
scope :non_alcohol_drink_filter, -&amp;gt; { Drink.joins(:item). where(item: {alcohol: "no"}).last(3) }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;User Authentication&lt;/strong&gt;&lt;br&gt;
My application provides standard user authentication, including signup, login, logout, and secure passwords. The &lt;code&gt;bcrypt&lt;/code&gt; gem I used helps generate salt and hashed passwords, while the &lt;code&gt;has_secure_password&lt;/code&gt; method that is provided by ActiveRecord saves the passwords in the database and authenticates users.&lt;/p&gt;

&lt;p&gt;There are two main methods we get from the #has_many_password method:&lt;br&gt;
(1) The &lt;code&gt;password=&lt;/code&gt; method allows us to create a user with a password attribute rather than a &lt;code&gt;password_digest&lt;/code&gt; attribute. The method uses &lt;code&gt;Bcrypt&lt;/code&gt; gem to hash and salt the password and then save it in the &lt;code&gt;password_digest&lt;/code&gt; column in our table. Note that we don’t have to validate the password manually in our code. #has_secure_password validates the password automatically when being invoked.&lt;/p&gt;

&lt;p&gt;(2) The &lt;code&gt;authenticate&lt;/code&gt; method takes in the password a user enters when logging in and uses &lt;code&gt;Bcrypt&lt;/code&gt; to hash and salt the input and compare it to what is saved in the &lt;code&gt;password_digest&lt;/code&gt; column for that user. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Log In with a Third Party&lt;/strong&gt;&lt;br&gt;
The authentication system of my app also allows users to login from Google. To implement this functionality we need three gems in total - &lt;br&gt;
(1) &lt;code&gt;omniauth&lt;/code&gt; - this gem helps us log in with a third party&lt;br&gt;
(2) &lt;code&gt;dotenv-rails&lt;/code&gt; - thie gem ensures that the environment variables are correctly loaded into the ENV hash in a secure manner&lt;br&gt;
(3) &lt;code&gt;omniauth-google-oauth2&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We also need to add two files -&lt;br&gt;
&lt;code&gt;.env&lt;/code&gt; - this file is where you save your ‘GOOGLE_CLIENT_ID’ and ‘GOOGLE_CLIENT_SECRET’ key-value pairs. Don’t forget to save it into the gitignore file!  &lt;/p&gt;

&lt;p&gt;&lt;code&gt;/config/initializers/omniauth.rb&lt;/code&gt; - this files is to tell Rails to use OmniAuth to Authenticate our user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# /config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
    provider :google_oauth2, ENV['GOOGLE_CLIENT_ID'], ENV['GOOGLE_CLIENT_SECRET'], :skip_jwt =&amp;gt; true
  end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then set up the route -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# config/routes.rb
get '/auth/:provider/callback', to: 'sessions#omniauth'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that we don’t have a get ‘/auth/google’ route set up because Omniauth uses Rack Middleware to intercept the request to ‘/auth/google’. &lt;/p&gt;

&lt;p&gt;Once the user clicks 'Login with Google’, it momentarily sends the user to mysite.com/auth/google, which quickly redirects to the Google sign-in page.&lt;/p&gt;

&lt;p&gt;After the user agrees to let mysite.com access the user’s information, the user is redirected back to &lt;br&gt;
mysite.com/auth/google/callback, and from there, to the page they initially tried to access.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nested Resources&lt;/strong&gt;&lt;br&gt;
Making use of a nested resource with the appropriate RESTful URLs has helped me keep my routes neat and tidy. It is better than dynamic route segments for representing parent/child relationships in the system. Note that do not nest more than one level deep.&lt;/p&gt;

&lt;p&gt;In my app, I included nested a new measurement route to the drinks resource - &lt;code&gt;new_drink_ingredient_path(@drink)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And nested &lt;code&gt;review&lt;/code&gt; routes to the &lt;code&gt;ingredients&lt;/code&gt; resource -   &lt;/p&gt;

&lt;p&gt;new: &lt;code&gt;new_ingredient_review_path(@ingredient)&lt;/code&gt;&lt;br&gt;
index: &lt;code&gt;ingredient_reviews_path(@ingredient)&lt;/code&gt;&lt;br&gt;
show: &lt;code&gt;ingredient_review_path(@ingredient, @review)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Below is how I created the nested index &lt;code&gt;review&lt;/code&gt; route to the &lt;code&gt;ingredients&lt;/code&gt; resource step by step. Note that the URL helper generated for each nested route will accept at least one argument.    &lt;/p&gt;

&lt;p&gt;Step 1 - set up nested routes in &lt;code&gt;config/routes.rb&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;resources :ingredients, only: [:show] do
     resources :reviews
  end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: make changes in the &lt;code&gt;reviews#index&lt;/code&gt; controller action. Add if-else statement to reuse the controller action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/controllers/reviews_controller.rb 

  def index
        if params[:ingredient_id]
          @ingredient = Ingredient.find_by(id: params[:ingredient_id])
            @reviews = @ingredient.reviews
        else
        @reviews = Review.all
        end
    end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the user comes from nested routes (&lt;code&gt;/ingredients/:id/&lt;/code&gt;) and makes a &lt;code&gt;index&lt;/code&gt; request (&lt;code&gt;/ingredients/:id/reviews&lt;/code&gt;),  the &lt;code&gt;ingredient_id&lt;/code&gt; key-value pair would be automatically saved in the &lt;code&gt;params&lt;/code&gt; hash. Else the user is determined coming from the review index page (&lt;code&gt;/reviews&lt;/code&gt;). That’s why we check the user’s http request by &lt;code&gt;params[:ingredient_id]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Step 3 - make changes to links in views:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/views/ingredients/show.html.erb

&amp;lt;%= link_to "Add a Review", ingredient_reviews_path(@ingredient) %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 4 - make changes in the &lt;code&gt;index&lt;/code&gt; form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/views/reviews/_form.html.erb

&amp;lt;div class="container"&amp;gt;

&amp;lt;% if @ingredient %&amp;gt;

&amp;lt;h3&amp;gt;All Reviews on &amp;lt;%= @ingredient.name %&amp;gt;&amp;lt;/h3&amp;gt;

&amp;lt;%= render partial: "reviews/reviews", locals: {reviews: @ingredient.reviews } %&amp;gt;

&amp;lt;%= link_to "Return #{@ingredient.name}", ingredient_path(@ingredient), class: "btn btn-info btn-sm" %&amp;gt;

&amp;lt;%else%&amp;gt;
&amp;lt;h3&amp;gt;All Reviews&amp;lt;/h3&amp;gt;
&amp;lt;%= render partial: "reviews", locals: {reviews: @reviews} %&amp;gt;

&amp;lt;%end%&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;DRY Code&lt;/strong&gt;&lt;br&gt;
Writing appropriate &lt;code&gt;partials&lt;/code&gt; and &lt;code&gt;helpers&lt;/code&gt; are crucial to DRY up the code and follow the single responsibility principle. Practicing more is extremely important to acquire these techniques.   &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Further Thoughts&lt;/strong&gt;&lt;br&gt;
During the project, one of my biggest challenge is how to build up the most effective and workable model relationships. I would like to do more researches on the model associations such as &lt;code&gt;has_one :through&lt;/code&gt;and &lt;code&gt;has_and_belongs_to_many&lt;/code&gt; later on. Furthermore, I want to practice set up the &lt;code&gt;forms with&lt;/code&gt; the #form_with method to substitute &lt;code&gt;form_for&lt;/code&gt; and &lt;code&gt;form_tag&lt;/code&gt;.  &lt;/p&gt;

</description>
      <category>beginners</category>
      <category>ruby</category>
      <category>rails</category>
    </item>
    <item>
      <title>My Book Review Sinatra App</title>
      <dc:creator>newAlicorn</dc:creator>
      <pubDate>Sat, 03 Jul 2021 00:28:21 +0000</pubDate>
      <link>https://dev.to/newalicorn0128/my-book-review-sinatra-app-3bfc</link>
      <guid>https://dev.to/newalicorn0128/my-book-review-sinatra-app-3bfc</guid>
      <description>&lt;p&gt;My Sinatra project is an online book review application in which a user can create, view, edit and delete their book review posts after safely signing up or logging in to their accounts. The user can also view others' posts, but he/she may not be allowed to edit or delete other users' posts. Here is my live site: &lt;a href="https://sinatra-book-app.herokuapp.com/"&gt;https://sinatra-book-app.herokuapp.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Through this project,  I have gained a better understanding of the MVC pattern, which I believe is the core concept of building up a Sinatra project. &lt;/p&gt;

&lt;p&gt;The Model-View-Controller (MVC) is an architectural pattern that separates an application into three main logical components: the model, the view, and the controller. Each of these components are built to handle specific development aspects of an application. The model contains the logic of the application. The view implements the interface of the application. The controller is a linker between the model and the view.&lt;/p&gt;

&lt;p&gt;The best practice is that the model and the view should NEVER communicate. All of the views should get their information from controllers.&lt;/p&gt;

&lt;p&gt;Furthermore, I have solidified my knowledge of user authentication. Below are the basic steps to create a user authentication in the Sinatra project: &lt;/p&gt;

&lt;p&gt;(1) Add &lt;code&gt;bcrypt&lt;/code&gt; to the gemfile, which would provide a hashing algorithm to the user’s password.&lt;/p&gt;

&lt;p&gt;(2) Add &lt;code&gt;has_secure_password&lt;/code&gt; to the User model.&lt;/p&gt;

&lt;p&gt;(3) The user table must have a &lt;code&gt;password_digest&lt;/code&gt; column in the database where the salted and hashed password will be stored.&lt;/p&gt;

&lt;p&gt;(4) When a user has successfully authenticated themselves, store their &lt;code&gt;user.id&lt;/code&gt; in the session as below:&lt;br&gt;
&lt;code&gt;session[:user_id] = user.id&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;(5) Ensure that the attribute we find users by login is unique.&lt;/p&gt;

&lt;p&gt;In short, building up a Sinatra project from scratch on one's own is challenging;  but once you've gone through the whole process, researched and corrected every single error, and finally push your site online, you would find how rewarding your hard work is!&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>sinatra</category>
      <category>ruby</category>
    </item>
  </channel>
</rss>
