<?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: clheard54</title>
    <description>The latest articles on DEV Community by clheard54 (@clheard54).</description>
    <link>https://dev.to/clheard54</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%2F336312%2F245ec21d-9682-4d94-9813-a27dfc3f0e1a.png</url>
      <title>DEV Community: clheard54</title>
      <link>https://dev.to/clheard54</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/clheard54"/>
    <language>en</language>
    <item>
      <title>Callback Functions: Say Whaat?</title>
      <dc:creator>clheard54</dc:creator>
      <pubDate>Thu, 09 Apr 2020 21:54:21 +0000</pubDate>
      <link>https://dev.to/clheard54/callback-functions-say-whaat-3jhd</link>
      <guid>https://dev.to/clheard54/callback-functions-say-whaat-3jhd</guid>
      <description>&lt;p&gt;Def: synchrony : simultaneous action, occurrence, or development&lt;/p&gt;

&lt;p&gt;In seventh grade math class, we took a detour from the textbook one trimester and were given instead the infamous “Yellow Book”. It was homemade and spiral-bound, a series of photocopied worksheets (whose origin, I’d now guess, was probably a typewriter, given the old-school CourierNew-esque font), handwritten explanations, problem sets pulled from a hodge-podge of sources -- a most bizarre collection indeed. And the topics covered were far from your run-of-the-mill seventh grade math class standards. We had units on modulo arithmetic, logical operators,  geometric proofs by construction, networks and matrices… But what I remember being a total nightmare at the time was a brief foray into the world of circuits. Circuits in series -- connecting end-to-end, a simple sum-of-its-parts pattern -- made sense enough; parallel circuits, on the other hand: I could not wrap my head around them.&lt;/p&gt;

&lt;p&gt;When I first started learning about synchronous and asynchronous programming, I had a flashback to my Yellow Book. In my head, I connected synchronous programming with the series circuit model: In synchronous programming, things happen one at a time, one after another. It’s all very linear and sensible. If you call a function that performs a lengthy action, that function will run to completion -- and too bad for the rest of your program, which is put on pause. Only once that original function has finished and returned its result will the program move on. Okay, so perhaps not-so-sensible. After all, we live in a society that is not known for its patience. &lt;/p&gt;

&lt;p&gt;But, as with circuits, there is an alternative.  In case you’re interested in a brief review: Series circuits are basically long daisy-chains. There is a single path along which the current can flow, and the circuit’s total voltage is equivalent to the sum of the voltage drops through each component. (Duh. No wonder my 7th grade brain liked this. But also, and more relevantly: This is similar to time in a synchronous programming model.  The total time taken to run a program will equal at least the sum of the time required to complete each task in sequence.) A parallel circuit, on the other hand, is one in which the current is not restricted to a single path. In the words of a Boston University physics professor, “the current in a parallel circuit breaks up, with some flowing along each parallel branch and re-combining when the branches meet again.” Which, it turns out, is actually not a bad  analogy for asynchronous programming.&lt;/p&gt;

&lt;p&gt;In an asynchronous programming model, many actions can be taken at the same time. When a function is executed, it does not necessarily halt the entire program in its tracks. Rather, your program will move on to the next functions, and when the initial action completes, the results will be revisited and/or incorporated as necessary.&lt;/p&gt;

&lt;p&gt;So conclusion number one: Asynchronous programming has huge advantages when it comes to speed.&lt;/p&gt;

&lt;p&gt;Conclusion number two, which is far less obvious: Sometimes, asynchronous programming can prove rather frustrating, since we don’t actually know exactly how long a process may take. For example, if I want to fetch come data from an API, I can make that request -- but I cannot determine the precise moment that the request will complete -- and in the meantime, my program will keep running. Will the results come in 5 lines later in my code? 10? How many functions will have executed in the meantime? What actions will occur without any of the information from that request having come in yet?&lt;/p&gt;

&lt;p&gt;What a glory it was to learn about callback functions last week. To be perfectly honest, I’m not a fan of the name “callback.” There are other names that seem far more intuitive to me. And the definition that is often put forward as the initial one seems, actually, not to be informative of a callback’s primary purpose. But regardless, here’s the important thing: A callback function is one that is told to wait its turn. It is, in fact, explicitly not executed until another function has completed its action. &lt;/p&gt;

&lt;p&gt;There are three big truths about JavaScript that help explain this:&lt;br&gt;
JavaScript is an “event-driven language” and behaves asynchronously by default. It does not wait for a response from a function before moving on to its next task. Take this classic example: When you call these two functions one after another, all goes as you might expect.&lt;/p&gt;

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

&lt;p&gt;But make a slight change to function numberOne (here, setTimeout is used to kinda imitate what would happen if, for instance, you made a GET request to an API that took .5 seconds to complete), and your results are a bit weirder.&lt;/p&gt;

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

&lt;p&gt;Even though function numberOne is called first, its results (console logging “I am first!”) show up second. This is because JavaScript mimics the impatience of humans and likes  to rush forward, finishing all the things it can even while impatiently waiting for something in the background.&lt;/p&gt;

&lt;p&gt;JavaScript can be impatient but its trying to help us out by delivering things efficiently. And sometimes, it must wait. For instance: Functions, at the end of their execution, return things. Those things, whatever they may be, are accessible only at the completion of the function. Need to make something wait until function DoingSomething is over? Great! You can make it part of what DoingSomething returns.&lt;/p&gt;

&lt;p&gt;JavaScript likes to treat everything as an object. That means functions, too, are objects. Because of their object-ness, functions can become arguments to other (outer) functions. Thus, they can also be returned by other functions. Voila. &lt;/p&gt;

&lt;p&gt;Let’s look a few other, perhaps more slightly realistic, example. As a student at Flatiron for the past 10 weeks, I’ve been doing a lot of building websites where we’re grabbing existing data or getting inputs from users, rendering said data to the page in various configurations, editing and updating with mouse/keyboard events… A large number of these mini projects involve fetching data from an API. These fetch requests are a great example of when callbacks are useful. &lt;/p&gt;

&lt;p&gt;In the example below, a fetch request is made to a Random Recipes API. We’ll get back one recipe, and that will be what we make for our next meal. &lt;/p&gt;

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

&lt;p&gt;When we call hungerAlert followed by yummy, you might expect to see their console.logs rendered in that order. But no! “Ahh, dinner complete!” is printed to the console first, despite the fact that we clearly called it second. While Javascript was waiting for the API fetch to complete in order to take the steps dependent on its promises, it went on to execute yummy without any delay.&lt;/p&gt;

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

&lt;p&gt;Below, we use a setTimeout function to simulate the delay of an API fetch. We also change our two functions slightly, so that hungerAlert now accepts a callback function as an argument. Even though hungerAlert is held on pause for 1 second, yummy does not execute this time. Because it is called inside hungerAlert as a callback function, it waits, and only due to this wait does it even know what “occasion” is. &lt;/p&gt;

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

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

&lt;p&gt;With the advent of promises, callback functions are not the only tool in our toolbox for dealing with ordering of functions. But still, they are a useful thing to have in the arsenal.&lt;/p&gt;

&lt;p&gt;Other fun facts about callback functions: &lt;br&gt;
They should not actually be invoked when being passed as an argument&lt;br&gt;
They can themselves have parameters&lt;br&gt;
They act as closure&lt;br&gt;
Callbacks can be named or anonymous&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>CLI Tips</title>
      <dc:creator>clheard54</dc:creator>
      <pubDate>Tue, 24 Mar 2020 22:29:53 +0000</pubDate>
      <link>https://dev.to/clheard54/cli-tips-h6o</link>
      <guid>https://dev.to/clheard54/cli-tips-h6o</guid>
      <description>&lt;p&gt;There's a poster hanging inside the Seattle campus of the Flatiron School. It lists some ubiquitous and helpful keyboard shortcuts -- and I've definitely referenced it several times in the past few weeks.&lt;/p&gt;

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

&lt;p&gt;Need to create a new project? Now I know that "mkdir" is what I'm looking for. Make some new files to populate that directory? "Touch" is the command that does the trick. Who would have thought that navigating through files and folders without a mouse or a single click could be so simple? But if you've got "pwd", "ls", and "cd" under your belt, you can check out what directory you're currently in, list the other files and directories in it, and easily move into a different directory of your choosing. Just gotta know those shortcuts.&lt;/p&gt;

&lt;p&gt;But alas. Not everything about the command line interface could be so lovely. If you've spent much time typing your way through the terminal, you, like me, may have experienced the infuriation upon realizing (and then forgetting and remembering, and remembering again), that you cannot simply click anywhere in your line of text to change where your cursor is. Oh no. Your cursor responds to your arrow keys, and likes to make its way back and forth through a line one...slow...space...at...a...time. &lt;/p&gt;

&lt;p&gt;Now, I'll be the first to admit it: My typing skills can sometimes be sloppy -- yay for lots of typos. How many times have I entered a long line in the terminal, only to realize that "dc" is not, in fact, the same thing as "cd"? It's perhaps a sign of my millennial impatience that it seems quite irksome to have to hold down the arrow key as my cursor traverses through the entire line of text to get back to the beginning two characters. I learned from one classmate that it's actually possible to increase the speed with which your cursor moves. But still.&lt;/p&gt;

&lt;p&gt;And deleting text in bulk? The terminal's refusal to acknowledge my mouse also prevented me from clearing entire words or lines all at once. Again, the joy of holding down the delete key and waiting for the cursor to move left one character at a time. I'm telling you, if time is money, then at those moments it feels like you're hemorrhaging it. &lt;/p&gt;

&lt;p&gt;So for those of you are like me: prone to typos (in your EXCITEMENT to get your ideas down!), impatient (ahem, excuse me, EAGER to keep moving along in your project!!), and ready to rejoice at greater efficiency, behold. The all-too-little known terminal commands that will positively change your life.&lt;/p&gt;

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

&lt;p&gt;Need to return to the beginning of the line you're currently typing? "Ctrl + A" = your new best friend.&lt;br&gt;
And to get back to the end of that line -- no sweat. "Ctrl + E"&lt;/p&gt;

&lt;p&gt;To delete that whole line in a hurry, just hit "Ctrl + U". And if you'd like to be slightly more selective in your deletions, "Ctrl + W" will delete just the last word typed.&lt;/p&gt;

&lt;p&gt;If you'd like to sidestep a search through a lengthy directory (it can be a pain to "ls" all the contents and visually comb through), you can instead begin your terminal command with a bang: "!". If you remember that your file has something to do with giraffes, "cd !giraffe" followed by "Tab" will show you any and all files with "giraffe" in their title.&lt;/p&gt;

&lt;p&gt;Careful, though. A double bang "!!" will execute the most recently entered command.&lt;/p&gt;

&lt;p&gt;Those commands are a sampling of the ones I'm most grateful to have discovered. Here are a few others... what's your favorite?&lt;/p&gt;

</description>
      <category>codenewbie</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Decrypting BCrypt</title>
      <dc:creator>clheard54</dc:creator>
      <pubDate>Tue, 10 Mar 2020 03:42:30 +0000</pubDate>
      <link>https://dev.to/clheard54/decrypting-bcrypt-3gba</link>
      <guid>https://dev.to/clheard54/decrypting-bcrypt-3gba</guid>
      <description>&lt;p&gt;Recently, privacy has become a hot-button issue in the tech world. With the development and advancement of facial recognition software, the extraordinary power of GPS tracking on our cell phones, and the storage of more and more sensitive data online, we’ve become increasingly aware just how important it is to build and/or strengthen privacy measures. &lt;/p&gt;

&lt;p&gt;But even when it comes to new developers learning to build small-potatoes applications, privacy remains relevant -- and extremely important. In general, it seems like good practice to safeguard any accounts with usernames and passwords. Luckily, there are many tools available to make that process fairly painless for a programmer. We’ve got loads of helper gems on our side. Last week, while my classmates and I were working on building our first web apps (many of which attempted to implement logins and passwords) we were introduced to one popular option: BCrypt. &lt;/p&gt;

&lt;p&gt;BCrypt, we learned, does a LOT of heavy lifting behind the scenes. In fact, it seemed like writing about 5 lines of code accomplished just about every one of the authentication and authorization measures a basic login requires. Literally. First, you have to go make sure you’ve got the BCrypt gem in your Gemfile. Easy enough. And the User table in the database needs to be updated; we’ll have to add a “password_digest” column. The User class itself also gets a quick one-liner: “has secure password”. And voila! Suddenly the User really does have a secure password. &lt;/p&gt;

&lt;p&gt;...But given that we started the lesson by chatting about cyber-security, transparency in privacy policies, and the power that knowledge about such matters provides, it seemed prudent to dig a bit deeper and attempt to understand what, exactly, BCrypt is doing behind the scenes. &lt;/p&gt;

&lt;p&gt;BCrypt does its job of adding security in several ways. First of all, it saves us from ever having to transmit or store a password in its unencrypted version. A user will need to enter the plainform string when creating an account -- but that password is never stored as such. As I mentioned above, the only column added to the User table (besides, presumably, username) is password_digest. And the entries in this column are never stored in their original format. Rather, BCrypt handles the work of automatically salting and hashing the entered password -- and it persists only this encrypted version to the database. &lt;/p&gt;

&lt;p&gt;This helps us programmers by allowing us to circumvent some potentially hairy areas. Normally, in order to grab user-entered data from a form, we’d need to have corresponding attributes for the object being created. And each of those attributes would need a writer method. For example, if I were creating a book object and trying to give it a title and author (by entering this data into a form), I would need to have access to the title= and author= methods. Otherwise, assigning those values is not available to me. (Think about strong params: Strong params are essentially a way of controlling which writer methods the user has permission to access. If an attribute isn’t listed in the strong params, the user cannot successfully re-assign any values that we would like to remain fixed.) &lt;/p&gt;

&lt;p&gt;But back to our User model. According to our current schema, a User doesn’t have a password attribute. There is no such column in the User table. So ActiveRecord, which we can usually rely on to provide reader and writer methods, is of no help to us. We could manually code out a writer method password=, but this would require more direct contact with the initial, unencrypted password. Not great. We also would ideally like to avoid involving the password_digest in the strong params -- we do not want there to be indiscriminate access to that data.&lt;/p&gt;

&lt;p&gt;BCrypt offers a neat solution. It saves us from having to add a “password” column in our User table, but still gives us access to a .password instance method. We aren’t responsible for writing our own password= method because BCrypt does that for us, providing the code that 1) gathers the plaintext version of the password from a form, 2)  automatically salts and hashes a password, and 3) persists this transformed, encrypted version in the password_digest column. &lt;/p&gt;

&lt;p&gt;Ultimately, what this means is that because of BCrypt, a user can create a new password and have it be safely stored without it ever being unencrypted. It’s also a boon for us programmers because it saves us from having to translate back and forth between the string and salty hash versions of the password. But BCrypt goes a step even further: To explore, let’s look at an example.&lt;/p&gt;

&lt;p&gt;Let’s say I’m creating an account and I enter my password as “banana123”. BCrypt automatically grabs this string, salts it (adding random characters to the front), and encrypts it. The end result may look something like this: “$2a$12$uwk8FBhpVQbvyHTHppO67ezQ..shaGuBKpIgNp2LSiV8tVm3/r8Sy”. This is what is stored as the password_digest in my database. So what happens when I come back and want to login again? I enter my password as “banana123”. Without BCrypt, we would stuck with the challenge of comparing “banana123” and “$2a$12$uwk8FBhpVQbvyHTHppO67ezQ..shaGuBKpIgNp2LSiV8tVm3/r8Sy”. Not only is this messy and ugly, it also means we’re spending more time in contact with the plain-string password. But BCrypt cleverly has its own version of the == comparison function… And their version can directly compare my “banana123” with the database’s “$2a$12$uwk8FBhpVQbvyHTHppO67ezQ....”. That’s right. Check it out:&lt;/p&gt;

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

&lt;p&gt;Clearly, the two strings are not equal (hence the return of ‘false’ when we compare them directly, above). But remarkably, comparing the BCrypt version of the password with the string DOES evaluate to true. &lt;/p&gt;

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

&lt;p&gt;In other words, BCrypt can look at the string entered by the user upon login and the encrypted salty hash persisted in the database, and successfully determine whether they match. &lt;br&gt;
Indeed, another service BCrypt provides is the “authenticate” method, which performs exactly this comparison, again saving us from any manual conversions.&lt;/p&gt;

&lt;p&gt;So yes, BCrypt does some magic. By leveraging a handful of methods in the background, it can provide authentication and authorization gateways to protect an account. But it’s important to also understand the limitations of BCrypt.&lt;/p&gt;

&lt;p&gt;Since we’re dealing with users and logins, we’re creeping into the realm of sessions. It may be tempting to believe that BCrypt has the power to also do work related to sessions: If it can store a password, perhaps it can also store user information in a session as part of the login and authentication process? If it acts as the gatekeeper for logins, maybe it also passes along login information about the user (such as id) to the session? But ‘tis not so. BCrypt will not automatically persist any user information to the current session. If a new User is creating their account, and then logs in for the first time, we will have to handle the work of assigning a sessions[:user_id]. We will be responsible for writing those methods that can pass along data to the session, or save info about a current_user, or destroy that information upon logout. BCrypt is a powerful tool, but it cannot do everything for us. So, as always, take care in using it -- not because it’s dangerous or insecure. But because it always serves you well to be aware of what the technology you are using is capable of: to know how it works behind the scenes, to understand its underlying processes, and to keep in mind its potential shortcomings or loopholes.&lt;/p&gt;

</description>
      <category>codenewbie</category>
      <category>rails</category>
      <category>security</category>
    </item>
    <item>
      <title>Peeling Back the Layers of Nested Attributes</title>
      <dc:creator>clheard54</dc:creator>
      <pubDate>Mon, 02 Mar 2020 22:12:58 +0000</pubDate>
      <link>https://dev.to/clheard54/peeling-back-the-layers-of-nested-attributes-4kmc</link>
      <guid>https://dev.to/clheard54/peeling-back-the-layers-of-nested-attributes-4kmc</guid>
      <description>&lt;p&gt;Last week, after slogging through a mess of repetitive Sinatra code, I finally dove into Rails (oh the magic of rails g scaffold!). ActiveRecord worked behind the scenes to build out many-to-many relationships with ease. Rails was smart enough to create models, migrations, and views for me. The magic, my friends, is real.&lt;/p&gt;

&lt;p&gt;But I've always been the person who isn't quite satisfied after a magic show. I can't just be awed and okay with it. I feel a compulsion to know the secret. To figure out what the trick is. To pull back the curtain and reveal what's hiding behind it. So when I came across something like this:&lt;/p&gt;

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

&lt;p&gt;...I skidded to an abrupt halt. "Accepts_nested_attributes_for"? And suddenly these relationships I'd been painstakingly crafting just appeared out of the void?! The Ruby helper seemed entirely opaque. So I had to unpack it fully, to dive into nested attributes - and their corresponding nested hashes. What follows is my attempt to unveil the mysteries of this method.&lt;/p&gt;

&lt;p&gt;SO WHEN DO WE RUN INTO NESTED ATTRIBUTES?&lt;br&gt;
Suppose we’re working with a model that represents the relationships between breweries and their beers. A brewery has many beers; a beer belongs to a specific brewery. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wzkhyJAD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/j5cbshnzznt33nk8noc7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wzkhyJAD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/j5cbshnzznt33nk8noc7.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--u07vvEIS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hmk2j2ctqo6ouyndnkxw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u07vvEIS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hmk2j2ctqo6ouyndnkxw.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A beer can hold a foreign key for its brewery, and that will be good enough to represent this has-many-belongs-to relationship. So far, so good. But a &lt;em&gt;brewery&lt;/em&gt; will have several beers... and each beer has its own attributes. This is the nesting.&lt;/p&gt;

&lt;p&gt;SO... HOW DOES NESTING AFFECT US?&lt;br&gt;
This is where “accepts_nested_attributes” comes in. In short, this helper method provides a super handy-dandy shortcut: It allows us to tell a brewery the properties of its beers AND create those beers at the same time. Magic! In particular, “accepts_nested_attributes” comes in handy when we start fiddling with writing forms. &lt;/p&gt;

&lt;p&gt;If we're adhering to the convention of RESTful Ruby routes, we probably need a "new" method that will allow us to create either a new beer or brewery. ActiveRecord is smart enough to create associations between objects (with very little work from us) -- but those objects need to exist before they can become related. What if we want to create a new brewery and immediately associate it with some beers -- but those beers don’t exist in our database yet either? How can we create both a brewery and its beers simultaneously? &lt;/p&gt;

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

&lt;p&gt;Enter "accepts_nested_attributes"! Let’s consider the case that we want to create a new brewery (Beer-o-mania?!) that makes 3 beers. Ideally, we’d like the “Create a New Brewery” form to take in data not only about the brewery's name and location, but also about each of its three beers. &lt;/p&gt;

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

&lt;p&gt;Those beers would be collected in an array -- but each beer would be its own hash, complete with its own name, style, and ABV keys. This means that our &lt;em&gt;params&lt;/em&gt; would ideally look something like this:&lt;/p&gt;

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

&lt;p&gt;Enter “Nested Attributes." As the above image shows, within the brewery hash, there is this array of beers -- and each beer has its own set of attributes. Now we just need to figure out how to build this structure from our form.&lt;/p&gt;

&lt;p&gt;Remember, our goal is to enter info into a form in order to save a new brewery to our database. In order to assign attributes to an object, though, we need a writer method (think back to Object-Oriented programming and the necessity of attr_readers and attr_writers). Our ability to build a custom brewery depends on the existence of a writer method for the brewery's name, location -- and its beers. If we're trying to assign attributes within the beers, that will require a further writer method. Something like this:&lt;/p&gt;

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

&lt;p&gt;The name “beers=” is already taken. So we resort to beers_attributes= as our method name. (And we can begin to see where "accepts_nested_attributes_for :beer" might come from!) Let’s head over to our Brewery Model to define this method. &lt;/p&gt;

&lt;p&gt;RUBY'S BEHIND-THE-SCENES SLEIGHT OF HAND&lt;br&gt;
Okay, here’s the thing. Remember our beer_attributes array from above? Well. Ruby takes that array and decides to secretly turn it into a HASH (with keys that are kind of like primary ids). So we have to keep the hash structure in mind as we try to transform each entry into a fully-fledged Ruby object. If you take a look below, it's clear that we are now only interested in the &lt;em&gt;values&lt;/em&gt; of the Ruby hash.&lt;/p&gt;

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

&lt;p&gt;Each of those values tells us all we could ever wish to know about a specific beer. All that’s left is to create an object from that information, and associate it with the Brewery. Guess what? Ruby provides another helper for us. The “build” method will do precisely this.&lt;/p&gt;

&lt;p&gt;The ‘build’ method works, on the most basic level, almost entirely like the ‘new’ method. What distinguishes it is one extra feature, and that’s what makes it important to us here. ‘Build’ automatically associates our newly created object with the object it's called on. Whereas Beer.new will be instantiated with no brewery_id/foreign key assignment, Brewery.beers.build will instantiate a new beer that already has its brewery_id set.&lt;/p&gt;

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

&lt;p&gt;So within the instance method “beers_attributes=”, we can call build on the brewery we’re currently working with, and ask build to create a beer in self.beers. A new beer can thus be created from 1) a set of attributes, that is 2)  nested within the brewery hash, which is itself 3) located in our params hash.&lt;/p&gt;

&lt;p&gt;To recap, right now we have a Brewery Model that looks like this:&lt;/p&gt;

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

&lt;p&gt;And a New form within our Brewery Views that still needs a bit of work:&lt;/p&gt;

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

&lt;p&gt;Building out the rest of this form really just means providing the fields needed to gather all the information about any beers that we’d like to create within a brewery. We can use the form helper "fields_for" to accomplish this.&lt;/p&gt;

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

&lt;p&gt;TYING IT TOGETHER IN OUR MVC MODEL&lt;br&gt;
Almost there! We’ve now set up our Model and our View successfully. The only thing to finalize is the Controller. There are two big things to remember here: One is that we’re eventually trying to create a Brewery based on the information stored in params. And what have we just done? Given params the ability to take in data (or nested attributes) on beers created by the brewery. We also wrote a writer method so that we could assign values to the beer attribute keys. Does our Controller know any of this yet, though? NO! It has no idea we actually want this assignment to be happening. And right now, our strong params are withholding from us the permission to make these changes. So :beer_attributes must be added to our strong params permissions -- and we should probably specify which beer attributes we want to give a user access to edit or update.&lt;/p&gt;

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

&lt;p&gt;Last thing’s last. Let’s make sure that when we’re creating a Brewery, we give it a heads-up that it might be born with some beers alongside it. Writing Brewery.new is not enough inside the 'new' controller method anymore. We must instantiate it with some beer fields (let's say three) so that the data gathered in our form fields actually has somewhere to go and live... &lt;/p&gt;

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

&lt;p&gt;And voila! Here's what our form looks like, and what it ultimately creates. Not bad at all.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--49oabg6o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/xat7g0yp7z63yhnpq3oq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--49oabg6o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/xat7g0yp7z63yhnpq3oq.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xBQK4VcQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/j23kqh7bkymkhgvvi5h8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xBQK4VcQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/j23kqh7bkymkhgvvi5h8.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rails</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Solving the Problem</title>
      <dc:creator>clheard54</dc:creator>
      <pubDate>Sat, 22 Feb 2020 19:17:35 +0000</pubDate>
      <link>https://dev.to/clheard54/solving-the-problem-54l8</link>
      <guid>https://dev.to/clheard54/solving-the-problem-54l8</guid>
      <description>&lt;p&gt;For a long time, I had a bug. Symptoms would flare up every now and again, but most of the time it was a low-level, nagging sensation. I'd go about my daily life -- teaching high schoolers math, for the most part -- but there was some part of my brain that didn't feel quite right. It wanted something else. Folks had been telling me for a while, and I suppose their idea gradually wheedled its way into my own subconscious. "You should learn to code." "I think you would really like coding." "You think like a programmer." They kindled a curiosity, one that has refused to be doused. I started to feel the itch, and as the months passed, it grew so that I couldn't ignore it any more.&lt;/p&gt;

&lt;p&gt;I suppose I’ve always loved patterns and problem-solving: My favorite card game by far is Set. There’s something so satisfying to me about the simultaneous flexibility and rigidity of the 'set' structure. A strict logic determines what “counts”; and yet within this set of rules, myriad possibilities abound. You could search by color - green, red, purple; you might strategically count the singles, doubles, and triples; or you could eyeball the diamonds or the squiggles alone. Sometimes, though, it’s a matter of taking in the whole picture, foregoing a methodical search and almost giving in to imagination in an attempt to find a newly elegant and efficient way of making the sets pop out.&lt;/p&gt;

&lt;p&gt;But anyways, logic and patterns and puzzles have always made me tick. So perhaps it’s not surprising that when I left college (my supremely useful Gender &amp;amp; Sexuality Studies degree in hand), I pivoted toward math. After all, as G.H. Hardy says, “A mathematician, like a painter or poet, is a maker of patterns. If his patterns are more permanent than theirs, it is because they are made with ideas.” &lt;/p&gt;

&lt;p&gt;Over my years of teaching math, Pre-Calculus became my primary passion. Pre-Calc asks students to discard prior notions of math as a discipline bounded by rigid rules. It is a class that emphasizes the problem-solving process, moving away from a dependence on formulae and focusing instead on an investigative/exploratory approach. My goal is to foster a curious and thoughtful mindset, to urge students to experiment and to develop in them a willingness to move through ambiguity. Indeed, this is what I love most about math: the imperative creativity involved and the possibility for elegance. Perhaps driven by an abstract question or ultimate goal, the problem-solving process itself remains open-ended, the only limitations being our ability (or willingness) to imagine different paths towards a solution.  I’m enthralled by the search for simplicity amidst seeming chaos, the incisive equation that cuts through so many calculations and drives at the heart of the problem. There is beauty and art, I think, in tinkering and streamlining, asking discerning and deft questions, and crafting the most precise and graceful explanations.&lt;/p&gt;

&lt;p&gt;Programming is a natural extension of this type of thinking. As in Set, as in math, there’s a well-defined logic providing a framework, a structure. A language dictates certain rules of syntax and communication. But beyond that, it’s a wide open puzzle. It’s not just about getting from Point A to Point B. Achieving some product by brute force doesn't count. It’s about the how: How to nimbly navigate, to execute and maneuver with elegance and concision. &lt;/p&gt;

&lt;p&gt;So it may have started as a mere itch. My initial interest in software engineering may have stemmed mostly from a desire to immerse myself in a this type of thinking, one that seems particularly worth fostering in this ever-evolving, future-oriented world. But the bug has turned into a fully-fledged passion. &lt;/p&gt;

&lt;p&gt;As I've immersed myself more and more in software engineering, I've come to believe that software engineering is a potential-filled tool for empowerment. As someone who holds a deep-seated passion for social justice, I’m interested in finding a way to marry tech and engineering with work for social change. I want to empower students, youth, and underrepresented populations to speak with conviction, and I want to provide them with the relevant tools for letting themselves be heard. I want to use code to build technologies that address disparities rather than perpetuating them. I want to work to eliminate implicit or unintentional inequities in new technologies. I want to push tech companies to create a rich texture of voices, experiences, and stories in their workforces. I want to use my coding skills to bring folks together, to help organizations and social justice initiatives coordinate with one another, to engage a wider spectrum of society and start conversations, to offer a platform for discussion and collaboration. &lt;/p&gt;

&lt;p&gt;To be honest, I’m not sure how to do these things with code yet. But coding seems like a crucial tool for empowering people with information, reaching folks who have been traditionally underserved, and making connections among coalitions so that they might work together to maximize their impact. And so I'm here, learning to code. I'm here, pursuing new knowledge in the hopes that being able to code will help me pursue these bigger-picture changes.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
