<?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: michaella latkovic</title>
    <description>The latest articles on DEV Community by michaella latkovic (@michaellalatkovic).</description>
    <link>https://dev.to/michaellalatkovic</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%2F182546%2F6699185e-4d66-40c7-acae-54751d3c0314.JPG</url>
      <title>DEV Community: michaella latkovic</title>
      <link>https://dev.to/michaellalatkovic</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/michaellalatkovic"/>
    <language>en</language>
    <item>
      <title>How to deploy a Rails API backend on Kubernetes with Amazon EKS and RDS</title>
      <dc:creator>michaella latkovic</dc:creator>
      <pubDate>Tue, 14 Jan 2020 04:33:26 +0000</pubDate>
      <link>https://dev.to/michaellalatkovic/deploying-on-kubernetes-part-1-a-rails-api-backend-2ojl</link>
      <guid>https://dev.to/michaellalatkovic/deploying-on-kubernetes-part-1-a-rails-api-backend-2ojl</guid>
      <description>&lt;p&gt;Recently I built a React Redux application with a Rails API backend called Root (you can see blog &lt;a href="https://dev.to/michaellalatkovic/root-a-simple-react-redux-application-with-bootstrap-106b"&gt;here&lt;/a&gt;). I thought it would be fun exercise to deploy my app on Kubernetes. I decided to use EKS to run Kubernetes on AWS as I've been wanting to learn more about AWS services as well. &lt;/p&gt;

&lt;h3&gt;
  
  
  1. Setup Pre-Requisites
&lt;/h3&gt;

&lt;p&gt;Make sure to install the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.docker.com/products/developer-tools" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/aws/aws-cli" rel="noopener noreferrer"&gt;AWS CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/weaveworks/eksctl" rel="noopener noreferrer"&gt;eksctl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/reference/kubectl/overview/" rel="noopener noreferrer"&gt;kubectl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kubernetes-sigs/aws-iam-authenticator" rel="noopener noreferrer"&gt;AWS IAM Authenticator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/getting-started-eksctl.html" rel="noopener noreferrer"&gt;Amazon EKS docs&lt;/a&gt; have a good overview of installing the AWS CLI, eksctl, kubectl, and the AWS IAM authenticator.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Update database.yml
&lt;/h3&gt;

&lt;p&gt;In the Rails API code, the database.yml file needs to be updated to allow for the environment variables we need to pass to connect to the production database. Running off of a centralized database is probably the biggest difference between running the app locally in development mode on my laptop and in production mode in the cloud.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;production:
  &amp;lt;&amp;lt;: *default
  database: &amp;lt;%= ENV['DB_NAME'] %&amp;gt;
  username: &amp;lt;%= ENV['DB_USERNAME'] %&amp;gt;
  password: &amp;lt;%= ENV['DB_PASSWORD'] %&amp;gt;
  host: &amp;lt;%= ENV['DB_URL'] %&amp;gt;
  port: 5432
~~~


### 3. Write the Dockerfile

To containerize the application, we need to create a Dockerfile in the root directory of the rails application. This defines how our container is built by the docker runtime.


DOCKERFILE for backend:

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

&lt;/div&gt;

&lt;p&gt;FROM ruby:2.6.1&lt;/p&gt;

&lt;h1&gt;
  
  
  Create a local folder for the app assets
&lt;/h1&gt;

&lt;p&gt;RUN mkdir /backend&lt;br&gt;
WORKDIR /backend&lt;/p&gt;

&lt;h1&gt;
  
  
  Install required tooling
&lt;/h1&gt;

&lt;p&gt;RUN apt-get update &amp;amp;&amp;amp; apt-get install -qq -y build-essential nodejs libpq-dev postgresql-client --fix-missing --no-install-recommends&lt;/p&gt;

&lt;h1&gt;
  
  
  Set our environment variables
&lt;/h1&gt;

&lt;p&gt;ENV RAILS_ENV production #run the app in production mode&lt;br&gt;
ENV RAILS_SERVE_STATIC_FILES true #serves static files (better performance)&lt;br&gt;
ENV RAILS_LOG_TO_STDOUT true #ensures our rails logs will be exposed from the container (useful for debugging!)&lt;/p&gt;

&lt;h1&gt;
  
  
  Copy and install Gems from our Gemfile
&lt;/h1&gt;

&lt;p&gt;COPY Gemfile /backend/Gemfile &lt;br&gt;
COPY Gemfile.lock /backend/Gemfile.lock&lt;/p&gt;

&lt;p&gt;RUN gem install bundler -v 2.0.2&lt;/p&gt;

&lt;p&gt;RUN bundle install --deployment&lt;/p&gt;

&lt;p&gt;COPY . ./&lt;/p&gt;

&lt;p&gt;EXPOSE 3000&lt;/p&gt;

&lt;h1&gt;
  
  
  Start the puma server
&lt;/h1&gt;

&lt;p&gt;CMD bundle exec puma -p 3000&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Now, we'll use the Dockerfile to build a container image we can run on the Kubernetes cluster. Navigate to the root directory of the backend app and build the Dockerfile:

{% raw %}`docker image build -t backend:1.0 .`

**Note: the '.' at the end of that command means build in the current directory. A super helpful resource I used was: [Docker Deep Dive](https://www.amazon.com/Docker-Deep-Dive-Nigel-Poulton/dp/1521822808/ref=tmm_pap_swatch_0?_encoding=UTF8&amp;amp;qid=1578946525&amp;amp;sr=8-1)**


Lastly, you can run the container to see if the image build worked.

`docker container run -d --name backend -p 3000:3000 backend:1.0`

You can test it by running `docker ps`. You should see something like this:

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

&lt;/div&gt;

&lt;p&gt;CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES&lt;br&gt;
ebbf78152a56        backend:1.0         "/bin/sh -c 'bundle …"   4 seconds ago       Up 2 seconds        0.0.0.0:3000-&amp;gt;3000/tcp   backend&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Note that this will expose the container on http://localhost:3000, but will not render any data as we have not connected the container to our database!

### 4. Push Docker images to cloud

In order to run our container on the Kubernetes cluster, we need it stored somewhere the cluster can access. I used [Amazon Elastic Container Registry](https://aws.amazon.com/ecr/) to host the container image, it was super simple to setup! 

1. Create the ECR repository (I called mine 'backend')
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/672my3onfgvzxazidpq1.png)


2. Push images to ECR. ECR gives you a really nice set of instructions on how to do this right from the console!
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/q1ndad24erkvdag4v7nz.png)

    a. Retrieve our ECR credentials:
    {% raw %}`$(aws ecr get-login --no-include-email --region us-west-2)`

    b. Tag the image for ECR
    `docker tag backend:1.0 &amp;lt;account ID&amp;gt;.dkr.ecr.us-west-2.amazonaws.com/backend:1.0`

    c. Push the image to ECR:
    `docker push &amp;lt;account ID&amp;gt;.dkr.ecr.us-west-2.amazonaws.com/backend:1.0`

3. See your image and get the URI. Once your image is pushed to ECR, you can see it in the console (or using the AWS CLI). You'll need to get the URI for the image in order to run it on your cluster.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/gbyalyotg6sulfeg8wek.png)

### 5. Create EKS cluster

It turns out there are a lot of ways to create an EKS cluster! I used eksctl as it was simple and easy. The [eksctl docs](https://eksctl.io/introduction/getting-started/) have a great overview of how to use eksctl to create a Kubernetes cluster on AWS.

To create my EKS cluster, I ran:
`eksctl create cluster --region us-west-2 --name root --managed`

This command creates an EKS cluster in Oregon named 'Root' (the name of my App) with an EKS managed node group.

The cluster takes a few minutes to create, when its done, you can see it in the AWS console:
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/vv73ltbxw4b2peyjcb9a.png)

You can also see that the cluster is running by seeing the running nodes with kubectl – `kubectl get nodes`

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

&lt;/div&gt;

&lt;p&gt;NAME                                           STATUS   ROLES    AGE   VERSION&lt;br&gt;
ip-192-168-66-201.us-west-2.compute.internal   Ready       25h   v1.14.7-eks-1861c5&lt;/p&gt;

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

### 6. Create RDS Postgres instance

The biggest difference between running the app locally and in Kubernetes is that instead of a single instance of the app using a database running on my laptop, lots of copies of my app (potentially) need to share a single database.

I read a few examples of people running Postgres in Kubernetes, but since my goal was to run this on AWS, I wanted to use [Amazon Relational Database Service](https://aws.amazon.com/rds/) to set up my Postgres database in the cloud.

Again, using Amazon RDS was extremely easy to use. There are a lot of options, I selected 'free tier' as a pre-configured setup as I'm not going to be scaling this app beyond a few tests. In production, you can select much larger instances to host the database.

You can even have RDS create the database for you when you provision the instance. This lets you skip the {% raw %}`db:create` step when configuring the database later. I opted to have RDS create my database 'backend'.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/ub5thhynfr3mvlza38dv.png)

When creating the database, it's important to setup the username, password, and port correctly. I used the default username, had RDS auto-generate a secure password, and set the port to 5432 - which is the default postgres port and **the port I had configured way back in my database.yml file**!

Some additional things to remember when setting this up are to ensure you allow for network connections between the database and the Kubernetes cluster. It is important that you create the DB in the same VPC as your K8s cluster. This ensures easy connectivity with the running API server. I also added the [security groups](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html) used by the cluster to the database ensure that my API containers are not blocked from communicating with the RDS database.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/6lfqq9ifgdhikkkqaj4f.png)

Because we're not running a highly-available database, RDS lets you select which Availability Zone (AZ) to run your database instance in. I left this to 'none' which seems to mean "run anywhere". In production I would probably run this as highly-available (across multiple AZs) or select an AZ that matches the AZs where we run the backend API server containers/nodes to minimize cross-AZ traffic ($$).

### 7. Setup our database credentials

When we run our backend container, we need to securely pass the login credentials to our container as environment variables. We'll do this with a K8s secret. I used [this blog](https://www.engineyard.com/blog/kubernetes-tutorial-running-a-rails-app-in-kubernetes) as a guide to set up the secret.

#### Steps:

a. Encrypt your username and password for the RDS database using base64 encryption `echo -n "&amp;lt;username&amp;gt;" | base64` and `echo -n "&amp;lt;password&amp;gt;" | base64`. Keep track of the output!

b. Create a yaml file for the secret:

db-creds.yaml

&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;  apiVersion: v1
  kind: Secret
  metadata:
    name: db-creds
  type: Opaque
  data:
    username: &amp;lt;base64 encoded username&amp;gt;
    password: &amp;lt;base64 encoded password&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;
c. Create the secret on the cluster: {% raw %}`kubectl create -f db-secret.yaml`


### 7. Create the K8s deployment

We're finally ready to run our app! To do this, we need to write a k8s deployment yaml file that specifies the container we want to run and passes all the correct environment variables for connecting to the RDS database. Note, when writing these files, _spaces matter_. I use atom to make sure everything lines up!

backend.yaml

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

&lt;/div&gt;

&lt;p&gt;apiVersion: extensions/v1beta1&lt;br&gt;
kind: Deployment&lt;br&gt;
metadata:&lt;br&gt;
  name: backend # name of the deployment&lt;br&gt;
  labels: # these labels apply to the deployment&lt;br&gt;
    app: root&lt;br&gt;
    component: backend&lt;br&gt;
spec:&lt;br&gt;
  strategy:&lt;br&gt;
    type: Recreate&lt;br&gt;
  template:&lt;br&gt;
    metadata:&lt;br&gt;
      labels: # these labels apply to our container&lt;br&gt;
        app: root&lt;br&gt;
        component: backend&lt;br&gt;
    spec:&lt;br&gt;
      containers:&lt;br&gt;
      - name: backend # name of our container&lt;br&gt;
        image: .dkr.ecr.us-west-2.amazonaws.com/backend:1.0 # the URI that we got from ECR&lt;br&gt;
        env:&lt;br&gt;
        - name: DB_URL&lt;br&gt;
          value: root..us-west-2.rds.amazonaws.com # URL of our database endpoint&lt;br&gt;
        - name: DB_USERNAME&lt;br&gt;
          valueFrom:&lt;br&gt;
            secretKeyRef:&lt;br&gt;
              name: db-creds&lt;br&gt;
              key: username # use the encoded username from the K8s secret db-creds&lt;br&gt;
        - name: DB_PASSWORD&lt;br&gt;
          valueFrom:&lt;br&gt;
            secretKeyRef:&lt;br&gt;
              name: db-creds&lt;br&gt;
              key: password # use the encoded password from the K8s secret db-creds&lt;br&gt;
        - name: DB_NAME&lt;br&gt;
          value: backend # our DB is named backend&lt;br&gt;
        ports:&lt;br&gt;
        - containerPort: 3000 # expose the running contianer on port 3000&lt;br&gt;
          name: backend&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Run this deployment with {% raw %}`kubectl create -f backend.yaml`. You should see:



```
$ kubectl create -f backend.yaml
deployment.extensions/backend created
```



You can check that the pods are running via `kubectl get pods`:



```
$ kubectl get pods
NAME                       READY   STATUS    RESTARTS   AGE
backend-68469b6dd4-8lcxl   1/1     Running   0          11m
```



You can describe the deployment and pods to get all sorts of interesting information - `kubectl describe pod/&amp;lt;pod ID&amp;gt;`

Remember way back in the Dockerfile when we set rails to log to STDOUT? Now this comes in handy because we can run `kubectl logs &amp;lt;pod ID&amp;gt;` to see the logs for our rails app. This can be very helpful in troubleshooting!

### 8. Configure the database

Now that our rails app is successfully running, we need to configure our database. You only have to do this once, the first time you set up the app. Future containers that run will automatically connect and find the configured database and data.

#### Steps
a. Exec (open a shell) into the running pod with `kubectl exec -it &amp;lt;pod ID&amp;gt; -- /bin/bash`. You're now executing commands inside of the running container!
b. Run `bundle exec rake db:migrate` to configure the database.
c. If you have seed data, you can add it to the database by running `bundle exec rake db:seed`

You'll see a ton of output as the database is setup by rails.
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/gp3bwlacok3vdxsojlwq.png)

### 9. Test your running API server!

We now have our backend rails API running on Kubernetes! You can test this out by setting up port forwarding to expose the deployment as a URL in our browser.


Run `kubectl port-forward deployment/backend 3000`. The 3000 means that the port forward will both listen and serve traffic on port 3000.



```
$ kubectl port-forward deployment/backend 3000
Forwarding from 127.0.0.1:3000 -&amp;gt; 3000
Forwarding from [::1]:3000 -&amp;gt; 3000
Handling connection for 3000
```



Visit the URL for our API in the browser: http://127.0.0.1:3000/api/v1/platforms

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/fdxz3919jfj9d4yu8p53.png)


Congratulations, the backend API is up and running!

### Next steps

The first half of my app is now running in a container on Kubernetes with an RDS Postgres database on AWS. In the second part of this blog, I will share how I containerizing my frontend and connected it to the backend. Stay tuned!


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

&lt;/div&gt;

</description>
      <category>kubernetes</category>
      <category>docker</category>
      <category>aws</category>
      <category>rails</category>
    </item>
    <item>
      <title>Root. A simple react redux application with bootstrap </title>
      <dc:creator>michaella latkovic</dc:creator>
      <pubDate>Tue, 24 Dec 2019 19:35:23 +0000</pubDate>
      <link>https://dev.to/michaellalatkovic/root-a-simple-react-redux-application-with-bootstrap-106b</link>
      <guid>https://dev.to/michaellalatkovic/root-a-simple-react-redux-application-with-bootstrap-106b</guid>
      <description>&lt;p&gt;I wrote a quick overview of the react redux app I built recently. I wanted to build an app I would actually find useful while also practicing building a React/Redux application. &lt;/p&gt;

&lt;p&gt;I brainstormed any challenges I was having that could be aided with the help of a useful app. As I am constantly learning and taking online courses, I began to think about all the digital platforms I use. &lt;/p&gt;

&lt;p&gt;Udemy, Coursera, Khan Academy, EdX, online textbooks... with so many wonderful resources online, it would be great to have one place you can go to manage and organize all your learning platforms!&lt;/p&gt;

&lt;p&gt;I created Root. Root allows you to consolidate all your digital learning platforms into one application. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--k7jz7yUL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/vdb1up7e6c4h7rb7xkyn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k7jz7yUL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/vdb1up7e6c4h7rb7xkyn.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see all your courses for a single application. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--d9_G-ATC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ovwj8dopbw160disv4u2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d9_G-ATC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ovwj8dopbw160disv4u2.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each course, also has the functionality to add to do items. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--g1WoONs3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/c09mhf7p9g7behj37tjs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--g1WoONs3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/c09mhf7p9g7behj37tjs.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Backend - a rails api
&lt;/h3&gt;

&lt;p&gt;I built the backend as a Rails API with a PostgreSQL database. I wanted to keep this app simple (at least to start) - I included 3 models as a basic framework. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Platform&lt;/li&gt;
&lt;li&gt;Course &lt;/li&gt;
&lt;li&gt;Todo&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Y8QENcct--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/jtpiy86a6vfuguhklzpc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Y8QENcct--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/jtpiy86a6vfuguhklzpc.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
For serialization I used the active_model_serializer gem and intentionally nested everything into the platforms index page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Frontend - react/redux/bootstrap
&lt;/h3&gt;

&lt;p&gt;To organize the frontend architecture, I have 3 containers and 12 components.&lt;/p&gt;

&lt;p&gt;The top-most component, the App component, is responsible for three main things.&lt;/p&gt;

&lt;p&gt;It renders the NavigationBar and Jumbrotron components. It renders The Platforms container, which holds all other containers and components. It also renders a Layout component and holds the same layout for entire application. &lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      &amp;lt;NavigationBar/&amp;gt;&lt;br&gt;
      &amp;lt;Jumbotron/&amp;gt;&lt;br&gt;
      &amp;lt;Layout&amp;gt;&lt;br&gt;
        &amp;lt;PlatformsContainer/&amp;gt;&lt;br&gt;
      &amp;lt;/Layout&amp;gt;&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Overview: &lt;strong&gt;Containers&lt;/strong&gt; + &lt;em&gt;Components&lt;/em&gt;&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;App&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Navigation&lt;/em&gt; (functional)&lt;br&gt;
&lt;em&gt;Jumbotron&lt;/em&gt; (functional)&lt;br&gt;
&lt;em&gt;Layout&lt;/em&gt; (functional)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Platform&lt;/strong&gt; &lt;strong&gt;Container&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Platforms&lt;/em&gt; (functional)&lt;br&gt;
&lt;em&gt;Platform&lt;/em&gt; (functional)&lt;br&gt;
&lt;em&gt;PlatformInput&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Course&lt;/strong&gt; &lt;strong&gt;Container&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Courses&lt;/em&gt; (functional)&lt;br&gt;
&lt;em&gt;Course&lt;/em&gt; (functional)&lt;br&gt;
&lt;em&gt;CourseInput&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ToDo&lt;/strong&gt; &lt;strong&gt;Container&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;ToDos&lt;/em&gt; (functional)&lt;br&gt;
&lt;em&gt;ToDoInput&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The redux store holds the platforms which will hold all courses and each course's todos as this is this way I designed my backend. This meant I could use only one single reducer, the platformsReducer which made it easier on the frontend to keep track of which platform courses and todos belong to as I always returned platforms. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--K9aBayWz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/xv15pd2mmxf8abmxih7r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--K9aBayWz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/xv15pd2mmxf8abmxih7r.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
(expanded - to show courses nested)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AlAcyrzN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/qrf9av9p687rqzfjvij0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AlAcyrzN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/qrf9av9p687rqzfjvij0.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I built 4 actions fetchPlatforms, addPlatform, addCourse, and addTo. &lt;/p&gt;

&lt;h3&gt;
  
  
  Bootstrap
&lt;/h3&gt;

&lt;p&gt;One thing that was important to me for this project was to really understand Bootstrap. For all my prior projects, I have done all by CSS by hand, which was great because I wanted to really understand how to do all the styling without help.&lt;/p&gt;

&lt;p&gt;However, I am at place where I feel comfortable and can now upgrade to Bootstrap and save TIME!&lt;/p&gt;

&lt;p&gt;Once I got the hang of importing the react-bootstrap components - the app really came together. &lt;a href="https://react-bootstrap.netlify.com/"&gt;The bootstrap docs&lt;/a&gt; are fantastic!&lt;/p&gt;

&lt;p&gt;To see all this code in detail, feel free to visit the GitHub repos!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/mvlt18/react-redux-app-backend"&gt;Root - backend repo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/mvlt18/react-redux-app-frontend"&gt;Root - frontend repo&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Next Additions:
&lt;/h3&gt;

&lt;p&gt;These are additions and functionalities that I'm currently working on adding: &lt;/p&gt;

&lt;p&gt;*Add a user model. &lt;br&gt;
*Ability to login/sign up for an account.&lt;br&gt;
*Delete/Edit a platform/course/todo&lt;br&gt;
*Check off a todo&lt;/p&gt;

&lt;p&gt;Happy coding, &lt;br&gt;
Michaella &lt;/p&gt;

</description>
      <category>react</category>
      <category>redux</category>
      <category>rails</category>
    </item>
    <item>
      <title>big O - big picture</title>
      <dc:creator>michaella latkovic</dc:creator>
      <pubDate>Mon, 28 Oct 2019 00:16:52 +0000</pubDate>
      <link>https://dev.to/michaellalatkovic/big-o-big-picture-1kfj</link>
      <guid>https://dev.to/michaellalatkovic/big-o-big-picture-1kfj</guid>
      <description>&lt;p&gt;One of the wonderful things about coding is that there are usually a multitude of ways to solve any single problem. However, could there be a right or wrong way to code an algorithm as long as the result is giving you the desired output? &lt;/p&gt;

&lt;p&gt;In reality, there are definitely &lt;em&gt;better&lt;/em&gt; ways of solving problems. &lt;/p&gt;

&lt;p&gt;So what does better really mean? Better means more efficient. &lt;/p&gt;

&lt;p&gt;But given two algorithms, how do you measure better? A very simple approach could be measuring the seconds it takes to finish executing. &lt;/p&gt;

&lt;p&gt;This approach presents with a problem - if I measure the time it take on my computer, and then let's say you run that same algorithm and measure the time on your computer, it will actually vary in time! Not only will different machines record different times, the same machine will record different times as well! This isn't a very reliable method of comparison - especially since for some very fast algorithms, speed may not be precise enough.&lt;/p&gt;

&lt;p&gt;Instead of measuring seconds, we can measure the number of simple operations the computer has to perform. &lt;/p&gt;

&lt;h3&gt;
  
  
  How do we do that?
&lt;/h3&gt;

&lt;p&gt;Big O is a way we can describe algorithms and compare them relatively. &lt;/p&gt;

&lt;p&gt;The most simple explanation I've heard is this:&lt;/p&gt;

&lt;p&gt;Big O allows us to talk about how the runtime of an algorithm grows as the inputs grow. In other words, we can compare the &lt;strong&gt;relative&lt;/strong&gt; growth rates of different algorithms. &lt;/p&gt;

&lt;p&gt;Common rates of increase are depicted in the graph 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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F7bs4myp0lsyjee8fbqeu.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F7bs4myp0lsyjee8fbqeu.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Examining this graph, we can see that the best rate of increase is no increase at all - O(1). Ha! Wonderful. &lt;/p&gt;

&lt;p&gt;This isn't always practical so we can use this graph as a visual of how the other rates compare. Given O(n) and O(n²) for example - as the number of inputs increase, O(n) increases linearly while O(n²) increases quadratically! Yikes! &lt;/p&gt;

&lt;h3&gt;
  
  
  3 Helpful Rules to Remember
&lt;/h3&gt;

&lt;h5&gt;
  
  
  1. Constants don't matter, drop them.
&lt;/h5&gt;

&lt;p&gt;O(5n) --&amp;gt; O(n)&lt;br&gt;
O(15) --&amp;gt; O(1)&lt;br&gt;
O(5n²) --&amp;gt; O(n²)&lt;/p&gt;

&lt;h5&gt;
  
  
  2. Smaller terms don't matter. Drop them.
&lt;/h5&gt;

&lt;p&gt;O(n + 5) --&amp;gt; O(n)&lt;br&gt;
O(10n + 25) --&amp;gt; O(n)&lt;br&gt;
O(5n² + 3n + 2) --&amp;gt; O(n²)&lt;/p&gt;

&lt;h5&gt;
  
  
  3. Two loops is always better then a nested loop.
&lt;/h5&gt;

&lt;p&gt;A good easy rule to follow when seeing a nested loop is to multiple by the number of nested loops to give you the Big O. &lt;/p&gt;

&lt;p&gt;For the below example of a simple nested loop, the Big O would be n * n = O(n²)&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fae6odlxqfw4ohxge3ghj.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fae6odlxqfw4ohxge3ghj.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While for two individual loops - Big O is O(n)&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fn7vk9zfxd5yimqeiw51t.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fn7vk9zfxd5yimqeiw51t.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy Coding, &lt;br&gt;
Michaella &lt;/p&gt;

&lt;h6&gt;
  
  
  Note: I've been using Big O in talking about time complexity - but there is also space complexity (how much memory we need in order to run an algorithm) which we can use Big O to compare as well. This is a different topic which I did not go into, but I highly encourage you to read about it as for the same algorithm, you can have different Big O's for time and space complexity!
&lt;/h6&gt;

&lt;p&gt;&lt;a href="https://courses.cs.washington.edu/courses/cse373/19sp/resources/math/asymptotic-analysis/" rel="noopener noreferrer"&gt;Graph Image Source&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F38j3437xaqyz60npblp2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F38j3437xaqyz60npblp2.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Home Grown Books - building a Single Page Application </title>
      <dc:creator>michaella latkovic</dc:creator>
      <pubDate>Fri, 25 Oct 2019 22:26:47 +0000</pubDate>
      <link>https://dev.to/michaellalatkovic/home-grown-books-building-a-single-page-application-4a22</link>
      <guid>https://dev.to/michaellalatkovic/home-grown-books-building-a-single-page-application-4a22</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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F9hr1mlfxklrpiitidir7.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F9hr1mlfxklrpiitidir7.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Home Grown Books is a Single Page Application (SPA) with a JavaScript frontend, a backend API built with Ruby and Rails,  and a PostgreSQL database.&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fv0tzrrt7213bna31a7py.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fv0tzrrt7213bna31a7py.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Starting this project, I wanted to keep it as simple as possible to give myself the focus to understand how all the pieces work together before jumping into a super complicated app! Users have the ability to add and delete books - as well as add reviews to books they have read.  &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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F8yo0mn248xfoz84l8m6g.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F8yo0mn248xfoz84l8m6g.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first thing I built was the backend - looking back, this was simple compared to what was coming in the frontend. &lt;/p&gt;

&lt;p&gt;For the backend architecture - I only have two models - Book and Reviews.&lt;/p&gt;

&lt;p&gt;Book has_many Reviews&lt;br&gt;
Reviews belong_to Book&lt;/p&gt;

&lt;p&gt;I created the necessary controller actions and serializers to display the json. I used the gem 'active_model_serializers' and added the associations between these two models so when I visited the index page on localhost:3000/books - you have all books and all associated reviews for each book. &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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ftea8m70vnutsq8l6jlto.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ftea8m70vnutsq8l6jlto.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the frontend, I built App, Books, Book, and BooksAdapter classes to organize the Javascript code. &lt;/p&gt;

&lt;p&gt;I built 4 AJAX calls covering 3 of the CRUD (CREATE, READ, UPDATE, DESTROY) actions summarized below:&lt;/p&gt;

&lt;p&gt;CREATE&lt;br&gt;
*Create a book&lt;br&gt;
*Create a new review&lt;/p&gt;

&lt;p&gt;READ&lt;br&gt;
*List all Books&lt;/p&gt;

&lt;p&gt;DELETE&lt;br&gt;
*Delete a book&lt;/p&gt;

&lt;h3&gt;
  
  
  Reflections
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Asynchronous JS + time&lt;/strong&gt;&lt;br&gt;
This project was a great learning experience - I went into this thinking it would only take a couple days. &lt;/p&gt;

&lt;p&gt;It is a &lt;em&gt;totally&lt;/em&gt; different experience when you are building projects from start to finish - I truly understand why EVERYONE says if you want to learn something, build something with it. &lt;/p&gt;

&lt;p&gt;I definitely struggled getting some of my fetch requests working correctly and ended up going  through code line by line investigating what is being console logged at each step. One thing I will definitely use more of on my next project are the devtools Chrome provides. I realied too heavily on just console.log when using breakpoints is so helpful!! &lt;/p&gt;

&lt;p&gt;This guide was super useful if anyone needs a refresher!&lt;br&gt;
&lt;a href="https://developers.google.com/web/tools/chrome-devtools/javascript/" rel="noopener noreferrer"&gt;https://developers.google.com/web/tools/chrome-devtools/javascript/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I can't believe I forgot about these... &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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fs659p721vh43hh8op5m7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fs659p721vh43hh8op5m7.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CSS&lt;/strong&gt; &lt;br&gt;
For the previous projects that I've built, I was a little intimidated by CSS. Since the focus of the projects wasn't on the frontend, I always used templates that I could tweak CSS slightly and it usually turned out OK. &lt;/p&gt;

&lt;p&gt;This time around, I wanted to build from scratch to really get comfortable with CSS and how it interacts with JS. &lt;/p&gt;

&lt;p&gt;I knew I wanted a grid layout of all the books so I &lt;em&gt;naively&lt;/em&gt; started building out divs and trying to get all the sizing to match up - this was not ideal. I learned from a fellow coder about the magic of flexbox. &lt;/p&gt;

&lt;p&gt;I researched the difference between CSS flexbox and CSS grid (flexbox is made for one dimensional layouts whereas grid is made for two dimensional layouts) and decided flexbox would suffice for my app needs. &lt;/p&gt;

&lt;p&gt;It took time, but it was definitely worth it! It can be easy to be overwhelmed with all the different properties you can assign - but it's actually kind of fun - and the best way to learn is simply testing it all out. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git commits - continued&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/michaellalatkovic/social-grads-my-first-rails-app-10p0"&gt;last blog&lt;/a&gt; that I wrote, I reflected on the importance of committing frequently and my troubles with not doing so initially. This time around, I am happy to report that I was much more thoughtful on the frequency and the thoughtfulness of the messages of my commits. Although, not yet perfected, and knowing this is still something to keep improving on with each project that I build -  I wanted to end on a good note - because even if we are always learning and improving - we need to celebrate our small wins. &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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F4aqjca6bltj3pk0q9ddz.jpeg" 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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F4aqjca6bltj3pk0q9ddz.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy Coding,&lt;br&gt;
Michaella&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Social Grads - my first Rails App. </title>
      <dc:creator>michaella latkovic</dc:creator>
      <pubDate>Fri, 02 Aug 2019 02:05:17 +0000</pubDate>
      <link>https://dev.to/michaellalatkovic/social-grads-my-first-rails-app-10p0</link>
      <guid>https://dev.to/michaellalatkovic/social-grads-my-first-rails-app-10p0</guid>
      <description>&lt;p&gt;The end is here! Well... at least the end of the Rails section of the &lt;a href="https://flatironschool.com"&gt;Learn.co&lt;/a&gt; Software Engineering curriculum.&lt;/p&gt;

&lt;p&gt;For the project, I created a web application called &lt;strong&gt;Social Grads&lt;/strong&gt; - a social tool for graduate school submissions. This app was inspired by the forum section of &lt;a href="https://forums.studentdoctor.net"&gt;The Student Doctor Network&lt;/a&gt; - if you have never been to this site, it's AMAZING.&lt;/p&gt;

&lt;p&gt;When I was applying to grad school myself, I spent &lt;strong&gt;MANY&lt;/strong&gt; hours reading anything and everything I could on this site. Two of my favorite (and super popular) forums are "The All-Encompassing, "What are my chances" thread!" and "Applied, Interviewed, Rejected, Attending" - the latter is truly what inspired me to create Social Grads. I know the pain of scrolling down to read every last post hoping to find any information on who is applying to what school, what their background is, and most importantly, did they get in?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jIS6qvZT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/6fbo7pkmf7i1id69rasi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jIS6qvZT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/6fbo7pkmf7i1id69rasi.png" alt="" width="880" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Social Grads takes this forum and creates a tool where users can create an account and add their information to a user profile. Users can sign up for a new account or login via GutHub.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3GDTXvkZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/vo5b5t7ivgdwz08wu14o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3GDTXvkZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/vo5b5t7ivgdwz08wu14o.png" alt="" width="880" height="666"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wO88no6n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/iq3v21n5fgo3t0mly6rf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wO88no6n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/iq3v21n5fgo3t0mly6rf.png" alt="" width="880" height="577"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once logged in, they can add submissions for each program they are applying to as show below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fALeIijd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/l78xywzb7b4e1w0vfk5z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fALeIijd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/l78xywzb7b4e1w0vfk5z.png" alt="" width="880" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not only is this an easy way to keep track of all the programs you are applying to, you can also easily search the site for other users - look at their profiles, see the submissions they have created and even look at college profiles with a summary of all the submissions by the Social Grads community who have active submissions at that school.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reflections
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;User experience &amp;amp; urls&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I added my nested routes after I had already done a fair amount of work on the rest of my app and view pages. When I was reviewing my application I noticed that while my app was redirecting to the correct views, my urls didn't always follow a consistent path that would make sense to a user as they are navigating the application. Essentially, the application was functioning correctly but would likely cause confusion once deployed in the real world. This exercise highlighted that it is critical to not get lost in thinking about our applications from the developers point of view - but to always remember to think about the design from the user's perspective.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Focus on MVP&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A challenge I saw myself falling into was getting overwhelmed with all the features I could add or wanted to add. I would spend time thinking through everything to realize a few hours passed and I hadn't added a single feature. I learned that it is better to hit that MVP to meet the requirements of the project even if there is a lot more potential. To keep momentum through this journey, I need to focus myself and know that I can always continue to build on this project later as well. This is something I will have to remember when it's time to build the final project for this program.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Commit F.R.E.Q.U.E.N.T.L.Y&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One of the biggest lessons this project has taught me is to be more thoughtful and  frequent with my commits. I used to commit features as a package (login, logout, new, edit etc...)&lt;/p&gt;

&lt;p&gt;This method worked for a while - it was neat and clean. If I wanted to see all code that went with adding a feature, I had it all in that single commit. However, this is not the best use case for commits.&lt;/p&gt;

&lt;p&gt;Two-thirds into this project, my master branch and my local directory somehow didn't align. I still had code that hadn't been pushed up because I was waiting to finish a feature. After much debugging (git stash, git pull, git rebase....) with the help of my instructors, the only thing that worked was:&lt;/p&gt;

&lt;p&gt;git add .&lt;br&gt;
git commit -m 'Please work.'&lt;br&gt;
push --force&lt;/p&gt;

&lt;p&gt;I forced all my code in one commit  - luckily, this fixed my merge conflict but I lost some code.&lt;/p&gt;

&lt;p&gt;Lesson learned. Commit frequently, even if it is a single addition of a link to a view page. You will thank yourself later!&lt;/p&gt;

&lt;p&gt;Happy Coding,&lt;br&gt;
Michaella&lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>webdev</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Sinatra Project: Fresh Bites</title>
      <dc:creator>michaella latkovic</dc:creator>
      <pubDate>Wed, 19 Jun 2019 01:29:53 +0000</pubDate>
      <link>https://dev.to/michaellalatkovic/sinatra-project-fresh-bites-3hb6</link>
      <guid>https://dev.to/michaellalatkovic/sinatra-project-fresh-bites-3hb6</guid>
      <description>&lt;p&gt;For the final assessment in the Sinatra section of the &lt;a href="https://flatironschool.com"&gt;Learn.co&lt;/a&gt; Software Engineering curriculum— the task was to create a CRUD, MVC app using Sinatra.&lt;/p&gt;

&lt;p&gt;I created a simple demo web application called &lt;strong&gt;Fresh Bites&lt;/strong&gt; to practice using all the skills and tools I’ve learned so far. What is Fresh Bites you may ask?&lt;/p&gt;

&lt;p&gt;Fresh Bites allows users to create an account to manage recipes for their furry best friends. Basically, I just wanted an excuse to use dog stock photos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9ems4RPH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/jos0ic48p87fzby5nxp1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9ems4RPH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/jos0ic48p87fzby5nxp1.png" alt="" width="880" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are looking to create a simple web app fast — here are the steps I took to get from concept to functional application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 : Model Relationships
&lt;/h3&gt;

&lt;p&gt;There were some benchmark specifications that were required as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Include more than one model class&lt;/li&gt;
&lt;li&gt;Include at least one has_many relationship on your User model&lt;/li&gt;
&lt;li&gt;Include at least one belongs_to relationship on another model&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I found it to helpful to draw out my relationships first — before even opening up my terminal to start building anything.&lt;/p&gt;

&lt;p&gt;I knew I wanted a User model and Recipe Model to start with. I decided it would be a nice addition to add a Category Model which meant I needed to add a fourth and final Recipe_category Model as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xyzosZEg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/e7pus6far2dudai4zl6v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xyzosZEg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/e7pus6far2dudai4zl6v.png" alt="" width="831" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Corneal Template
&lt;/h3&gt;

&lt;p&gt;I used the &lt;a href="https://github.com/thebrianemory/corneal"&gt;Corneal&lt;/a&gt; Ruby gem to lay out my basic app structure. Not only did this save time, it was pretty comprehensive as well! I definitely recommend trying it out!&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Database Migrations
&lt;/h3&gt;

&lt;p&gt;With the help of ActiveRecord, I created database migrations for each of my models…I did relaize I forgot to add a user_id column to my recipes table which added one last migration. Luckily, using a few gems (activerecord, sinatra-activerecord, and rake), it is super easy to do all of this. To learn more about how these gems work to set up ActiveRecord to add a database to Sinatra applications — check out &lt;a href="https://learn.co/lessons/sinatra-activerecord-setup"&gt;this post&lt;/a&gt; which I found super helpful.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uZpZaGVT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/yhjvijkxb3dv97ccrdih.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uZpZaGVT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/yhjvijkxb3dv97ccrdih.png" alt="" width="533" height="145"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Snapshot of final set of database migrations
&lt;/h6&gt;

&lt;h3&gt;
  
  
  Step 4: Model — View — Controller (MVC)
&lt;/h3&gt;

&lt;p&gt;With the basic template already created with the Corneal gem — I went deeper with the MVC architectural pattern:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9ihIbRv4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/i0frw1vqishpz7akx1r8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9ihIbRv4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/i0frw1vqishpz7akx1r8.png" alt="" width="364" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Snapshot of final MVC file structure
&lt;/h6&gt;

&lt;h4&gt;
  
  
  Creating my Models
&lt;/h4&gt;

&lt;p&gt;Having already drawn out my model relationships, this was a a pretty simple task. I created my four models (User, Recipe, Category, and Recipe_category) all inheriting from Active Record. If you want to learn more about the details of how to do this — and quite frankly all that comes after — I highly recommend &lt;a href="https://guides.rubyonrails.org/active_record_basics.html"&gt;this guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It’s awesome, I advise to stop reading this and just go there 😊&lt;/p&gt;

&lt;h4&gt;
  
  
  Creating my Views
&lt;/h4&gt;

&lt;p&gt;User — signup, login, index, and show view pages.&lt;br&gt;
Recipe — index, show, new, and edit view pages.&lt;br&gt;
Categories — only needed an index and show views.&lt;/p&gt;

&lt;p&gt;In addition, I created a welcome and a logout view page.&lt;/p&gt;

&lt;p&gt;FYI: The layout.erb file holds all of my styling to keep a consistent feel for all my pages. I used the &lt;a href="https://learn.co/lessons/sinatra-yield-readme"&gt;yield statement&lt;/a&gt; in the layout.erb file where I wanted other view page content to be loaded.&lt;/p&gt;

&lt;h4&gt;
  
  
  Creating my Controllers
&lt;/h4&gt;

&lt;p&gt;This is where we build out CRUD (Create, Read, Update, Delete) functionality.&lt;/p&gt;

&lt;p&gt;I’ve summarized what controller actions I included in my application. I used &lt;a href="https://learn.co/lessons/sinatra-restful-routes-readme"&gt;this post&lt;/a&gt; as my guide for how to implement RESTful routes. If you are interested in the code, I’ve added a link to the GitHub repo at the end of this blog!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;application_controller&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;route to my welcome page &amp;amp; a few helper methods&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;users_controller&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;index action (display all users) and show action (display a single user)&lt;/li&gt;
&lt;li&gt;get request to display signup page and post request create a new user account&lt;/li&gt;
&lt;li&gt;get request to display login page and post request to log into an existing account&lt;/li&gt;
&lt;li&gt;get request to logout&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;recipes_controller&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;index action (display all recipes) and show action (display a single recipe)&lt;/li&gt;
&lt;li&gt;new action to display new recipe form and create action to create a new recipe&lt;/li&gt;
&lt;li&gt;edit action to display an edit recipe form and update action to update the recipe&lt;/li&gt;
&lt;li&gt;delete action to delete a recipe&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;categories_controller&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;index action (display all categories) and show action (display a single category)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I listed the above in order of “MVC”, however, I prefer to write out Models, Controllers, then Views… or even more realistically Models, then alternate between Controllers and Views — as you create RESTful routes in the controller, creating corresponding views (erb files) and then testing it out to make sure it works.&lt;/p&gt;

&lt;p&gt;There is a lot more that went into programming (&lt;em&gt;debugging really&lt;/em&gt;) all the functionality and front-end design of the application but these are the steps I took in the beginning to at least get to a point where I have an application that was running!&lt;/p&gt;

&lt;p&gt;If you are interested in the looking at the complete code — feel free to checkout the &lt;a href="https://github.com/mvlt18/sinatra-project"&gt;GitHub repo&lt;/a&gt;!&lt;/p&gt;

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