<?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: Levi</title>
    <description>The latest articles on DEV Community by Levi (@levi).</description>
    <link>https://dev.to/levi</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%2F223212%2F00f6a6f6-5b61-4b85-b2e2-effd717f1281.jpeg</url>
      <title>DEV Community: Levi</title>
      <link>https://dev.to/levi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/levi"/>
    <language>en</language>
    <item>
      <title>A Simple Git Branch Workflow</title>
      <dc:creator>Levi</dc:creator>
      <pubDate>Sat, 04 Jan 2020 23:01:41 +0000</pubDate>
      <link>https://dev.to/levi/a-simple-git-branch-workflow-24hh</link>
      <guid>https://dev.to/levi/a-simple-git-branch-workflow-24hh</guid>
      <description>&lt;h2&gt;
  
  
  Why?
&lt;/h2&gt;

&lt;p&gt;Git is the preeminent tool for version control–that is, keeping track of and managing changes. This post is about implementing a simple but powerful workflow for managing and tracking the changes of a project as it grows and matures. A branching workflow allows us to carefully make and track changes to our project without risking the integrity of its core.&lt;/p&gt;

&lt;p&gt;Version control gives us a better handle on the animal of our code base. Every project warrants a repository, an observed and organized container for code. If you're serious about grooming a project that lasts, you owe it to yourself to use Git. For the purposes of this illustration, we'll use Github as the example of an online host for Git.&lt;/p&gt;

&lt;h2&gt;
  
  
  How
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Getting Started
&lt;/h3&gt;

&lt;p&gt;New projects must be started either locally or with a new repository on Github. This new repository may be either initialized with files or linked with an existing local directory. Mind the checkbox labelled "Initialize with a README" when creating a new repository (here on out referred to as a &lt;strong&gt;repo&lt;/strong&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%2Fyqaw3s7k8qjf968vq0lk.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%2Fyqaw3s7k8qjf968vq0lk.png" alt="Mind this checkbox"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have already started a project on your computer you will be "importing an existing repository," so take Github's advice and do &lt;em&gt;not&lt;/em&gt; check this box. Checking the box will make it more complicated to link your local directory with the remote repo. Instead, "push [this] existing repository on the command line" by opening a terminal window, moving into the project's directory, and executing the following three lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git init
$ git remote add origin git@github.com:USERNAME/REPO-NAME.git
$ git push -u origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;git init&lt;/code&gt; initializes the local directory as a new, empty git repo (&lt;code&gt;$&lt;/code&gt; denotes that we're executing this command in the terminal). This command generates an invisible &lt;code&gt;.git&lt;/code&gt; file and endows the directory space with all the powers that Git affords. &lt;code&gt;git remote add&lt;/code&gt; adds a remote (i.e. server) of the name &lt;code&gt;origin&lt;/code&gt; at the address &lt;code&gt;git@github.com:USERNAME/REPO-NAME.git&lt;/code&gt;. This command links the local repository to a server that will also host the repository. &lt;code&gt;git push -u origin master&lt;/code&gt; pushes, or uploads, the contents in the master branch of the directory to the origin server. &lt;code&gt;-u&lt;/code&gt; sets this remote repository as the default upstream reference, meaning &lt;code&gt;origin&lt;/code&gt; will be the default remote repository from which things are pulled and to which things are pushed.&lt;/p&gt;

&lt;p&gt;If you're starting your project from scratch and have no local work, feel free to check the box and have the resulting generated README.md serve as your first project file!&lt;/p&gt;

&lt;p&gt;Below is an illustration of the state of our project. The shapes with dashed borders represent the project on the remote repository, while the solid-bordered shapes represent the local project. Each circle is a commit. A huge thanks to the &lt;a href="https://learngitbranching.js.org/" rel="noopener noreferrer"&gt;Learn Git Branching Applet&lt;/a&gt; for providing a means of simulating and visualizing Git workflows. We'll use these diagrams to grasp what we're doing.&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%2Fqgkytb8guots0ogsia6q.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%2Fqgkytb8guots0ogsia6q.png" alt="Local synced with remote, two commits"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the image above, our local repo is synced with the remote repo–both have two commits. The boxes pointing at the commits point to the where (or, more accurately, when) in the project a branch is. Here, the master branch is at the latest commit, C2. The &lt;strong&gt;head&lt;/strong&gt; is denoted by the asterisk (*) indicates where in a project's history we are working. Most often, the head points to the latest checkpoint, like a tape recorder &lt;em&gt;head&lt;/em&gt; might rest on the freshest spot of tape, or a record player needle might point to the most recent song.&lt;/p&gt;

&lt;h3&gt;
  
  
  Saving Progress
&lt;/h3&gt;

&lt;p&gt;In plain English, let's talk about the meat and and potatoes of a Git workflow: staging, committing, and pushing. These actions are essential to saving changes to your work. You should do them every time you make a substantial change. &lt;/p&gt;

&lt;p&gt;To &lt;strong&gt;stage&lt;/strong&gt;, we execute &lt;code&gt;git add&lt;/code&gt; in our project's directory. Innocuous enough! &lt;code&gt;git add .&lt;/code&gt; and &lt;code&gt;git add FILE.js&lt;/code&gt; will &lt;strong&gt;stage&lt;/strong&gt; &lt;em&gt;all&lt;/em&gt; files in the directory or &lt;em&gt;only&lt;/em&gt; the &lt;code&gt;FILE.js&lt;/code&gt; file, respectively. By &lt;strong&gt;stage&lt;/strong&gt;, we mean &lt;em&gt;tell Git we want to track the changes made to these files&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;To &lt;strong&gt;commit&lt;/strong&gt;, we execute &lt;code&gt;git commit -m "COMMIT MESSAGE&lt;/code&gt; to record the changes made to staged files in our project's git history. Committing is roughly the same thing as saving, though the only thing we're saving is the &lt;em&gt;changes&lt;/em&gt; to the files, not the files themselves. See &lt;a href="https://dev.to/jacobherrington/how-to-write-useful-commit-messages-my-commit-message-template-20n9"&gt;How to Write Useful Commit Messages&lt;/a&gt; for advice on how to do just that. The following illustration shows the state of our project after the previous two commands. Our local project repo is ahead of the remote by one commit!&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%2F5xbbvgkvxou5336d29c8.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%2F5xbbvgkvxou5336d29c8.png" alt="New local commit"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To &lt;strong&gt;push&lt;/strong&gt;, we execute &lt;code&gt;git push&lt;/code&gt;. By default, this command will upload our code in its current branch to a server (known as the &lt;em&gt;remote&lt;/em&gt; in Git parlance and named &lt;code&gt;origin&lt;/code&gt; by default). We can specify which branch to push by passing it in as an option like so : &lt;code&gt;git push REMOTE_NAME BRANCH_NAME&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Frd0o2oq2s3tczod8vfwb.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%2Frd0o2oq2s3tczod8vfwb.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now our local and remote repos are in sync! With &lt;code&gt;add&lt;/code&gt;, &lt;code&gt;commit&lt;/code&gt;, and &lt;code&gt;push&lt;/code&gt; at our disposal, we're equipped to track changes to our project. Lugging this verbiage around begs the question, &lt;em&gt;"When will we ever need this?"&lt;/em&gt; Commit &lt;em&gt;every&lt;/em&gt; substantial change to your work. Commit! Set up your sessions controller?  Implementing authorization and just amended your user model? Commit! Fix a bug? Commit!&lt;/p&gt;

&lt;p&gt;Stage and commit every little milestone of your work. When you finish a work session, or as needed, push these changes so they're accessible to others. In short (and for example):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;git add .&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git commit -m "Refactor custom Account model methods"&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git push&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Damage Control with Branches
&lt;/h3&gt;

&lt;p&gt;Many are tempted to work exclusively in the &lt;code&gt;master&lt;/code&gt; branch. This behavior would be akin to me writing this blog post in pen longhand, while sitting at a rolling desk on a rocking boat yelling, "I make no mistakes!" Consider the &lt;code&gt;master&lt;/code&gt; branch to be your &lt;code&gt;final draft&lt;/code&gt; branch, the public face of your project. As we work on our projects, the &lt;code&gt;master&lt;/code&gt; branch will be where our changes come home to rest, but those changes will first be conceived and nurtured in their own branches before being merged.&lt;/p&gt;

&lt;p&gt;A branch of a Git project is a parallel universe. When we create a branch, we are able to make changes to our project as it existed in the moment we branched while protecting the &lt;code&gt;master&lt;/code&gt; branch from new, more volatile code. &lt;/p&gt;

&lt;p&gt;Before you go about turning your dreams into reality, consider giving spirit form by identifying the distinct building blocks of your project. A web application, for example, often adheres to a Model-View-Controller architecture, with separate models, controllers, and views for different aspects of the application. As we work on our project with Git, it behooves us to create new branches for each model, controller, and view as they're implemented. Further on down the road, we may create branches for new features or bug fixes.&lt;/p&gt;

&lt;p&gt;Branching in Git is as simple as &lt;code&gt;git branch BRANCH_NAME&lt;/code&gt;. This command creates a new branch. To work in that branch, we need to check it out, like we would a book at the library. &lt;code&gt;git checkout BRANCH_NAME&lt;/code&gt; does the trick. Since we're lucky enough to be working in a field where laziness is a virtue, we can abridge this process. &lt;code&gt;git checkout -b BRANCH_NAME&lt;/code&gt; will both create and checkout a branch.&lt;/p&gt;

&lt;p&gt;Once we've created a branch, we can save our progress with &lt;code&gt;add&lt;/code&gt; and &lt;code&gt;commit&lt;/code&gt; as usual. Remember that executing &lt;code&gt;git push&lt;/code&gt; will upload our project as it exists in the last commit in the current branch. The diagram below shows the state of our project after doing all of the above. Note the location of the asterisk! It is on &lt;em&gt;account-m&lt;/em&gt; on account of us being in that particular branch.&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%2Fx38e8dyyccaxcrk3wd47.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%2Fx38e8dyyccaxcrk3wd47.png" alt="Creating a new branch, committing and pushing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The image above shows the &lt;code&gt;master&lt;/code&gt; branch pointing to an earlier commit than the &lt;code&gt;account-m&lt;/code&gt; branch. Since we've committed in &lt;code&gt;account-m&lt;/code&gt;, &lt;code&gt;master&lt;/code&gt; is behind! When the purpose of a feature branch has been fulfilled and its quality is satisfactory, it's time to &lt;strong&gt;merge&lt;/strong&gt; that branch back into the &lt;code&gt;master&lt;/code&gt; branch. Intuitively enough, we accomplish this feat with &lt;code&gt;git merge&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;First, we checkout the master branch, then we execute &lt;code&gt;git merge BRANCH_NAME&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F7odwx9sa24dxxib7jxki.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%2F7odwx9sa24dxxib7jxki.png" alt="Checking out the master branch"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice the location of the asterisk! We're now in the master branch. Now merge the &lt;code&gt;account-model&lt;/code&gt; branch and push our changes to remote.&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%2Fljwc5n51dufc9sab9lig.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%2Fljwc5n51dufc9sab9lig.png" alt="Checking out the master branch, merging the other branch, and pushing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In short, we've accomplished the following...:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;$ git checkout -b account-model&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A half-hour of thought and toil passes...&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$ git add .&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$ git commit -m "Create basic Account migration and model"&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$ git checkout master&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$ git merge account-model&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Putting It All Together
&lt;/h3&gt;

&lt;p&gt;We now know how to save our progress and to create progress in a safe place before making it a lasting part of our project. Now let's look at how this workflow plays with others.&lt;/p&gt;

&lt;p&gt;Say we're working with someone else on this project. They are going to, say, flesh out the controller for the accounts model we created previously. They go off, clone (aka download) our repository, work, faithfully commit, and push their changes to remote. If we want to see their work on &lt;em&gt;our&lt;/em&gt; machine, we need to &lt;strong&gt;pull&lt;/strong&gt; what is on the remote, with &lt;code&gt;git pull&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fbho0ukc57vuc63pm2z8d.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%2Fbho0ukc57vuc63pm2z8d.png" alt="Pulling a partner's woork"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that the asterisk is on the master branch, two commits behind our colleague's branch. Our colleague isn't quite done yet, so we decide to work on a separate feature on a separate branch. We do so, and make a couple commits' worth of progress.&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%2Ftl41kb49mhbhungntgzo.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%2Ftl41kb49mhbhungntgzo.png" alt="Making our own progress"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the meantime, our colleague finished and pushed their last commit for their branch. We promptly pull it to stay abreast.&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%2Fuyuth572i203iq7bnncd.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%2Fuyuth572i203iq7bnncd.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We finish with our work, and decide it's time to put everything together, merging and (of course!) pushing the result to the remote so our team can work from it.&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%2Fb6tyu5wxl32gsncn0xt1.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%2Fb6tyu5wxl32gsncn0xt1.png" alt="Merging everyone's work"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This process is the basic unit of a Git branching workflow. Each member of a team project works on a branch appropriate to a particular feature, component, or variation of the project. Commits are made and pushed with every milestone. When a particular branch has served its purpose and is ready for the big time, it is merged into the master branch. And on and on it goes!&lt;/p&gt;

&lt;h2&gt;
  
  
  Resolving Conflicts
&lt;/h2&gt;

&lt;p&gt;Invariably, you will run into conflicts. Resolving them is beyond the scope of this blog post, but here are a tip for avoiding them and resources for dealing with them.&lt;/p&gt;

&lt;p&gt;To avoid merge conflicts, each branch has contain changes that only pertain to separate files. If the branches being merged both have variations of the same file, it'll be time to resolve conflict.&lt;/p&gt;

&lt;p&gt;Resolving merge conflicts is far from terrible! &lt;a href="https://code.visualstudio.com/docs/editor/versioncontrol#_merge-conflicts" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt;, &lt;a href="https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/resolving-a-merge-conflict-on-github" rel="noopener noreferrer"&gt;Github&lt;/a&gt; (if you're making pull requests on the repo instead of locally merging), and even your native terminal provide tools for editing and resolving differences between conflicting files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Now What?
&lt;/h2&gt;

&lt;p&gt;Many of us, when we first start learning Git, do so just out of the demands of interfacing with others through our job or the Internet. Maybe we want to host our projects on Github and share our work with the world! Maybe we can only take a crack at someone else's work by accessing it through Bitbucket.&lt;/p&gt;

&lt;p&gt;Strictly speaking, you don't have to be plugged in to the Web to use Git. Whether we're working alone, in pairs, or in a small group, a couple of guidelines and handful of Git commands will enhance our ability to organize, collaborate, and more fully realize the vision of our projects. Whatever software you start or contribute to, and even if you're working alone, take care to employ Git with best practices so you reap the rewards of a well-managed project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources and References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/docs" rel="noopener noreferrer"&gt;git Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.atlassian.com/git/tutorials/saving-changes" rel="noopener noreferrer"&gt;Atlassian: Saving Changes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learngitbranching.js.org/" rel="noopener noreferrer"&gt;Learn Git Branching Applet&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>git</category>
      <category>productivity</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Authentication and Authorization à la Rails bcrypt</title>
      <dc:creator>Levi</dc:creator>
      <pubDate>Fri, 06 Dec 2019 00:21:10 +0000</pubDate>
      <link>https://dev.to/levi/authentication-and-authorization-a-la-rails-bcrypt-1kn0</link>
      <guid>https://dev.to/levi/authentication-and-authorization-a-la-rails-bcrypt-1kn0</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;User accounts are an indispensable feature of web applications. They allow us to create persistent, tailored experiences for the people using our site. They also help us better track how our application is used. Despite their usefulness, implementing user accounts can be akin to opening Pandora's box of troubles.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--43l5QA0X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/q4levi8nzn2fvp09z79e.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--43l5QA0X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/q4levi8nzn2fvp09z79e.jpg" alt="Pandora's Box"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We live in an age of savvy sackers of digital domains. While we've opened a box of possibilities, they've brought a host of problems with them! How do we stand a chance? We lean on others' work and trade configuration for convention. But before we find some shoulders to stand on, let's get a sense of the problem we're trying to solve.&lt;/p&gt;

&lt;h1&gt;
  
  
  Signing Up And Signing In
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Signing Up&lt;/strong&gt; and &lt;strong&gt;Signing In&lt;/strong&gt; are actions with which we are all familiar. They allow web applications to &lt;em&gt;authenticate&lt;/em&gt; and &lt;em&gt;authorize&lt;/em&gt; their users.&lt;/p&gt;

&lt;p&gt;When we &lt;strong&gt;Sign Up&lt;/strong&gt;, we create a means by which a web application determines that we are who we say we are. Signing Up happens once in the lifetime of a user in an application. It creates a new user instance in the backend of the server with information that can be use to &lt;em&gt;authenticate&lt;/em&gt; that user. Authentication asks the question, "Are you who you say you are?" When we sign in, we are authenticated by the application based on the username and password we provide, and consequently given access to different features of the application. &lt;/p&gt;

&lt;p&gt;We are engaged in &lt;em&gt;single-factor authentication&lt;/em&gt; when we only have to provide one type of information to authenticate ourselves.  As you might imagine, single-factor authentication is not the best means of securing user accounts, as anyone with a username and password can access an account. That's where &lt;a href="https://en.wikipedia.org/wiki/Multi-factor_authentication"&gt;multi-factor&lt;/a&gt; authentication comes into play. We encounter multi-factor authentication pretty well every day, when a site asks us to enter a randomly generated code sent to our phones in addition to our username and password, or when an ATM machine requires us to enter a PIN number and insert our debit card. We won't build multi-factor authentication in this post, but it's important to be aware of.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PPBWVx8y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/gh3ipgqqyxyhvkhyss0w.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PPBWVx8y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/gh3ipgqqyxyhvkhyss0w.jpg" alt="Adam Being Authenticated"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once we're signed in and authenticated by an application, it will check to see if we are &lt;em&gt;authorized&lt;/em&gt; to perform the actions we attempt to perform. Authorization asks the question, "Are you allowed to do that?" The means by which a web application authorizes a user is through cookies, specifically, session cookies.&lt;/p&gt;

&lt;p&gt;A cookie is a bit of data stored on a user's browser. Web applications can store all kinds of information in cookies to track a user's state and history. A session cookie is a cookie that lasts for the duration of a session on a web application, typically from sign/log in to sign/log out. &lt;/p&gt;

&lt;p&gt;When a user signs in, the user's browser is given a cookie by the web application identifying that user. The authorization of the user can then be checked when HTTP requests are made of the application.&lt;/p&gt;

&lt;p&gt;Signing up happens once in the lifetime of user on a web application. It gives the application a means of authenticating the user, or checking to see that they are who they say they are, through a username, password, and any other required information. When a user signs in, they are authenticated and given an identifying session cookie. As the user interacts with the application, the application can check to see that the user is authorized, or permitted, to perform an action by referencing the user's cookie.&lt;/p&gt;

&lt;h1&gt;
  
  
  Authentication with bcrypt
&lt;/h1&gt;

&lt;p&gt;Authentication is a web application's way of checking to see that a user is who they say they are. There are several Ruby gems already written to facilitate this process. &lt;a href="https://github.com/plataformatec/devise"&gt;devise&lt;/a&gt; is one of the most popular, along with &lt;a href="https://github.com/omniauth/omniauth"&gt;omniauth&lt;/a&gt; and &lt;a href="https://github.com/doorkeeper-gem/doorkeeper"&gt;doorkeeper&lt;/a&gt;. We're not going to use any of those! For the purposes of understanding the process of authentication and authorization, we'll be using a gem that's been staring you in the face since you first opened a Rails Gemfile: &lt;a href="https://github.com/codahale/bcrypt-ruby"&gt;bcrypt&lt;/a&gt;. Uncomment that guy!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="s1"&gt;'https://rubygems.org'&lt;/span&gt;
&lt;span class="n"&gt;git_source&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:github&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="s2"&gt;"https://github.com/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.git"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# ruby '2.5.1'&lt;/span&gt;

&lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="c1"&gt;# Use Redis adapter to run Action Cable in production&lt;/span&gt;
&lt;span class="c1"&gt;# gem 'redis', '~&amp;gt; 4.0'&lt;/span&gt;
&lt;span class="c1"&gt;# Use ActiveModel has_secure_password&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'bcrypt'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'~&amp;gt; 3.1.7'&lt;/span&gt;

&lt;span class="c1"&gt;# Use ActiveStorage variant&lt;/span&gt;
&lt;span class="c1"&gt;# gem 'mini_magick', '~&amp;gt; 4.8'&lt;/span&gt;

&lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;bcrypt&lt;/code&gt; the Ruby gem is based on bcrypt the OpenBSD hashing algorithm. Given any string, such as a password, the hash will scramble the string along with a dash of random characters (known as salt) in such a way that the process cannot be reversed or guessed. &lt;code&gt;bcrypt&lt;/code&gt; the Ruby gem allows us to use the bcrypt algorithm to hash passwords, and it also manages storing the salt used in hashing so that we can later authenticate our users.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;pw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;BCrypt&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'P4ssW02d!'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; "$2a$12$YNW0EG8VwLmy1l9yxMeyAOaen/Yhx7LTBJR6G7jnG2WMkr9fo7aO6"&lt;/span&gt;

&lt;span class="n"&gt;pw&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'P4ssW02d!'&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There is a lot that &lt;code&gt;bcrypt&lt;/code&gt; doesn't do for us. We need to alter our user database table, model, controller, and views to make use of &lt;code&gt;bcrypt&lt;/code&gt;'s functionality.&lt;/p&gt;

&lt;h2&gt;
  
  
  bcrypt and the User Model
&lt;/h2&gt;

&lt;p&gt;In order to use &lt;code&gt;bcrypt&lt;/code&gt;, our user table must have a &lt;code&gt;password_digest&lt;/code&gt; attribute. In your Rails projects, you might execute the following: &lt;code&gt;rails generate resource User username password_digest&lt;/code&gt;. After migrating the table, we should have a schema similar to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="s2"&gt;"users"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;force: :cascade&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"username"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"password_digest"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note that we're storing a password digest, not a password. Never, ever, for any reason, whatsoever, even if your mother asks you too, even if you think it will cure your foot fungus, &lt;em&gt;&lt;strong&gt;never store passwords in plain text.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We must also add &lt;code&gt;has_secure_password&lt;/code&gt; to our User model. You'll notice that I've added some validations to ensure our users are created with a unique username and non-unique password. &lt;em&gt;Do not&lt;/em&gt; require unique passwords, as it will give ne'er-do-wells the information and confidence they need to gain access to user accounts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;has_secure_password&lt;/span&gt;
  &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;presence: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;uniqueness: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
  &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;presence: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;has_secure_password&lt;/code&gt; is a helper method for models that gives them access to methods which will aid in authentication. We can test them in &lt;code&gt;rails console&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;usr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;username: &lt;/span&gt;&lt;span class="s2"&gt;"cheetochester"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;password: &lt;/span&gt;&lt;span class="s2"&gt;"Ch33zy$"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;password_confirmation: &lt;/span&gt;&lt;span class="s2"&gt;"Ch33zy$"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; #&amp;lt;User id: 4, username: "cheetochester", password_digest: "$2a$12$Io.kXzHPXoGZYzuWBawSFOawjvGNmsrHsCiXbNhlYep..." ...&amp;gt;&lt;/span&gt;

&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"cheesys"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; false&lt;/span&gt;

&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Ch33zy$"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; #&amp;lt;User id: 4, username: "cheetochester", password_digest: "$2a$12$Io.kXzHPXoGZYzuWBawSFOawjvGNmsrHsCiXbNhlYep..." ...&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note that when we create a new user, we do so with the &lt;code&gt;password&lt;/code&gt; and &lt;code&gt;password_confirmation&lt;/code&gt; keys, not &lt;code&gt;password_digest&lt;/code&gt;. &lt;code&gt;bcrypt&lt;/code&gt; handles validating &lt;code&gt;password&lt;/code&gt; and &lt;code&gt;password_confirmation&lt;/code&gt; and converting &lt;code&gt;password&lt;/code&gt; into the &lt;code&gt;password_digest&lt;/code&gt; that is saved in the database. Given a password string, the &lt;code&gt;#authenticate&lt;/code&gt; method returns false if the password is incorrect, and the user instance if the password is correct.&lt;/p&gt;

&lt;h2&gt;
  
  
  Routes
&lt;/h2&gt;

&lt;p&gt;Before we can confidently set up our controllers, we must have a clear vision of our routes. In this basic example application, users can create and view their accounts. They can also sign in and out of their accounts. We will manage this functionality with the following routes in &lt;code&gt;rails-app/config/routes.rb&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;draw&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:create&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:show&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"/signup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"users#new"&lt;/span&gt;
  &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"/login"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"sessions#new"&lt;/span&gt;
  &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="s2"&gt;"/sessions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"sessions#create"&lt;/span&gt;
  &lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="s2"&gt;"/sessions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"sessions#destroy"&lt;/span&gt;
  &lt;span class="c1"&gt;# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating a Sign Up Form
&lt;/h2&gt;

&lt;p&gt;The code excerpt below depicts a basic User controller. We have supported actions for creating a user and seeing their page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsersController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;
    &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
    &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;valid?&lt;/span&gt;
      &lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;
      &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="vi"&gt;@user&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;  
      &lt;span class="n"&gt;redirect&lt;/span&gt; &lt;span class="ss"&gt;:new&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;
    &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="kp"&gt;private&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;user_params&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;permit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:password_confirmation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There is no special sauce for creating a sign up form. We simply need a form that will pass &lt;code&gt;username&lt;/code&gt;, &lt;code&gt;password&lt;/code&gt;, and &lt;code&gt;password_confirmation&lt;/code&gt; to our application. In &lt;code&gt;rails-app/app/views/users/new.html.erb&lt;/code&gt; we can generate a form with Rails form helpers like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form_for&lt;/span&gt; &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;label&lt;/span&gt; &lt;span class="ss"&gt;:username&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text_field&lt;/span&gt; &lt;span class="ss"&gt;:username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s2"&gt;"Username"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;label&lt;/span&gt; &lt;span class="ss"&gt;:password&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;password_field&lt;/span&gt; &lt;span class="ss"&gt;:password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s2"&gt;"Password"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;label&lt;/span&gt; &lt;span class="ss"&gt;:password_confirmation&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;password_field&lt;/span&gt; &lt;span class="ss"&gt;:password_confirmation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s2"&gt;"Confirm Password"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;submit&lt;/span&gt; &lt;span class="s2"&gt;"Create Account"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;On submission, our &lt;code&gt;UsersController#create&lt;/code&gt; action will attempt to create a new user instance with those parameters. If the user instance is valid, the user will be redirected to their show page. Otherwise, the user will be redirected to the new user page.&lt;/p&gt;

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

&lt;p&gt;Now that we have handled signing up a user, let's tackle signing them in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Logging In
&lt;/h2&gt;

&lt;p&gt;Logging in, or signing in, will be handled through Rails' &lt;code&gt;session&lt;/code&gt; hash, which reads and manages a session cookie on a user's browser. Managing &lt;code&gt;session&lt;/code&gt; requires enough unique actions to warrant another controller. We'll call this controller the &lt;code&gt;SessionsController&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SessionsController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
    &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;username: &lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:username&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:password&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
      &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;
      &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="vi"&gt;@user&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;  
      &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;login_path&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In this controller we've defined two actions. &lt;code&gt;SessionsController#new&lt;/code&gt; is simply responsible for rendering a page that enables a user to create a new session (also known as log in). The contents of &lt;code&gt;rails-app/app/views/sessions/new.html.erb&lt;/code&gt; maybe as simple as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form_tag&lt;/span&gt; &lt;span class="n"&gt;sessions_path&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;label_tag&lt;/span&gt; &lt;span class="s2"&gt;"Username"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;text_field_tag&lt;/span&gt; &lt;span class="ss"&gt;:username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s2"&gt;"Username"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;label_tag&lt;/span&gt; &lt;span class="s2"&gt;"Password"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;password_field_tag&lt;/span&gt; &lt;span class="ss"&gt;:password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s2"&gt;"Password"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;submit_tag&lt;/span&gt; &lt;span class="s2"&gt;"Log In"&lt;/span&gt;&lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The purpose of this form is to prompt the authentication of a user and the storage of their identity in the session cookie. In &lt;code&gt;SessionsController#create&lt;/code&gt;, we first try to find the user based on their username. If the user exists, we authenticate them using the password provided in the form and the &lt;code&gt;#authenticate&lt;/code&gt; method granted to us by the &lt;code&gt;bcrypt&lt;/code&gt; gem. If they are authenticated, we will store their &lt;code&gt;id&lt;/code&gt; in the session cookie (&lt;code&gt;session[:user_id] = @user.id&lt;/code&gt;). Otherwise, they will be redirected to the login path.&lt;/p&gt;

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

&lt;p&gt;What keeps someone from simply modifying their session cookie to mimic a user? Lucky for us, Rails encrypts the cookies that it creates!&lt;/p&gt;

&lt;h1&gt;
  
  
  Authorization with bcrypt
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Laying the Foundation for Authorization
&lt;/h2&gt;

&lt;p&gt;We've implemented authentication with a couple of forms, a handful of routes and controller actions, and a few &lt;code&gt;bcrypt&lt;/code&gt; methods. And yet a one-winged bird can't fly. We need authorization to put our authentication to work. We can lay the foundation for authorization by writing helper methods in &lt;code&gt;rails-app/app/controllers/application_controller.rb&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ApplicationController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActionController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;helper_method&lt;/span&gt; &lt;span class="ss"&gt;:logged_in?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:current_user&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;current_user&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;logged_in?&lt;/span&gt;
    &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="n"&gt;current_user&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;authorized&lt;/span&gt;
    &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;login_path&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;logged_in?&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here we've defined a few helper methods for use in our controllers and views. &lt;code&gt;ApplicationController#current_user&lt;/code&gt; looks for a value in the &lt;code&gt;:user_id&lt;/code&gt; key of the &lt;code&gt;session&lt;/code&gt; cookie-hash. If there is one, the corresponding user instance will be returned. Otherwise, the return value is &lt;code&gt;nil&lt;/code&gt;. &lt;code&gt;#logged_in?&lt;/code&gt; coerces the return value of &lt;code&gt;current_user&lt;/code&gt; into a Boolean by use of a double-bang. &lt;code&gt;#authorized&lt;/code&gt; will trigger a redirect to the login page unless a user is logged in (that is, unless a value of session[:user_id] exists and it matches the value of an id of an existing user).&lt;/p&gt;

&lt;p&gt;Since all of our controllers inherit from &lt;code&gt;ApplicationController&lt;/code&gt;, we can go ahead and use these methods in them. &lt;code&gt;helper_method&lt;/code&gt; let's us use the methods arguments passed to it in our views.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authorization in Controllers
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;before_action&lt;/code&gt; callback method can help us make short work of using our authorization methods. In our &lt;code&gt;UsersController&lt;/code&gt;, we'll add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsersController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="n"&gt;before_action&lt;/span&gt; &lt;span class="ss"&gt;:authorized&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:show&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;With this line, the application will check to see if a user is logged in and redirect to the login path if they aren't before the &lt;code&gt;#show&lt;/code&gt; action is even fired. But the fun doesn't stop here. We can leverage our authorization helper methods to conditionally render our views! &lt;/p&gt;

&lt;h2&gt;
  
  
  Authorization in Views
&lt;/h2&gt;

&lt;p&gt;In &lt;code&gt;rails-app/app/views/layouts/application.html.erb&lt;/code&gt;, let's add a login/logout button below our view template. That way, it will appear on any pages we add to our application. Recall that &lt;code&gt;&amp;lt;%= yield %&amp;gt;&lt;/code&gt; in &lt;code&gt;application.html.erb&lt;/code&gt; is where the templates corresponding to our controller actions get rendered.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
...

  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;br&amp;gt;&lt;/span&gt;

    &lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;logged_in?&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
      &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;button_to&lt;/span&gt; &lt;span class="s2"&gt;"Logout"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sessions_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;method: :delete&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
      &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;button_to&lt;/span&gt; &lt;span class="s2"&gt;"Login Page"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;login_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;method: :get&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Since we defined the &lt;code&gt;#logged_in?&lt;/code&gt; helper method and passed &lt;code&gt;:logged_in?&lt;/code&gt; as an argument to &lt;code&gt;helper_method&lt;/code&gt; in our &lt;code&gt;ApplicationController&lt;/code&gt;, we are able to use it in our views. This bit of &lt;code&gt;erb&lt;/code&gt; renders a logout button if a user is logged in, and vice versa.&lt;/p&gt;

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

&lt;p&gt;We can get even more specific. Since we have a helper method &lt;code&gt;current_user&lt;/code&gt; that returns the user of the current session, we can render custom content for that user. On the &lt;code&gt;rails-app/app/views/users/show.html.erb&lt;/code&gt; page, we can make it so that a user sees special content if they're on their own show page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Welcome to the page of &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;username&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;

&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;current_user&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;This is my page!!!&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



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

&lt;h1&gt;
  
  
  Logging Out
&lt;/h1&gt;

&lt;p&gt;Every good story has to come to an end. When a user logs out, they are essentially ending their session. One basic way of ending a user's session is to set the value of &lt;code&gt;session[:user_id]&lt;/code&gt; to &lt;code&gt;nil&lt;/code&gt;. We'll add the following action to our &lt;code&gt;SessionsController&lt;/code&gt; to do so.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SessionsController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;destroy&lt;/span&gt;
    &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
    &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;login_path&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you're the observant type, you'll have noticed that the logout button we created last section makes the HTTP request that will be routed to this action. With that action, the session cookie will cease to know about the user and the user will not be authorized in the application.&lt;/p&gt;

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

&lt;p&gt;And that's all it takes to build out basic authentication and authorization in a Rails application with &lt;code&gt;bcrypt&lt;/code&gt;! When we authenticate a user, we check to see they are who they say they are. We facilitate authentication in a web application through sign up and sign/log in forms. To make use of authentication, we track user state in a session cookie and use that cookie to perform authorization before relevant actions in our application.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;bcrypt&lt;/code&gt; helps us implement authentication by giving us a means of securely storing and cross-referencing authentication factors (like passwords) in our database. To authorize users, we write helper methods that use some of those means as well as the built-in Rails sessions cookie to check user state and react accordingly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Bhh7iwoO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/1a69o6hwwxn4mn0vvkrk.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Bhh7iwoO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/1a69o6hwwxn4mn0vvkrk.jpg" alt="Narcissus Getting Lost in Himself"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that you have some idea of how it works, try to implement it yourself! When you're comfortable using &lt;code&gt;bcrypt&lt;/code&gt;, break out the big guns like &lt;code&gt;devise&lt;/code&gt; and try again. Authentication and authorization are essential parts of secure web applications. We'll all be better off if you use them. And never store plain text passwords in a database.&lt;/p&gt;

&lt;h1&gt;
  
  
  Further Reading
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Multi-factor_authentication"&gt;Multi-factor authentication&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.mozilla.org/webdev/2012/06/08/lets-talk-about-password-storage/"&gt;Let's talk about password storage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gcn.com/articles/2013/12/02/hashing-vs-encryption.aspx"&gt;Why salted hash is as good for passwords as for breakfast&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://api.rubyonrails.org/classes/ActiveModel/SecurePassword/ClassMethods.html#method-i-has_secure_password"&gt;&lt;code&gt;ActiveModel&lt;/code&gt; and adds methods to set and authenticate against a BCrypt password&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>security</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Jumpstarting Applications with ActiveRecord</title>
      <dc:creator>Levi</dc:creator>
      <pubDate>Wed, 13 Nov 2019 05:49:57 +0000</pubDate>
      <link>https://dev.to/levi/jumpstarting-applications-with-activerecord-2284</link>
      <guid>https://dev.to/levi/jumpstarting-applications-with-activerecord-2284</guid>
      <description>&lt;h2&gt;
  
  
  Why ActiveRecord is Awesome
&lt;/h2&gt;

&lt;p&gt;ActiveRecord is a Ruby gem that serves up an object relational mapper (ORM) for relational database management systems (RDBMSs). In this post, we'll explore how to use it outside of the Rails ecosystem in the service of fleshing out a simple domain model.&lt;/p&gt;

&lt;p&gt;ActiveRecord provides a Ruby interface for creating, reading, updating, and deleting a database and its constituent tables and data. This interface comes without requiring you to rewrite more than a configuration file when switching from SQLite to PostgreSQL. Databases are a useful addition to any Ruby application because they give us a place to save data--Ruby "flushes" data after each execution session.&lt;/p&gt;

&lt;p&gt;A lot of people encounter ActiveRecord for the first time when crossing the tracks into Rails territory, but ActiveRecord can be leveraged without the trappings of the entire Rails framework. Any Ruby project that involves a database can benefit from the features ActiveRecord provides!&lt;/p&gt;

&lt;h2&gt;
  
  
  What You Need
&lt;/h2&gt;

&lt;h3&gt;
  
  
  File Directory Structure and Gems
&lt;/h3&gt;

&lt;p&gt;Let's start by laying out a basic file directory structure for our application. You may have you own ideas and preferences--that's more than alright. The structure I'm about to present is a stripped-down version of what you might see in a Rails project. Go to town laying this out with &lt;code&gt;mkdir&lt;/code&gt; and &lt;code&gt;touch&lt;/code&gt; in your directory or start clicking away in your file browser.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app/
 » models/
    » planet.rb
config/
 » environment.rb
 » database.yml
db/
 » migrate/
 » seeds.rb 
Gemfile
Rakefile
README.md
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It takes a village to raise an application! We'll start by filling in the &lt;code&gt;Gemfile&lt;/code&gt; in our project directory and calling out the gems we want and need.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# where Bundler will look for gems if they're not already installed&lt;/span&gt;
&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="s1"&gt;'https://rubygems.org'&lt;/span&gt;

&lt;span class="c1"&gt;# Ruby's quintessential ORM&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'activerecord'&lt;/span&gt;
&lt;span class="c1"&gt;# generates fake data, mostly strings&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'faker'&lt;/span&gt;
&lt;span class="c1"&gt;# allows us to create and run tasks from the command line&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'rake'&lt;/span&gt;
&lt;span class="c1"&gt;# enables us to import a whole folder's worth of code into a file&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'require_all'&lt;/span&gt;
&lt;span class="c1"&gt;# gives us useful Rake tasks for managing a database&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'sinatra-activerecord'&lt;/span&gt;
&lt;span class="c1"&gt;# provides us with a primitive Ruby-SQLite3 database&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'sqlite3'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you don't have &lt;a href="https://bundler.io/"&gt;Bundler&lt;/a&gt; installed, now's a good time to hop on the wagon. &lt;code&gt;gem install bundler&lt;/code&gt; ought to do the trick in your terminal.&lt;/p&gt;

&lt;p&gt;With Bundler installed, installing our project's gems is as easy as &lt;code&gt;bundle install&lt;/code&gt; (or &lt;code&gt;bundle&lt;/code&gt;, if you're feeling lazy). Bundler scans the gem file for our projects dependencies and downloads and installs whatever is not already on our system. Bundler makes it quick and easy to get any system up to speed with a Ruby application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ruby Environment and Database Configuration
&lt;/h3&gt;

&lt;p&gt;Let's take a little trip into the &lt;code&gt;config/&lt;/code&gt; directory. In &lt;code&gt;environment.rb&lt;/code&gt; we will centralize importing gems and local Ruby files so that we need only require &lt;code&gt;environment.rb&lt;/code&gt; in our run files to get things done.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'bundler'&lt;/span&gt;
&lt;span class="no"&gt;Bundler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;
&lt;span class="n"&gt;require_all&lt;/span&gt; &lt;span class="s1"&gt;'app'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That wasn't so hard, was it? &lt;code&gt;require 'bundler'&lt;/code&gt; makes it so that we can execute the following line &lt;code&gt;Bundler.require&lt;/code&gt; and essentially &lt;code&gt;require&lt;/code&gt; everything in the &lt;code&gt;Gemfile&lt;/code&gt;. &lt;code&gt;require_all 'app'&lt;/code&gt; requires all local &lt;code&gt;.rb&lt;/code&gt; files in the &lt;code&gt;app/&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;Now comes the weird part. In &lt;code&gt;database.yml&lt;/code&gt;, copy-paste the following code [&lt;a href="https://gist.github.com/danopia/940155"&gt;source&lt;/a&gt;]:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# SQLite version 3.x&lt;/span&gt;
&lt;span class="c1"&gt;#   gem install sqlite3-ruby (not necessary on OS X Leopard)&lt;/span&gt;
&lt;span class="ss"&gt;development:
  adapter: &lt;/span&gt;&lt;span class="n"&gt;sqlite3&lt;/span&gt;
  &lt;span class="ss"&gt;database: &lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;development&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sqlite3&lt;/span&gt;
  &lt;span class="ss"&gt;pool: &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
  &lt;span class="ss"&gt;timeout: &lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here we specify what kind of RDBMS we are interfacing with, the name and location of the database file (if it doesn't exist it will be generated), then maximum number of open connections (pools) to the database, and the time limit for query operations. &lt;code&gt;sinatra-activerecord&lt;/code&gt; will refer to this file by default to configure the connection between ActiveRecord and the SQLite database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rake Tasks
&lt;/h3&gt;

&lt;p&gt;Rake is a Ruby gem that allows us to run tasks, or snippets of Ruby code, from the command line. It also gives us the ability to tidily define these within a file known as the &lt;code&gt;Rakefile&lt;/code&gt;. In our &lt;code&gt;Rakefile&lt;/code&gt;, let's write the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# imports everything (gems and local files) specified in environment.rb&lt;/span&gt;
&lt;span class="nb"&gt;require_relative&lt;/span&gt; &lt;span class="s1"&gt;'config/environment'&lt;/span&gt;
&lt;span class="c1"&gt;# gives us an arsenal of rake tasks for managing our database&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'sinatra/activerecord/rake'&lt;/span&gt;

&lt;span class="c1"&gt;# describes the task&lt;/span&gt;
&lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s1"&gt;'starts a console'&lt;/span&gt;
&lt;span class="c1"&gt;# establishes the name of the rake option: console&lt;/span&gt;
&lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:console&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# turns on logging of SQL queries while in the task&lt;/span&gt;
  &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;STDOUT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;# starts a Ruby REPL session&lt;/span&gt;
  &lt;span class="no"&gt;Pry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, by executing &lt;code&gt;rake console&lt;/code&gt; in our terminal while in our project directory, we will be able to start a REPL session and experiment with methods to our hearts content, all with access to the contents of our project and without the fuss and muss of managing a run file.&lt;/p&gt;

&lt;p&gt;While ActiveRecord and Rake are separately invaluable gems, their power and usefulness is compounded with the inclusion of &lt;code&gt;sinatra-activerecord&lt;/code&gt;. Right now, while in your project directory in your terminal, run &lt;code&gt;rake -T&lt;/code&gt; in the command line to see your available tasks. See all the ones with the &lt;code&gt;db:&lt;/code&gt; prefix? &lt;a href="https://github.com/sinatra-activerecord/sinatra-activerecord"&gt;Sinatra&lt;/a&gt; gave us those.&lt;/p&gt;

&lt;h2&gt;
  
  
  Breathing Life into the Domain Model
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Making/Mapping a Class/Model
&lt;/h3&gt;

&lt;p&gt;One of the advantages of using ActiveRecord is that it is an object relational mapper. It gives us the ability to map the structure of our database to the structure of our codebase. Here's a quick refresher on the Active Record pattern of ORMs (for which the ActiveRecord gem is named) with the database element on the left and equivalent codebase element on the right:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Database = Domain&lt;/li&gt;
&lt;li&gt;Table = Model&lt;/li&gt;
&lt;li&gt;Column = Attribute&lt;/li&gt;
&lt;li&gt;Row = Instance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With ActiveRecord, making our model participate in this scheme is as simple as dirt (or at least inheritance).&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;app/models/planet.rb&lt;/code&gt;, park the following lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Planet&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;class Planet &amp;lt; ActiveRecord::Base&lt;/code&gt; is our golden goose, as it endows our Planet class (aka our Planet model) with all of the rights and privileges and &lt;a href="https://guides.rubyonrails.org/active_record_basics.html#crud-reading-and-writing-data"&gt;methods of ActiveRecord therein&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;I've stuck a class method in there to print all instances of our Planet class with a little flavor. Yet we've no instances to speak of! Let's fix that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating the Database
&lt;/h3&gt;

&lt;p&gt;ActiveRecord will look specifically for a &lt;code&gt;db/&lt;/code&gt; folder at the top of your project directory, along with a &lt;code&gt;migrate/&lt;/code&gt; subdirectory. ActiveRecord builds out a database with Ruby files called &lt;a href="https://edgeguides.rubyonrails.org/active_record_migrations.html"&gt;migrations&lt;/a&gt;, which specify the action to take on the database and the schema being added or altered.&lt;/p&gt;

&lt;p&gt;Thanks to &lt;code&gt;sinatra-activerecord&lt;/code&gt;, we have access to a Rake task that will generate a migration file for us. Run &lt;code&gt;rake db:create_migration NAME=create_planets&lt;/code&gt; in your terminal.&lt;/p&gt;

&lt;p&gt;You should now have a file that looks like &lt;code&gt;TIMESTAMP_create_planets.rb&lt;/code&gt;. Inside it, input the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreatePlanets&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Migration&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;change&lt;/span&gt;
    &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="ss"&gt;:planets&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;
      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;boolean&lt;/span&gt; &lt;span class="ss"&gt;:inhabitable&lt;/span&gt;

      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timestamps&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here is the table that corresponds to our model, along with specifications for the tables columns (aka the model's attributes). Note that the table name is plural while the model name was singular (see: &lt;a href="https://edgeguides.rubyonrails.org/active_record_basics.html#naming-conventions"&gt;ActiveRecord Naming Conventions&lt;/a&gt;). &lt;/p&gt;

&lt;p&gt;To create this table in our database, we need only lean on another rake task sung by Sinatra: &lt;code&gt;rake db:migrate&lt;/code&gt;. If the migration was successful, we will have a &lt;code&gt;schema.rb&lt;/code&gt; file in the &lt;code&gt;db/&lt;/code&gt; directory. Check it! Don't edit it ever! It's created and updated with each migration. It's contents should reflect the contents of our migration.&lt;/p&gt;

&lt;p&gt;We've come a long way. It's high time we paused to test the makings of our project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test Driving an ActiveRecord Project
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Seeding the Database
&lt;/h3&gt;

&lt;p&gt;It is critical we test the functionality of our model and database before further fleshing out our project. While we could always require the formal &lt;code&gt;rspec&lt;/code&gt; gem and write formal tests, we aren't going to do that during this foray. Instead, we'll populate our database with seed data and poke at it while in our &lt;code&gt;rake console&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;seeds.rb&lt;/code&gt; file, we are encouraged to write ActiveRecord methods that populate our database (hence the name "seeds"). We will do just that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;boolean_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;Planet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="no"&gt;Faker&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Movies&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;StarWars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;planet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="ss"&gt;inhabitable: &lt;/span&gt;&lt;span class="n"&gt;boolean_array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sample&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;These 7 lines generate 5 planets with random names and inhabitability booleans. To seed our database with this data, we simply run &lt;code&gt;rake db:seed&lt;/code&gt; in our terminal while in the project directory. We know our seeding was successful if we get no immediate feedback.&lt;/p&gt;

&lt;h3&gt;
  
  
  Poking at the Database
&lt;/h3&gt;

&lt;p&gt;With our database seeded, let's see if we can do some damage. Pop into the rake console by executing &lt;code&gt;rake console&lt;/code&gt; in your terminal. This command should start a Pry session.&lt;/p&gt;

&lt;p&gt;Let's flex some ActiveRecord methods. Our Planet model inherited from &lt;code&gt;ActiveRecord::Base&lt;/code&gt;, so it should have gotten something for it's trouble! Here are a few things you can try:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Planet.create(name: STRING, inhabitable: BOOLEAN)&lt;/code&gt; creates a new instance of the Planet class with the specified parameters and saves it in the database&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Planet.all&lt;/code&gt; returns all instances of Planet&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Planet.find(2)&lt;/code&gt; returns the Planet instance with &lt;code&gt;id == 2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;planet.update(name: STRING)&lt;/code&gt; updates the instance of Planet (planet) with the given attribute-value pair&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Planet.all.last.delete&lt;/code&gt; deletes the last instance of Planet in the database&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Full CRUD, just like that! These are but a few of the methods ActiveRecord provides for you. &lt;a href="https://edgeguides.rubyonrails.org/active_record_basics.html"&gt;Read the docs&lt;/a&gt; to get the full scoop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where To Go From Here
&lt;/h2&gt;

&lt;p&gt;Once you grasp domain modeling, CRUD, and the Active Record pattern, ActiveRecord is as powerful as it is intuitive. We've said nothing about &lt;a href="https://edgeguides.rubyonrails.org/association_basics.html"&gt;relationships&lt;/a&gt; between models or &lt;a href="https://edgeguides.rubyonrails.org/active_record_validations.html"&gt;validating&lt;/a&gt; model attributes.&lt;/p&gt;

&lt;p&gt;ActiveRecord empowers us to create and manage RDBMS in sweet, sweet Ruby. We don't need to fret about what flavor of SQL we're using or translating a sorted polymorphic has-many select into a specific query. We can focus on adhering to a rock-solid object-oriented programming pattern to build a readable and maintainable application.&lt;/p&gt;

&lt;p&gt;That isn't to say we should simply skip over SQL (in fact, if you don't know SQL, take an hour or two the next chance you get and work through &lt;a href="https://sqlbolt.com/"&gt;SQLBolt&lt;/a&gt;). A basic understanding SQL and RDBMS will help you understand what's going on under the hood of ActiveRecord so you can fix things when they inevitably break down.&lt;/p&gt;

&lt;p&gt;When you build out your next (or current) project, think of it in terms of the data flowing through it and how that data can be encapsulated and described. Draw out a &lt;a href="https://hackernoon.com/making-a-case-for-domain-modeling-17cf47030732"&gt;domain model&lt;/a&gt; and think of the models that make it up and the relationships between them. Think about the attributes that describe those models. Then make your models, write your migrations, seed your database, and play!&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>beginners</category>
      <category>sql</category>
    </item>
  </channel>
</rss>
