<?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>Forem: Micah Shute</title>
    <description>The latest articles on Forem by Micah Shute (@micahshute).</description>
    <link>https://forem.com/micahshute</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%2F99039%2Fad1762d8-9e91-4c53-ab5a-afb74f145c29.jpg</url>
      <title>Forem: Micah Shute</title>
      <link>https://forem.com/micahshute</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/micahshute"/>
    <language>en</language>
    <item>
      <title>Strategy and Decorator Design Patterns</title>
      <dc:creator>Micah Shute</dc:creator>
      <pubDate>Tue, 19 Mar 2019 04:27:16 +0000</pubDate>
      <link>https://forem.com/micahshute/strategy-and-decorator-design-patterns-20j6</link>
      <guid>https://forem.com/micahshute/strategy-and-decorator-design-patterns-20j6</guid>
      <description>&lt;h1&gt;
  
  
  Why do I use a Decorator or Strategy?
&lt;/h1&gt;

&lt;p&gt;Or any design pattern, for that matter? In general, design patterns are created and used to promote &lt;a href="https://en.wikipedia.org/wiki/Composition_over_inheritance" rel="noopener noreferrer"&gt;object composition over inheritance&lt;/a&gt;, allow for &lt;a href="https://stackoverflow.com/questions/98984/black-box-vs-white-box-reuse" rel="noopener noreferrer"&gt;(black-box) code reuse&lt;/a&gt;, better enforce the &lt;a href="https://en.wikipedia.org/wiki/Single_responsibility_principle" rel="noopener noreferrer"&gt;single responsibility principle&lt;/a&gt;, and reduce the size and unwieldiness of your code's classes in general.&lt;br&gt;
Like any design pattern, Decorators and Strategies have specific scenarios when they are there are beneficial to use. These two patterns can have similar use cases, and it can be easy to confuse when you should use one or the other. According to [1], both Decorators and Strategies can be employed when your goal is an "alternative to extending functionality by subclassing". Strategies can also be used when you have classes with algorithmic dependencies, and Decorators can be used to easily alter the functionality of a class which itself is not easily changed.&lt;/p&gt;

&lt;p&gt;So what actually are they and how do you use them?&lt;br&gt;
Let's get specific. Decorators and Strategies are just extra classes I write to alter/extend the functionality of a class I have already written. The way they alter this functionality is different, and therefore they are useful in different scenarios. First, let's look at the class diagrams [1]:&lt;/p&gt;
&lt;h4&gt;
  
  
  Decorator
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0fmyp2afy4hgl1kzf13v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0fmyp2afy4hgl1kzf13v.png" alt="Decorator Class Diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What is this saying? If you haven't looked at too many class diagrams, or you are only familiar with &lt;a href="https://stackoverflow.com/questions/1517582/what-is-the-difference-between-statically-typed-and-dynamically-typed-languages" rel="noopener noreferrer"&gt;dynamically typed languages&lt;/a&gt;, it can be confusing. Each box with a bold title represents a class. In Ruby, we won't actually be programming all of the classes we would in Java or C++, for example.&lt;/p&gt;

&lt;p&gt;All of the boxes which do not say Concrete are the architecture of our inter-class APIs that we are designing. In statically typed languages, we have to define these in code as Interfaces, Prototypes, Abstract Classes, etc. depending on the language. In dynamically typed languages, they are defined in the documentation and in our minds as the engineers of the class ecosystem. There are ups and down to both statically and dynamically typed languages; statically typed classes error check for you, help you be more precise and cleaner in your code, and ensure you are designing your system correctly, while dynamically typed languages require less code and can be a lot simpler to create and read IF designed well and properly documented. If designed badly, they can be much harder to read and debug.&lt;br&gt;
But now getting back to the &lt;code&gt;Decorator&lt;/code&gt; Class Diagram; basically, this diagram tells us that we have a class &lt;code&gt;ConcreteComponent&lt;/code&gt; and we want to extend its functionality. This class has the functions and properties as defined by &lt;code&gt;Component&lt;/code&gt;. So, we make another class with the same API as &lt;code&gt;ConcreteComponent&lt;/code&gt; (i.e. it conforms to the &lt;code&gt;Component&lt;/code&gt; design) except that it has one extra reference: a &lt;code&gt;Component&lt;/code&gt; (which is going to be the original class you wanted to extend the functionality of or any decorator it is already wearing), and we call this new design &lt;code&gt;Decorator&lt;/code&gt;. We can make as many different types of &lt;code&gt;Decorator&lt;/code&gt; classes, as long as it adheres to this design.&lt;/p&gt;

&lt;p&gt;Above you can see that the &lt;code&gt;Component&lt;/code&gt; can do an &lt;code&gt;Operation()&lt;/code&gt;. So, our &lt;code&gt;Decorator&lt;/code&gt; also has to be able to do an &lt;code&gt;Operation()&lt;/code&gt;. Since our &lt;code&gt;Decorator&lt;/code&gt; has a reference to &lt;code&gt;Component&lt;/code&gt;, it just looks at how &lt;code&gt;Component&lt;/code&gt; does &lt;code&gt;Operation()&lt;/code&gt;, mimics that output, and then changes what it needs to and returns this new-and-improved output from its &lt;code&gt;Operation()&lt;/code&gt; method. That is what the dotted lines are showing you above.&lt;/p&gt;

&lt;p&gt;Pseudo-Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class NumberComponent
   func operation(x){
      return x
   }
end

class BinaryNumberDecorator
   constructor(component){
      this.c = component 
   }  
   func operation(x){
      return this.c.operation(x).toBinary()
   }
end

c = new NumberComponent()
d = new BinaryNumberDecorator(c)
x = 2
c.operation(x) // outputs what your original class returns
d.operation(x) // extends functionality of NumberComponent using the same function call
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'll show more complex, working ruby code below.&lt;/p&gt;

&lt;h4&gt;
  
  
  Strategy
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjnlvjl3pz6n3thidhw13.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjnlvjl3pz6n3thidhw13.png" alt="Strategy Class Diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, the &lt;code&gt;Context&lt;/code&gt; is the class I want to extend the functionality of. So, I make a &lt;code&gt;Strategy&lt;/code&gt; class that can perform that function. It is interchangeable because each &lt;code&gt;ConcreteStrategy&lt;/code&gt; conforms to the same &lt;code&gt;Strategy&lt;/code&gt; interface. Note that unlike the &lt;code&gt;Decorator&lt;/code&gt;, the &lt;code&gt;Strategy&lt;/code&gt; does not need to share an interface with &lt;code&gt;Context&lt;/code&gt;. This design pattern is convenient when the functionality I want is complex and can be implemented with different algorithms. Let's say I am creating a class which needs to perform the &lt;a href="https://medium.com/@micah.shute/divide-and-conquer-the-fast-fourier-transform-f61cb060710b" rel="noopener noreferrer"&gt;Fast Fourier Transform (FFT)&lt;/a&gt;. Since the FFT can be calculated in different ways, and I may want to switch to a faster/better algorithm in the future, I can implement a Strategy to perform the calculation.&lt;/p&gt;

&lt;p&gt;Pseudo-Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class DataContext
   constructor(data, fftStrategy = new Radix2Strategy()){
      this.data = data
      this.fftStrategy = fftStrategy
   }
   func fft(){
      return this.fftStrategy.fft(this.data)
   }
end

class BruteForceFFTStrategy
   func fft(data){
      ...perform brute force fft
      return calculated_fft
   }
end

class Radix2Strategy
   func fft(data){
      ...perform radix 2 strategy
      return calculated_fft
   }
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Intuition
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;Decorators&lt;/code&gt; are kind of like Russian nesting dolls. You take an object you want and nest it inside of your class which uses the inner functionality and adds onto it to makes it more functional. So actually, &lt;code&gt;decorators&lt;/code&gt; are more like in MIB when the little Arquillian is controlling the humanoid body inside the head. He is like the original &lt;code&gt;Component&lt;/code&gt; and the body is like a &lt;code&gt;Decorator&lt;/code&gt;. He could then decorate himself further by having his human decoration operate some sort of exoskeleton. At that point, the little alien and his exterior would have the same methods, like &lt;code&gt;moveArm()&lt;/code&gt; or &lt;code&gt;push()&lt;/code&gt;, but the decorated exoskeleton would have a much different output (i.e. he could push harder). As such, the &lt;code&gt;decorator&lt;/code&gt; has to have the same interfaces as the underlying class. It eats the original &lt;code&gt;Component&lt;/code&gt; and allows the world to interact with it the same way it would interact with the original &lt;code&gt;Component&lt;/code&gt;.&lt;br&gt;
Strategies, on the other hand, are kind of like replaceable cards in a robot. Imagine you pulled off the back plate and there were slots with digital cards inserted for each function such as eating, walking, talking, etc. You could take any of them out and replace them when an algorithm was updated or you wanted to change the behavior of the robot.&lt;br&gt;
In general, if you are wondering whether to use a &lt;code&gt;Strategy&lt;/code&gt; or &lt;code&gt;Decorator&lt;/code&gt; design pattern, a rule of thumb is to keep the base class simple in a &lt;code&gt;decorator&lt;/code&gt;. If the &lt;code&gt;Component&lt;/code&gt; is too complicated, you will have to mirror too many methods in each &lt;code&gt;decorator&lt;/code&gt;, and it will be better to use a &lt;code&gt;strategy&lt;/code&gt;.&lt;br&gt;
Also, decorators are widely used when you want to dynamically add functionality to an object, not necessarily an entire class (and perhaps withdraw this functionality at a later time). Strategies are commonly used to perform a function which is very complicated and can be performed in different ways (perhaps with different time/space complexities).&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Example
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Decorators:
&lt;/h4&gt;



&lt;div class="highlight js-code-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;IceCream&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;price: &lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="vi"&gt;@price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;price&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;price&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="vi"&gt;@price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;amt&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;price&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="vi"&gt;@price&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;ingredients&lt;/span&gt;
        &lt;span class="s2"&gt;"Ice Cream"&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;class&lt;/span&gt; &lt;span class="nc"&gt;WithJimmies&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="vi"&gt;@item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item&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;price&lt;/span&gt;
        &lt;span class="vi"&gt;@item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;price&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.5&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;ingredients&lt;/span&gt;
        &lt;span class="vi"&gt;@item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ingredients&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;", Jimmies"&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;class&lt;/span&gt; &lt;span class="nc"&gt;WithChocolateSyrup&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="vi"&gt;@item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item&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;price&lt;/span&gt;
        &lt;span class="vi"&gt;@item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;price&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.2&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;ingredients&lt;/span&gt;
        &lt;span class="vi"&gt;@item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ingredients&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;", Chocolate Syrup"&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;class&lt;/span&gt; &lt;span class="nc"&gt;WithOreos&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="vi"&gt;@item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item&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;price&lt;/span&gt;
        &lt;span class="vi"&gt;@item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;price&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;1.0&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;ingredients&lt;/span&gt;
        &lt;span class="vi"&gt;@item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ingredients&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;", Oreos"&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;class&lt;/span&gt; &lt;span class="nc"&gt;FroYo&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;price: &lt;/span&gt;&lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="vi"&gt;@price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;price&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;price&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="vi"&gt;@price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;amt&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;price&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="vi"&gt;@price&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;ingredients&lt;/span&gt;
        &lt;span class="s2"&gt;"Froyo"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


&lt;span class="n"&gt;treat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;IceCream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;treat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;WithJimmies&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="n"&gt;treat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;treat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;WithOreos&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="n"&gt;treat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;treat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;WithChocolateSyrup&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="n"&gt;treat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;treat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ingredients&lt;/span&gt; &lt;span class="c1"&gt;# "Ice Cream, Jimmies, Oreos, Chocolate Syrup"&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;treat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;price&lt;/span&gt; &lt;span class="c1"&gt;# 2.7&lt;/span&gt;
&lt;span class="n"&gt;another_treat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;FroYo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;another_treat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;WithJimmies&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="n"&gt;another_treat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;treat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ingredients&lt;/span&gt; &lt;span class="c1"&gt;# "Froyo, Jimmies"&lt;/span&gt;
&lt;span class="c1"&gt;# Froyo and Ice Cream (Components) and all of the Decorators have #price and #ingredients&lt;/span&gt;
&lt;span class="c1"&gt;# methods, making them conform to the same interface.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Strategies:
&lt;/h4&gt;



&lt;div class="highlight js-code-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;ChocolateSyrup&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;price&lt;/span&gt;
        &lt;span class="mf"&gt;0.2&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;ingredients&lt;/span&gt;
        &lt;span class="s2"&gt;"Chocolate Syrup"&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;class&lt;/span&gt; &lt;span class="nc"&gt;Jimmies&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;price&lt;/span&gt;
        &lt;span class="mf"&gt;0.5&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;ingredients&lt;/span&gt;
        &lt;span class="s2"&gt;"Jimmies"&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;class&lt;/span&gt; &lt;span class="nc"&gt;Oreos&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;price&lt;/span&gt;
        &lt;span class="mf"&gt;1.0&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;ingredients&lt;/span&gt;
        &lt;span class="s2"&gt;"Oreos"&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;class&lt;/span&gt; &lt;span class="nc"&gt;IceCream&lt;/span&gt;

    &lt;span class="nb"&gt;attr_accessor&lt;/span&gt; &lt;span class="ss"&gt;:toppings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:price_strategy&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;toppings: &lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;price_strategy: &lt;/span&gt;&lt;span class="no"&gt;CalculatePriceStandardStrategy&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="vi"&gt;@toppings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;toppings&lt;/span&gt;
        &lt;span class="vi"&gt;@price_strategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;price_strategy&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;price&lt;/span&gt;
        &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;price_strategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;calculate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toppings&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;def&lt;/span&gt; &lt;span class="nf"&gt;ingredients&lt;/span&gt;
        &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toppings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;"Ice Cream, "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toppings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ss"&gt;:ingredients&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;", "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Ice Cream"&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;class&lt;/span&gt; &lt;span class="nc"&gt;CalculatePriceStandardStrategy&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;toppings&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;toppings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;cum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;cum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;price&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;class&lt;/span&gt; &lt;span class="nc"&gt;CalculatePriceRewardsMemberStrategy&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;toppings&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;toppings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;cum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;cum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;price&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="n"&gt;toppings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;ChocolateSyrup&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;Jimmies&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;Oreos&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="n"&gt;strategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;CalculatePriceStandardStrategy&lt;/span&gt;
&lt;span class="n"&gt;treat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;IceCream&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="ss"&gt;toppings: &lt;/span&gt;&lt;span class="n"&gt;toppings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;price_strategy: &lt;/span&gt;&lt;span class="n"&gt;strategy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;treat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ingredients&lt;/span&gt; &lt;span class="c1"&gt;# Ice Cream, Chocolate Syrup, Jimmies, Oreos&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;treat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;price&lt;/span&gt; &lt;span class="c1"&gt;# 2.7&lt;/span&gt;
&lt;span class="n"&gt;treat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;price_strategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;CalculatePriceRewardsMemberStrategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;treat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;price&lt;/span&gt; &lt;span class="c1"&gt;# 1.86&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That covers the basics. You can see more in-depth descriptions and discussion in the reference below.&lt;/p&gt;

&lt;h5&gt;
  
  
  References:
&lt;/h5&gt;

&lt;p&gt;[1] DESIGN PATTERNS Elements of Reusable Object-Oriented Software, Gamma, Helm, Johnson, Vlissides&lt;/p&gt;

</description>
      <category>designpatterns</category>
      <category>decorator</category>
      <category>strategy</category>
      <category>ruby</category>
    </item>
    <item>
      <title>Resource Summary for Simple Rails Features</title>
      <dc:creator>Micah Shute</dc:creator>
      <pubDate>Thu, 20 Dec 2018 06:44:02 +0000</pubDate>
      <link>https://forem.com/micahshute/resource-summary-for-simple-rails-features-ped</link>
      <guid>https://forem.com/micahshute/resource-summary-for-simple-rails-features-ped</guid>
      <description>&lt;h2&gt;
  
  
  I made my first rails app last week, and here are some resources and strategies I used to make it work
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Google Authentication
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/zquestz/omniauth-google-oauth2"&gt;Google OAuth gem&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# config/initializers/omniauth.rb&lt;/span&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;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt; &lt;span class="no"&gt;OmniAuth&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Builder&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="ss"&gt;:google_oauth2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'GOOGLE_KEY'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'GOOGLE_SECRET'&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;ul&gt;
&lt;li&gt;You can add a &lt;code&gt;google_uid&lt;/code&gt; column and a &lt;code&gt;google_refresh_token&lt;/code&gt; to the &lt;code&gt;user&lt;/code&gt; table if you need a unique property with which to query a user, or you want to use more advanced features of Google's API (and allow an offline refresh of the token). Because I have a uniqueness validation of a user's &lt;code&gt;email&lt;/code&gt; and I am only using Google for authentication, I didn't need those columns but added them anyway just in case I had a design change in the future.&lt;/li&gt;
&lt;li&gt;In my schema, I made a &lt;code&gt;user&lt;/code&gt;'s &lt;code&gt;email&lt;/code&gt; validate uniqueness so that logging in with Google could create a whole new account, or find an account with that email and update a &lt;code&gt;google_uid&lt;/code&gt; property to it without altering the password. 

&lt;ul&gt;
&lt;li&gt;To make this method foolproof, it would be important to have a user verify their email if the account is made traditionally (ie without OAuth). &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;You need to have an action dedicated to handling the OAuth callback. 

&lt;ul&gt;
&lt;li&gt;This action needs to be associated with the callback route you specify in the Google API page (the link to that page is on the GitHub of the Google OAuth gem linked above.)&lt;/li&gt;
&lt;li&gt;My custom route for the callback that I defined in my &lt;code&gt;routes.rb&lt;/code&gt; file was: &lt;code&gt;get 'auth/google_oauth2/callback', to: 'sessions#googleAuth'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;My callback action in my &lt;code&gt;SessionsController&lt;/code&gt; utilized a custom class method written in the &lt;code&gt;User&lt;/code&gt; model, to which it passed the return from the OAuth process, like so:
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;#  SessionController#googleAuth&lt;/span&gt;
    &lt;span class="n"&gt;access_token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"omniauth.auth"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&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;from_google&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;access_token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;#  User.rb&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_google&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;refresh_token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;refresh_token&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;found_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;email: &lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="n"&gt;found_user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;google_uid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;token&lt;/span&gt;
            &lt;span class="n"&gt;found_user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;google_refresh_token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;refresh_token&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;refresh_token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;present?&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;found_user&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="n"&gt;new_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;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;
                &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;
                &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;google_uid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;token&lt;/span&gt;
                &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;google_refresh_token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;refresh_token&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;refresh_token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;present?&lt;/span&gt;
                &lt;span class="n"&gt;rand_password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;RandomPasswordStrategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random_password&lt;/span&gt;
                &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rand_password&lt;/span&gt;
                &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;password_confirmation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rand_password&lt;/span&gt;
            &lt;span class="k"&gt;end&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;new_user&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;ul&gt;
&lt;li&gt;From there, you just check to see if the user is valid, and log them in if it is, and otherwise display an error.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;RandomPasswordStrategy&lt;/code&gt; is just a class I made that uses the &lt;code&gt;sysrandom/securerandom&lt;/code&gt; method &lt;code&gt;SecureRandom.hex(64)&lt;/code&gt; combined with random ordering of required symbols and numbers (as required by the password policy) to create a complex, valid random password.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Authorization Methods, Error Pages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;I put a lot of private methods in my &lt;code&gt;ApplicationController&lt;/code&gt; to abstract away authorization throughout my app, making it easier to authenticate a user in the correct manner and display an appropriate message to them if there was an issue. &lt;/li&gt;
&lt;li&gt;I wanted logged out users to be able to see most of the app, and then restrict other parts of it to only users with accounts. There are some aspects that only specific users have access to, such as editing your own posts, etc. &lt;/li&gt;
&lt;li&gt;Some pages will show differently based on whether or not the user is logged in. To accomplish this simply, I added two methods to the &lt;code&gt;ApplicationController&lt;/code&gt; so it is available to all Controllers (which inherit from &lt;code&gt;ApplicationController&lt;/code&gt;), as well as adding them as &lt;code&gt;helper_methods&lt;/code&gt; to make them available in the Views if necessary:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;#  application_controller.rb&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="n"&gt;helper_method&lt;/span&gt; &lt;span class="ss"&gt;:current_user&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;current_user&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;id: &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;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="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;These are primarily used as decision-makers on what is shown on certain pages, or building blocks to more advanced authorization methods. &lt;/li&gt;
&lt;li&gt;If an unauthorized user tries to access a page you don't want them to, it is appropriate to show a 403 error page. I accomplished this by creating a &lt;code&gt;public/403.html.erb&lt;/code&gt; file, and calling it via another method in &lt;code&gt;ApplicationController&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# application_controller.rb&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;not_authorized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"You are not authorized to view that page"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;flash&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:danger&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;
    &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:file&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'public/403.html.erb'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;:status&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:layout&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;false&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;ul&gt;
&lt;li&gt;Which can accept a custom flash message as a parameter, and which serves as a good building block for other methods, like this:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# application_controller.rb&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;authorize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt;
        &lt;span class="n"&gt;not_authorized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;a href="/login"&amp;gt;Login&amp;lt;/a&amp;gt; or &amp;lt;a href="/signup"&amp;gt;Signup&amp;lt;/a&amp;gt; to view this page!'&lt;/span&gt;&lt;span class="p"&gt;)&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="o"&gt;!!&lt;/span&gt;&lt;span class="n"&gt;current_user&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;current_user&lt;/span&gt;
            &lt;span class="n"&gt;not_authorized&lt;/span&gt;
            &lt;span class="kp"&gt;false&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="kp"&gt;true&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;ul&gt;
&lt;li&gt;If the above is called without a user parameter, it will only display a 403 error page if the user is not logged in. If it is called with a user, the 403 will be called unless that specific user is logged in. It also returns a boolean to indicate success or failure. If you need to use &lt;code&gt;current_user&lt;/code&gt; in the controller after calling &lt;code&gt;authorize&lt;/code&gt;, you will get an error if the authorization fails. An easy way to fix this is to use an &lt;code&gt;if-else&lt;/code&gt; block with the authorization check rather than using it as a standalone function so that any code which calls current_user will not be run unless authorization succeeds. For this to work, a boolean (or at least truthy and falsy) value must be returned. If the authorization fails, it will return false and then once the controller action is complete it will render the 403 error page. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Following Users, Sending Messages, Reacting to Posts, Scope Methods
&lt;/h3&gt;

&lt;p&gt;For some relationships, ActiveRecord relations aren't as simple as &lt;code&gt;has_many :classes, through: :user_classes&lt;/code&gt; or something like that. 3 Situations particularly I had to get more creative to make work:&lt;/p&gt;

&lt;h4&gt;
  
  
  Following other Users:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Many to many relationships, ie a user is following many users and is followed by many users.&lt;/li&gt;
&lt;li&gt;The answer to the problem is just a simple join table, but it's just slightly different than a standard join table, as it joins a table to itself, and requires a few extra words in the ActiveRecord class methods. The join table I used was:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# schema.rb&lt;/span&gt;

&lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="s2"&gt;"following_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;integer&lt;/span&gt; &lt;span class="s2"&gt;"following_id"&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;integer&lt;/span&gt; &lt;span class="s2"&gt;"follower_id"&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;ul&gt;
&lt;li&gt;And then to make the User model work correctly:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# user.rb&lt;/span&gt;

&lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:following_users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;foreign_key: &lt;/span&gt;&lt;span class="s2"&gt;"follower_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;dependent: :destroy&lt;/span&gt;
&lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:follower_users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;class_name: &lt;/span&gt;&lt;span class="s2"&gt;"FollowingUser"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;foreign_key: &lt;/span&gt;&lt;span class="s2"&gt;"following_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;dependent: :destroy&lt;/span&gt;
&lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:followers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;class_name: &lt;/span&gt;&lt;span class="s2"&gt;"User"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;through: :follower_users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;foreign_key: &lt;/span&gt;&lt;span class="s2"&gt;"follower_id"&lt;/span&gt;
&lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:following&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;class_name: &lt;/span&gt;&lt;span class="s2"&gt;"User"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;through: :following_users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;foreign_key: &lt;/span&gt;&lt;span class="s2"&gt;"following_id"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Messaging
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;This was pretty similar to implementing following/followers, except the model &lt;code&gt;Message&lt;/code&gt; is the join table, and is also the model that we are interested in, so it is simply just:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# schema.rb&lt;/span&gt;

&lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="s2"&gt;"messages"&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;integer&lt;/span&gt; &lt;span class="s2"&gt;"sender_id"&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;integer&lt;/span&gt; &lt;span class="s2"&gt;"reciever_id"&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;text&lt;/span&gt; &lt;span class="s2"&gt;"content"&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="s2"&gt;"viewed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;default: &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;"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;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# user.rb&lt;/span&gt;

&lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:sent_messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:class_name&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Message"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:foreign_key&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"sender_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;dependent: :destroy&lt;/span&gt;
&lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:recieved_messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:class_name&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Message"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:foreign_key&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"reciever_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;dependent: :destroy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Reacting to Posts
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;There were a few solutions to this problem I considered, but I decided to make a table &lt;code&gt;ReactionType&lt;/code&gt; which has a many-to-many polymorphic relationship to anything that is &lt;code&gt;reactable&lt;/code&gt;, in my case &lt;code&gt;Topic&lt;/code&gt;s and &lt;code&gt;Post&lt;/code&gt;s. &lt;code&gt;Reactions&lt;/code&gt; were the join tables between the &lt;code&gt;reactables&lt;/code&gt; and the &lt;code&gt;ReactionTypes&lt;/code&gt;. I did this instead of &lt;code&gt;Reaction&lt;/code&gt; holding the reaction type via a string in order to minimize errors (ie spelling errors), and allow for flexibility, for example, easy expansion of allowed &lt;code&gt;ReactionTypes&lt;/code&gt; in the future. 

&lt;ul&gt;
&lt;li&gt;Doing it this way made &lt;code&gt;Reactions&lt;/code&gt; a 3-way join table between &lt;code&gt;User&lt;/code&gt;, &lt;code&gt;reactables&lt;/code&gt;, and &lt;code&gt;ReactionType&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ReactionType&lt;/code&gt;s have to be seeded to the types you want to be available to the user. I had &lt;code&gt;like&lt;/code&gt;, &lt;code&gt;dislike&lt;/code&gt;, &lt;code&gt;genius&lt;/code&gt;, and &lt;code&gt;report&lt;/code&gt;.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# schema.rb&lt;/span&gt;

  &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="s2"&gt;"reaction_types"&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;"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;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;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="s2"&gt;"reactions"&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;integer&lt;/span&gt; &lt;span class="s2"&gt;"user_id"&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;"reactable_type"&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;bigint&lt;/span&gt; &lt;span class="s2"&gt;"reactable_id"&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;integer&lt;/span&gt; &lt;span class="s2"&gt;"reaction_type_id"&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="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"reactable_type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"reactable_id"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s2"&gt;"index_reactions_on_reactable_type_and_reactable_id"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

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





&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# reaction.rb&lt;/span&gt;

  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:reaction_type&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:reactable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;polymorphic: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# post.rb&lt;/span&gt;

&lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:reactions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;as: :reactable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;dependent: :destroy&lt;/span&gt;
&lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:reaction_types&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;through: :reactions&lt;/span&gt;

&lt;span class="c1"&gt;#topic.rb&lt;/span&gt;

&lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:reactions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;as: :reactable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;dependent: :destroy&lt;/span&gt;
&lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:reaction_types&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;through: :reactions&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;In the same fashion using polymorphic relationships, you can create tags that can be attached to &lt;code&gt;taggables&lt;/code&gt;, and post replies to things which are &lt;code&gt;postable&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Advanced ActiveRecord class methods
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;When I was trying to make the correct ActiveRecord class methods to retrieve specific "statistics" for a user dashboard or to find popular topics for my homepage, I found that the best resource for me was to see other advanced and specific class methods and use those examples as a reference. I will put some of mine here in the hopes that others can use it as a reference.

&lt;ul&gt;
&lt;li&gt;To create a "spotlight topic" of the day for my homepage - take the most positively reacted topic in the past 24 hours:
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# topic.rb&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trending_today&lt;/span&gt;
    &lt;span class="no"&gt;Topic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;joins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:reaction_types&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;reaction_types: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'like'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'genius'&lt;/span&gt;&lt;span class="p"&gt;]},&lt;/span&gt; &lt;span class="ss"&gt;classroom_id: &lt;/span&gt;&lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;reactions: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;created_at: &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;)}).&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Arel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'count(reaction_type_id) DESC'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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;ul&gt;
&lt;li&gt;Find the most reacted &lt;code&gt;Topic&lt;/code&gt; by &lt;code&gt;User&lt;/code&gt; and &lt;code&gt;reaction_type&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;#topic.rb&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;most_liked_by_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;most_reacted_type_by_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'like'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit&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="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="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;most_reacted_type_by_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;
        &lt;span class="no"&gt;Topic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;joins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:reaction_types&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;reaction_types: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="ss"&gt;user_id: &lt;/span&gt;&lt;span class="n"&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="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Arel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'count(reaction_type_id) DESC'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="no"&gt;Topic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;joins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:reaction_types&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;reaction_types: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="ss"&gt;user_id: &lt;/span&gt;&lt;span class="n"&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="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Arel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'count(reaction_type_id) DESC'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;limit&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="c1"&gt;#user.rb&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;most_liked_topics&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;Topic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;most_liked_by_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit&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;h3&gt;
  
  
  Setting up Bootstrap
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://medium.freecodecamp.org/add-bootstrap-to-your-ruby-on-rails-project-8d76d70d0e3b"&gt;This post&lt;/a&gt; walks through how to set up your rails app with bootstrap in just a few minutes.&lt;/li&gt;
&lt;li&gt;There is a complication with bootstrap that won't be ideal right 'out of the box' -&amp;gt; while rails will give your &lt;code&gt;form_for&lt;/code&gt; fields the &lt;code&gt;fields_with_errors&lt;/code&gt; class automatically when there are issues with the form inputs, Bootstrap will not respond to it. Instead, it responds to the class &lt;code&gt;is-invalid&lt;/code&gt;.

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://jasoncharnes.com/bootstrap-4-rails-fields-with-errors/"&gt;This blog&lt;/a&gt; shows a working good solution to make form errors work well with rails. It just includes adding a file and code to your &lt;code&gt;config/initializers&lt;/code&gt; folder, and basically, all it does is change the default &lt;code&gt;field-with-errors&lt;/code&gt; class to &lt;code&gt;is-invalid&lt;/code&gt; instead, which is what bootstrap uses to indicate a field which was filled out incorrectly.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Rendering Markdown
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;I was between the two libraries &lt;code&gt;redcarpet&lt;/code&gt; and &lt;code&gt;kramdown&lt;/code&gt;. I ended up choosing &lt;a href="https://github.com/gettalong/kramdown"&gt;kamdown&lt;/a&gt; because:

&lt;ul&gt;
&lt;li&gt;It is more recently committed and seems to be maintained more&lt;/li&gt;
&lt;li&gt;Its popularity is growing while &lt;code&gt;redcarpet&lt;/code&gt; is decreasing&lt;/li&gt;
&lt;li&gt;It allows integration with &lt;code&gt;MathJax&lt;/code&gt; which allows LaTex rendering.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Getting basic integration was relatively simple. It got a little more complicated to achieve the following 2 goals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Syntax highlighting for code&lt;/li&gt;
&lt;li&gt;Being able to sanitize the user's input while allowing all of the Markdown features to implement correctly.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I decided to use &lt;a href="https://github.com/jneen/rouge"&gt;rouge&lt;/a&gt; for syntax highlighting. I'll show you the code below to get it working with Kramdown, but the hard piece of information to find was how to get the proper CSS files that make the highlighting happen. Here's a good &lt;a href="https://stackoverflow.com/questions/43905103/kramdown-rouge-doesnt-highlight-syntax"&gt;stack overflow answer&lt;/a&gt; that's hard to find. Basically, once you tell &lt;code&gt;kramdown&lt;/code&gt; that you want to use &lt;code&gt;rouge&lt;/code&gt; (and you have installed both the &lt;code&gt;kramdown gem&lt;/code&gt; and the &lt;code&gt;rouge gem&lt;/code&gt;), you can run &lt;code&gt;rougify help style&lt;/code&gt; in your terminal, and you can see all of the custom CSS files you can add to your &lt;code&gt;app/assets/stylesheets&lt;/code&gt; path. To get the raw CSS, type &lt;code&gt;rougify style&lt;/code&gt; followed by one of the allowed styles. For example: &lt;code&gt;rougify style colorful&lt;/code&gt;. The CSS will be printed in your terminal. You could also run&lt;br&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rougify style colorful &amp;gt; ./app/assets/stylesheets/rouge_style.css
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Now, it's relatively easy to render markdown. I made a helper method to make it extra simple:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# application_helper.rb&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;render_markdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;markdown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="s1"&gt;'components/content'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;markdown: &lt;/span&gt;&lt;span class="no"&gt;Kramdown&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Document&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="n"&gt;markdown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;parse_block_html: &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;syntax_highlighter: :rouge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;syntax_highlighter_opts: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;line_numbers: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;to_html&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

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





&lt;div class="highlight"&gt;&lt;pre class="highlight erb"&gt;&lt;code&gt;
&lt;span class="c"&gt;&amp;lt;!-- views/components/_content.html.erb --&amp;gt;&lt;/span&gt;

&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;sanitize_markdown&lt;/span&gt; &lt;span class="n"&gt;markdown&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;

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



&lt;ul&gt;
&lt;li&gt;Custom sanitize method:

&lt;ul&gt;
&lt;li&gt;As you can see here, I am not using &lt;code&gt;raw&lt;/code&gt; or &lt;code&gt;.html_safe&lt;/code&gt; to render this HTML data because ultimately it &lt;em&gt;came from a user and cannot be trusted&lt;/em&gt;. However, the safe &lt;code&gt;sanitize&lt;/code&gt; method disallows certain things I want to be rendered, such as tables. You can get proper sanitation AND your desired HTML tags by manually appending to the whitelisted tags allowed through &lt;code&gt;sanitize&lt;/code&gt; by doing something like what is shown below.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# application_helper.rb&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sanitize_markdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sanitize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;tags:  &lt;/span&gt;&lt;span class="no"&gt;Loofah&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTML5&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;WhiteList&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ALLOWED_ELEMENTS_WITH_LIBXML2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sx"&gt;%w(table th td tr span)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;attibutes: &lt;/span&gt;&lt;span class="no"&gt;Loofah&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTML5&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;WhiteList&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ALLOWED_ATTRIBUTES&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sx"&gt;%w( style )&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;h3&gt;
  
  
  General tips
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Set up the app with PostgreSQL

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dev.to/micahshute/setting-up-windows-subsytem-for-linux-3b7n"&gt;Here's a blog post&lt;/a&gt; I wrote about setting up WSL, but there's a section at the bottom that covers using pgAdmin and setting up a Rails app with PostgreSQL&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Save all secret keys as environment variables. I used &lt;a href="https://github.com/laserlemon/figaro"&gt;Figaro&lt;/a&gt; to make it easy.&lt;/li&gt;
&lt;li&gt;Avoid the N+1 problem

&lt;ul&gt;
&lt;li&gt;This occurs when you get a collection of models, of which you want to query and show nested models. If you iterate over your models &lt;code&gt;n&lt;/code&gt; times to do this, you are making &lt;code&gt;n+1&lt;/code&gt; database calls which can be quite expensive with large amounts of data, especially when requesting over a network. This is easily fixed by using the &lt;code&gt;includes&lt;/code&gt; method when making your initial query. &lt;a href="https://guides.rubyonrails.org/active_record_querying.html"&gt;Check this site out&lt;/a&gt; and go to the section called "Solution to N + 1 queries problem" for more info. &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Clean up the database automatically when objects are destroyed

&lt;ul&gt;
&lt;li&gt;When you appropriately add
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="ss"&gt;dependent: :destroy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;to your ActiveRecord class methods (examples can be seen in code snippets above), you are telling ActiveRecord to destroy these relations upon the destruction of the model. As you can see above, I implemented this for &lt;code&gt;reactions&lt;/code&gt; within &lt;code&gt;post.rb&lt;/code&gt;. This tells rails that when a &lt;code&gt;post&lt;/code&gt; is destroyed, all user &lt;code&gt;reactions&lt;/code&gt; to it should also be destroyed. This prevents disconnected likes and dislikes, etc, from floating around in your database for no reason. Also, note this should be a one-sided relationship. You would not want a &lt;code&gt;post&lt;/code&gt; to be destroyed if a user destroys their one reaction to it.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding custom files and classes

&lt;ul&gt;
&lt;li&gt;There are going to be things you want your app to do that are outside of MVC. This means you are going to want to add files outside of the standard &lt;code&gt;model&lt;/code&gt;, &lt;code&gt;view&lt;/code&gt; and &lt;code&gt;controller&lt;/code&gt; directories. Here are some resources with advice on how to do this:&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/15260984/guidelines-for-where-to-put-classes-in-rails-apps-that-dont-fit-anywhere"&gt;A StackOverflow answer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/maxim/6503591"&gt;A GitHub gist post&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Personally, I used a &lt;code&gt;lib&lt;/code&gt; directory in my &lt;code&gt;app&lt;/code&gt; directory because it is eagerly loaded in production and lazy loaded in development. I did not need to alter any configuration or environment files for the classes within files in that directory were referenced.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>beginners</category>
      <category>rails</category>
      <category>ruby</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Divide and Conquer the Fast Fourier Transform</title>
      <dc:creator>Micah Shute</dc:creator>
      <pubDate>Wed, 07 Nov 2018 07:18:06 +0000</pubDate>
      <link>https://forem.com/micahshute/divide-and-conquer-the-fast-fourier-transform-c5g</link>
      <guid>https://forem.com/micahshute/divide-and-conquer-the-fast-fourier-transform-c5g</guid>
      <description>&lt;h2&gt;
  
  
  What is the Fourier Transform and why should I care
&lt;/h2&gt;

&lt;p&gt;Simply put, the Fourier Transform allows humans or machines to see time domain signals in the frequency domain. Common applications are data visualization in oscilloscopes and function generators, radar, sonar, &lt;a href="https://en.wikipedia.org/wiki/Fourier-transform_spectroscopy"&gt;spectral analysis&lt;/a&gt;, digital communication signal processing, and instrument monitoring.&lt;/p&gt;

&lt;p&gt;There is also a broad range of uses for the Fourier Transform beyond visualization or even an end game of frequency analysis. Linear Time Invariant (LTI) systems and signals respond to each other through &lt;a href="https://en.wikipedia.org/wiki/Convolution"&gt;convolution&lt;/a&gt;, which can be a mathematically impractical operation to evaluate. These system outputs can be modeled accurately by simply multiplying their Fourier Transforms together and then converting them back to the time domain, given that we avoid aliasing when doing so. &lt;/p&gt;

&lt;p&gt;Lastly, a lot of data compression uses algorithms similar to the Fast Fourier Transform. For example, &lt;a href="https://en.wikipedia.org/wiki/Discrete_cosine_transform"&gt;JPEGs use the Discrete Cosine Transform&lt;/a&gt; which is very similar to the Discrete Fourier Transform.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why and how does it work
&lt;/h2&gt;

&lt;p&gt;This is a question with a long answer. Here's the short and dirty:&lt;/p&gt;

&lt;p&gt;This is the equation to convert a time domain signal x(t) to a frequency domain signal X(f):  &lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.codecogs.com/eqnedit.php?latex=%24X(f)&amp;amp;space;=&amp;amp;space;%5Cint_%7B-%5Cinfty%7D%5E%7B%5Cinfty%7D%7Bx(t)%7De%5E%7B-j2%5Cpi&amp;amp;space;t%7Ddt%24"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Mvj0n7et--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://latex.codecogs.com/gif.latex%3F%2524X%28f%29%26space%3B%3D%26space%3B%255Cint_%257B-%255Cinfty%257D%255E%257B%255Cinfty%257D%257Bx%28t%29%257De%255E%257B-j2%255Cpi%26space%3Bt%257Ddt%2524" title="$X(f) = \int_{-\infty}^{\infty}{x(t)}e^{-j2\pi t}dt$"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Where t is time and f is frequency in Hz.&lt;/p&gt;

&lt;p&gt;If you haven't seen this before it doesn't make much sense. Without getting caught up in the math, here's what you need to know:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Almost all signals that exist can be made up of a summation of cosine and sine signals, even aperiodic continuous time signals. 

&lt;ul&gt;
&lt;li&gt;For example, a decaying exponential signal &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="http://www.codecogs.com/eqnedit.php?latex=%24x(t)&amp;amp;space;=&amp;amp;space;e%5E%7B-t%7Du(t)%24"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CP9h044S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://latex.codecogs.com/gif.latex%3F%2524x%28t%29%26space%3B%3D%26space%3Be%255E%257B-t%257Du%28t%29%2524" title="$x(t) = e^{-t}u(t)$"&gt;&lt;/a&gt; has the frequencies: &lt;a href="http://www.codecogs.com/eqnedit.php?latex=X(f)&amp;amp;space;=&amp;amp;space;%5Cfrac%7B1%7D%7B1&amp;amp;space;&amp;amp;plus;&amp;amp;space;j2%5Cpi&amp;amp;space;f%7D"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qttXKSgG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://latex.codecogs.com/gif.latex%3FX%28f%29%26space%3B%3D%26space%3B%255Cfrac%257B1%257D%257B1%26space%3B%26plus%3B%26space%3Bj2%255Cpi%26space%3Bf%257D" title="X(f) = \frac{1}{1 + j2\pi f}"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;whose magnitudes look like this:&lt;br&gt;
    - &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--99E98kUm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/qmsde0ac0zkp70meiz62.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--99E98kUm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/qmsde0ac0zkp70meiz62.png" alt="Fourier Transform"&gt;&lt;/a&gt;&lt;br&gt;
    - You may recognize that a capacitor responds to a voltage impulse via an exponential decay, slowly discharging its built up voltage over time. So, the fact that the frequency makeup of the exponential decay is large for lower frequencies and small for higher frequencies makes sense intuitively, because the voltage across a capacitor will only look like the input when the input changes values slowly enough to allow this discharge process to take place. This is why the frequency range looks the way it does in this case.&lt;br&gt;
    - Note: Negative frequencies are part of both sine and cosine signals. it is what keeps time signals "real" when we mathematically model them as will be explained below. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We can make mathematically convenient equations using Euler's property:

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.codecogs.com/eqnedit.php?latex=e%5E%7Bj2%5Cpi&amp;amp;space;ft%7D&amp;amp;space;=&amp;amp;space;%5Ccos(2%5Cpi&amp;amp;space;ft)&amp;amp;space;&amp;amp;plus;&amp;amp;space;j%5Csin(2%5Cpi&amp;amp;space;ft)"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8FiTSbGE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://latex.codecogs.com/gif.latex%3Fe%255E%257Bj2%255Cpi%26space%3Bft%257D%26space%3B%3D%26space%3B%255Ccos%282%255Cpi%26space%3Bft%29%26space%3B%26plus%3B%26space%3Bj%255Csin%282%255Cpi%26space%3Bft%29" title="e^{j2\pi ft} = \cos(2\pi ft) + j\sin(2\pi ft)"&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.codecogs.com/eqnedit.php?latex=e%5E%7B-j2%5Cpi&amp;amp;space;ft%7D&amp;amp;space;=&amp;amp;space;%5Ccos(2%5Cpi&amp;amp;space;ft)&amp;amp;space;-&amp;amp;space;j%5Csin(2%5Cpi&amp;amp;space;ft)"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DnXTende--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://latex.codecogs.com/gif.latex%3Fe%255E%257B-j2%255Cpi%26space%3Bft%257D%26space%3B%3D%26space%3B%255Ccos%282%255Cpi%26space%3Bft%29%26space%3B-%26space%3Bj%255Csin%282%255Cpi%26space%3Bft%29" title="e^{-j2\pi ft} = \cos(2\pi ft) - j\sin(2\pi ft)"&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.codecogs.com/eqnedit.php?latex=%5Ccos(2%5Cpi&amp;amp;space;ft)&amp;amp;space;=&amp;amp;space;%5Cfrac12(e%5E%7Bj2%5Cpi&amp;amp;space;t%7D&amp;amp;space;&amp;amp;plus;&amp;amp;space;e%5E%7B-j2%5Cpi&amp;amp;space;t%7D)"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--onxvJi9s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://latex.codecogs.com/gif.latex%3F%255Ccos%282%255Cpi%26space%3Bft%29%26space%3B%3D%26space%3B%255Cfrac12%28e%255E%257Bj2%255Cpi%26space%3Bt%257D%26space%3B%26plus%3B%26space%3Be%255E%257B-j2%255Cpi%26space%3Bt%257D%29" title="\cos(2\pi ft) = \frac12(e^{j2\pi t} + e^{-j2\pi t})"&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://www.codecogs.com/eqnedit.php?latex=%5Csin(2%5Cpi&amp;amp;space;ft)&amp;amp;space;=&amp;amp;space;%5Cfrac%7B1%7D%7B2j%7D(e%5E%7Bj2%5Cpi&amp;amp;space;t%7D&amp;amp;space;-&amp;amp;space;e%5E%7B-j2%5Cpi&amp;amp;space;t%7D)"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4Kt23P4V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://latex.codecogs.com/gif.latex%3F%255Csin%282%255Cpi%26space%3Bft%29%26space%3B%3D%26space%3B%255Cfrac%257B1%257D%257B2j%257D%28e%255E%257Bj2%255Cpi%26space%3Bt%257D%26space%3B-%26space%3Be%255E%257B-j2%255Cpi%26space%3Bt%257D%29" title="\sin(2\pi ft) = \frac{1}{2j}(e^{j2\pi t} - e^{-j2\pi t})"&gt;&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Don't be confused about the imaginary numbers. They are a way to show phase angle data in the frequency domain. Real time signals will never become "imaginary" time signals - the imaginary parts will always cancel out to give you a mixture of sines and cosines. &lt;/li&gt;
&lt;li&gt;Note that this shows why negative frequencies are necessary to model sinusoids in this way.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, if we know from (1) that all signals can be made up of a summation of sines and cosines, we can manipulate that fact to retrieve those cosines and sines from a time signal. These retrieved sines and cosines are our frequency domain signal. It is done mathematically via the equation above, like was shown in the example.&lt;/p&gt;
&lt;h2&gt;
  
  
  Ok ... so I don't see how I can make a program that does this
&lt;/h2&gt;

&lt;p&gt;As of now, our equation acts on a continuous time (CT) signal via an infinite integral. That is not conducive to digital processing and programming. Before we can try to write a program to get the information we need, you have to do a few things to get a signal we can manipulate.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Turn the infinite CT signal into a discrete time, limited size signal. This can be done by sampling and quantization for a limited number of samples. If you sample at a rate &amp;gt;= twice the highest frequency component of the signal (ie the Nyquist frequency), you can avoid aliasing. This is usually done by dedicated hardware. However, we care now about how we use these samples, not how we get them.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Change the equation for getting the frequency domain of our signal so it can work with a size-limited array of sampled data points instead of an infinite continuous time signal. So, instead of an integral we need a summation, and instead of an infinite size we use the size of our sampled data array:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;One more problem though - the frequency domain of an aperiodic signal, discrete or not, is still continuous - so we can't manipulate it on a computer. The answer to this is the Discrete Fourier Transform, a periodically sampled version of the Fourier Transform for a discrete time signal. To get this, we can replace the frequency term with a term that divides it into equal parts over the N samples: &lt;a href="http://www.codecogs.com/eqnedit.php?latex=2%5Cpi&amp;amp;space;f&amp;amp;space;%5CRightarrow&amp;amp;space;%5Cfrac%7B2%5Cpi&amp;amp;space;k%7D%7BN%7D"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0s_fIqTr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://latex.codecogs.com/gif.latex%3F2%255Cpi%26space%3Bf%26space%3B%255CRightarrow%26space%3B%255Cfrac%257B2%255Cpi%26space%3Bk%257D%257BN%257D" title="2\pi f \Rightarrow \frac{2\pi k}{N}"&gt;&lt;/a&gt; where we are evaluating for the k^th sample and there are N total samples.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you are curious if we can recreate the time domain samples accurately from this sampled version of the frequency domain, the short answer is yes, as long as we avoid time-domain aliasing by ensuring the total samples of our frequency domain are greater than or equal to the length of our time domain sample. We can increase the sample rate of our frequency domain without increasing the length of our sampled data by adding zeros to the end of the time domain signal. This will make the samples of our frequency domain be closer together.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Anyway, the end story is that we get this equation to get a frequency domain transform function from an array of sampled data: &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://www.codecogs.com/eqnedit.php?latex=X(k)&amp;amp;space;=&amp;amp;space;%5Csum_%7Bn&amp;amp;space;=&amp;amp;space;0%7D%5E%7BN-1%7D%7Bx(n)e%5E%7B-j%5Cfrac%7B2%5Cpi&amp;amp;space;kn%7D%7BN%7D%7D%7D"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k7ga3R2P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://latex.codecogs.com/gif.latex%3FX%28k%29%26space%3B%3D%26space%3B%255Csum_%257Bn%26space%3B%3D%26space%3B0%257D%255E%257BN-1%257D%257Bx%28n%29e%255E%257B-j%255Cfrac%257B2%255Cpi%26space%3Bkn%257D%257BN%257D%257D%257D" title="X(k) = \sum_{n = 0}^{N-1}{x(n)e^{-j\frac{2\pi kn}{N}}}"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  How do you compute it
&lt;/h2&gt;

&lt;p&gt;Now that we have the equation, this part is easy!&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;signal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="no"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="no"&gt;Math&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;PI&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="c1"&gt;# 1 Hz cosine signal&lt;/span&gt;
&lt;span class="n"&gt;sample_times&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;int&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;int&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;100.0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# Sample for 10 seconds every 0.01 seconds (100 times per period over 10 periods)&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sample_times&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# turn time into sample values&lt;/span&gt;

&lt;span class="c1"&gt;#Discrete Fourier Transform&lt;/span&gt;
&lt;span class="n"&gt;ft&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;tot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_with_index&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;x_n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
        &lt;span class="n"&gt;tot&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;x_n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="no"&gt;Math&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;E&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Complex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="no"&gt;Math&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;PI&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="n"&gt;ft&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;tot&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Too easy! Done, right?&lt;/p&gt;

&lt;p&gt;Not quite. You get the right answer, but that looks like a nested loop to me. ϴ(n^2) is rearing its ugly head to let us know we can't do any real-time processing with this algorithm.&lt;/p&gt;

&lt;p&gt;Since the FFT is needed in so many real-time applications, and sampled signals are usually very long, we need to find a way to severely cut down on processing time.  &lt;/p&gt;

&lt;h2&gt;
  
  
  How to compute it well: Divide and Conquer
&lt;/h2&gt;

&lt;p&gt;So here's where the Fast Fourier Transform (FFT) comes in, which allows us to use this signal in real time. &lt;/p&gt;

&lt;p&gt;First, let's get intuition to what the shortcuts are that we can take advantage of, which makes it advantageous and possible to cut this problem down into smaller sub-problems. The characteristics we want to use are twofold, and come from the fact that we are manipulating &lt;a href="https://en.wikipedia.org/wiki/Root_of_unity"&gt;complex roots of unity&lt;/a&gt; by multiplying by &lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.codecogs.com/eqnedit.php?latex=e%5E%7B-j%5Cfrac%7B2%5Cpi&amp;amp;space;kn%7D%7BN%7D%7D"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NgoHzfWp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://latex.codecogs.com/gif.latex%3Fe%255E%257B-j%255Cfrac%257B2%255Cpi%26space%3Bkn%257D%257BN%257D%257D" title="e^{-j\frac{2\pi kn}{N}}"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;on each iteration. What does that mean? Well, remember from above that &lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.codecogs.com/eqnedit.php?latex=e%5E%7Bj2%5Cpi&amp;amp;space;ft%7D&amp;amp;space;=&amp;amp;space;%5Ccos(2%5Cpi&amp;amp;space;ft)&amp;amp;space;&amp;amp;plus;&amp;amp;space;j%5Csin(2%5Cpi&amp;amp;space;ft)"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8FiTSbGE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://latex.codecogs.com/gif.latex%3Fe%255E%257Bj2%255Cpi%26space%3Bft%257D%26space%3B%3D%26space%3B%255Ccos%282%255Cpi%26space%3Bft%29%26space%3B%26plus%3B%26space%3Bj%255Csin%282%255Cpi%26space%3Bft%29" title="e^{j2\pi ft} = \cos(2\pi ft) + j\sin(2\pi ft)"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Let's first see what an example of that looks like; I did a little back-of-a-napkin demonstration:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JAx1aDBE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/dbgcpuajxw7mjio1p867.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JAx1aDBE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/dbgcpuajxw7mjio1p867.jpg" alt="Real Imaginary"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;So you can think of the Real and Imaginary axis like East/West and North/South lines, and &lt;a href="http://www.codecogs.com/eqnedit.php?latex=e%5E%7Bj2%5Cpi&amp;amp;space;ft%7D"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FimMnseG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://latex.codecogs.com/gif.latex%3Fe%255E%257Bj2%255Cpi%26space%3Bft%257D" title="e^{j2\pi ft}"&gt;&lt;/a&gt; as a compass needle that points to the angle &lt;a href="http://www.codecogs.com/eqnedit.php?latex=2%5Cpi&amp;amp;space;f"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EKtz6Evo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://latex.codecogs.com/gif.latex%3F2%255Cpi%26space%3Bf" title="2\pi f"&gt;&lt;/a&gt; and changes with time t. The properties we want to take advantage of are based off of the situation where we divide the 2π radians into N even segments, as we are doing to calculate the Discrete Fourier Transform. That can be visualized:  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WxxtSmLe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/mpxvxaiqzda8evcw51kc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WxxtSmLe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/mpxvxaiqzda8evcw51kc.jpg" alt="Complex Roots of Unity"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Can you see the properties we want to exploit? They are:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The i^th partition is the complex conjugate of the N-i^th  partition. This means that if we have 8 partitions (and k = 1), the 1^st partition is &lt;a href="http://www.codecogs.com/eqnedit.php?latex=e%5E%7Bj2%5Cpi&amp;amp;space;/&amp;amp;space;8%7D"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VU7RKysp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://latex.codecogs.com/gif.latex%3Fe%255E%257Bj2%255Cpi%26space%3B/%26space%3B8%257D" title="e^{j2\pi / 8}"&gt;&lt;/a&gt; and the -1^st partition (ie the 7th partition) is &lt;a href="http://www.codecogs.com/eqnedit.php?latex=e%5E%7Bj14%5Cpi&amp;amp;space;/&amp;amp;space;8%7D"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dMjI9i1R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://latex.codecogs.com/gif.latex%3Fe%255E%257Bj14%255Cpi%26space%3B/%26space%3B8%257D" title="e^{j14\pi / 8}"&gt;&lt;/a&gt;. 

&lt;ul&gt;
&lt;li&gt;n = 1:  &lt;a href="http://www.codecogs.com/eqnedit.php?latex=%5C,%5C,e%5E%7Bj2%5Cpi&amp;amp;space;/8%7D&amp;amp;space;=&amp;amp;space;%5Ccos(2%5Cpi/8)&amp;amp;space;&amp;amp;plus;j%5Csin(2%5Cpi/8)&amp;amp;space;=&amp;amp;space;0.707&amp;amp;space;&amp;amp;plus;j0.707"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iL5hfMrf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://latex.codecogs.com/gif.latex%3F%255C%2C%255C%2Ce%255E%257Bj2%255Cpi%26space%3B/8%257D%26space%3B%3D%26space%3B%255Ccos%282%255Cpi/8%29%26space%3B%26plus%3Bj%255Csin%282%255Cpi/8%29%26space%3B%3D%26space%3B0.707%26space%3B%26plus%3Bj0.707" title="\,\,e^{j2\pi /8} = \cos(2\pi/8) +j\sin(2\pi/8) = 0.707 +j0.707"&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;n = 7:  &lt;a href="http://www.codecogs.com/eqnedit.php?latex=%5C,%5C,e%5E%7Bj14%5Cpi/8%7D&amp;amp;space;=&amp;amp;space;cos(14%5Cpi/8)&amp;amp;space;&amp;amp;plus;&amp;amp;space;j%5Csin(14%5Cpi&amp;amp;space;/8)&amp;amp;space;=&amp;amp;space;0.707&amp;amp;space;-&amp;amp;space;j0.707"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--prv3otFZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://latex.codecogs.com/gif.latex%3F%255C%2C%255C%2Ce%255E%257Bj14%255Cpi/8%257D%26space%3B%3D%26space%3Bcos%2814%255Cpi/8%29%26space%3B%26plus%3B%26space%3Bj%255Csin%2814%255Cpi%26space%3B/8%29%26space%3B%3D%26space%3B0.707%26space%3B-%26space%3Bj0.707" title="\,\,e^{j14\pi/8} = cos(14\pi/8) + j\sin(14\pi /8) = 0.707 - j0.707"&gt;&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;As you can see, the 1 and N-1 signals are related because their real components are the same, and their imaginary components are negatives of each other. You can see that visually above.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;2_ This circle is periodic, so when the variable k begins to increase, we just loop around the circle as n increments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now let's finally see how to exploit these characteristics using the Radix 2 FFT algorithm.&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We know that in order to divide and conquer, we want to break down a problem in halves (or some radix). We notice from our drawing that if we take the even partitions in the case of 8 partitions, we will be left with the partitions as if we had 4 complex roots of unity instead of 8 (ie 4 even divisions of 2π), thus giving us a smaller problem to solve, which is what we want. Mathematically, let's see what it looks like if we broke the signal up into even and odd samples: 

&lt;ul&gt;
&lt;li&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9ZHaiXJX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/sgd2cw831uf0xa4pjrld.gif" alt="Summation"&gt;&lt;/li&gt;
&lt;li&gt;This reduces to an equation of 2 sub-arrays of data which are half the size of the original dataset, and will be multiplied by the roots of unity of N/2 instead of N, essentially creating 2 identical sub-problems:

&lt;ul&gt;
&lt;li&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2lnZ5e3H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/jbww0povagr8qtvp1nov.gif" alt="Subproblems"&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;We can now just recurse with our even and odd subarrays until you hit the base case of N = 1 (here n and k will be zero so you are just multiplying this one value by e^0 = 1), and return that value as the DFT of itself. Then combine per the equation above.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Awesome, but there is still one more thing we can do. Remember how we said that the i^th and N-i^th roots are complex conjugates of each other (ie, the roots of unity drawing is a mirror image across the x axis)? Well, that means that once we solve the two sub-problems for size of N/2, we can combine them to get the N DFT values by creating their corresponding "mirror image" values at the same time. This will stop us from having to loop through the N/2 sub-problems' data twice to create the N data values required to make X(k) one level up. We want to take the k^th result of the DFT of the even array and we add it to  &lt;a href="http://www.codecogs.com/eqnedit.php?latex=e%5E%7B-j%5Cfrac%7B2%5Cpi&amp;amp;space;k%7D%7BN%7D%7D"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HIVVKjDl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://latex.codecogs.com/gif.latex%3Fe%255E%257B-j%255Cfrac%257B2%255Cpi%26space%3Bk%257D%257BN%257D%257D" title="e^{-j\frac{2\pi k}{N}}"&gt;&lt;/a&gt; times the k^th result of the DFT of the odd array, and put it into an array that will be for the 0...N/2 values of X(k). We again take the k^th result of the DFT of the even array but now we subtract from it &lt;a href="http://www.codecogs.com/eqnedit.php?latex=e%5E%7B-j%5Cfrac%7B2%5Cpi&amp;amp;space;k%7D%7BN%7D%7D"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HIVVKjDl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://latex.codecogs.com/gif.latex%3Fe%255E%257B-j%255Cfrac%257B2%255Cpi%26space%3Bk%257D%257BN%257D%257D" title="e^{-j\frac{2\pi k}{N}}"&gt;&lt;/a&gt; times the k^th result of the DFT of the odd array, and put it into an array that will be for the N/2...N values of X(k). We do this N/2 times. Lastly, we append the N/2...N array to the end of the 0...N/2 array to get the full answer for the next level up, X(k). In an equation, each level's combine step looks like this: &lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://www.codecogs.com/eqnedit.php?latex=X(k)&amp;amp;space;=&amp;amp;space;FFT(even%5C,&amp;amp;space;subarray)%5Bk%5D&amp;amp;space;&amp;amp;plus;&amp;amp;space;e%5E%7B-j%5Cfrac%7B2%5Cpi&amp;amp;space;k%7D%7BN%7D%7DFFT(odd%5C,subarray)%5Bk%5D"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R9nLl7YJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://latex.codecogs.com/gif.latex%3FX%28k%29%26space%3B%3D%26space%3BFFT%28even%255C%2C%26space%3Bsubarray%29%255Bk%255D%26space%3B%26plus%3B%26space%3Be%255E%257B-j%255Cfrac%257B2%255Cpi%26space%3Bk%257D%257BN%257D%257DFFT%28odd%255C%2Csubarray%29%255Bk%255D" title="X(k) = FFT(even\, subarray)[k] + e^{-j\frac{2\pi k}{N}}FFT(odd\,subarray)[k]"&gt;&lt;/a&gt; for &lt;a href="http://www.codecogs.com/eqnedit.php?latex=0%5Cleqslant&amp;amp;space;k&amp;amp;space;&amp;lt;&amp;amp;space;N/2"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0K1lYXxb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://latex.codecogs.com/gif.latex%3F0%255Cleqslant%26space%3Bk%26space%3B%3C%26space%3BN/2" title="0\leqslant k &amp;lt; N/2"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://www.codecogs.com/eqnedit.php?latex=X(k)&amp;amp;space;=&amp;amp;space;FFT(even%5C,&amp;amp;space;subarray)%5Bk%5D&amp;amp;space;-&amp;amp;space;e%5E%7B-j%5Cfrac%7B2%5Cpi&amp;amp;space;k%7D%7BN%7D%7DFFT(odd%5C,subarray)%5Bk%5D"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AmVEK3nr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://latex.codecogs.com/gif.latex%3FX%28k%29%26space%3B%3D%26space%3BFFT%28even%255C%2C%26space%3Bsubarray%29%255Bk%255D%26space%3B-%26space%3Be%255E%257B-j%255Cfrac%257B2%255Cpi%26space%3Bk%257D%257BN%257D%257DFFT%28odd%255C%2Csubarray%29%255Bk%255D" title="X(k) = FFT(even\, subarray)[k] - e^{-j\frac{2\pi k}{N}}FFT(odd\,subarray)[k]"&gt;&lt;/a&gt; for &lt;a href="http://www.codecogs.com/eqnedit.php?latex=N/2%5Cleqslant&amp;amp;space;k&amp;amp;space;&amp;lt;&amp;amp;space;N"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i0cK4nv9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://latex.codecogs.com/gif.latex%3FN/2%255Cleqslant%26space%3Bk%26space%3B%3C%26space%3BN" title="N/2\leqslant k &amp;lt; N"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;3_ A necessary detail:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This premise of being able to divide the problem by 2 and make even partitions of the unit circle requires that the sample data array be a power of 2. This is a simple metric to meet. All you have to do is add 0s to the end of your data until your data array's length is a power of 2. This ensures the algorithm works, and it creates closer "sample points" in your Discrete Fourier Transform, making the visualization better.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Show me how you implemented it
&lt;/h2&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;Radix2Strategy&lt;/span&gt; 

    &lt;span class="no"&gt;E&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Math&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;E&lt;/span&gt;
    &lt;span class="no"&gt;PI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Math&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;PI&lt;/span&gt;

    &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:data&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;data: &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="vi"&gt;@data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;
        &lt;span class="n"&gt;zero_fill&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;calculate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;recursive_fft&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&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;recursive_fft&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="n"&gt;w_n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;E&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="no"&gt;PI&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="no"&gt;Complex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="n"&gt;a0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_even&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;a1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_odd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;y0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;recursive_fft&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;y1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;recursive_fft&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Array&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="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
            &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y0&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;y1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y0&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;y1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;w_n&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;y&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;get_even&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;even&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_with_index&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;even&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dup&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;even?&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;even&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;get_odd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;odd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_with_index&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;odd&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dup&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;odd?&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;odd&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;zero_fill&lt;/span&gt;
        &lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;
        &lt;span class="vi"&gt;@data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt; &lt;span class="no"&gt;Array&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="n"&gt;closest_pow_of_2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&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;def&lt;/span&gt; &lt;span class="nf"&gt;closest_pow_of_2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="no"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ceil&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;



</description>
      <category>computerscience</category>
      <category>math</category>
      <category>algorithms</category>
      <category>programming</category>
    </item>
    <item>
      <title>Developing Style: Big O, Sorting</title>
      <dc:creator>Micah Shute</dc:creator>
      <pubDate>Wed, 17 Oct 2018 15:49:33 +0000</pubDate>
      <link>https://forem.com/micahshute/developing-style-big-o-sorting-13pj</link>
      <guid>https://forem.com/micahshute/developing-style-big-o-sorting-13pj</guid>
      <description>&lt;p&gt;A continuation of the documentation of my studies as I learn the foundations of programming. Feedback is welcomed. &lt;/p&gt;

&lt;h1&gt;
  
  
  Big O
&lt;/h1&gt;

&lt;h2&gt;
  
  
  What is it
&lt;/h2&gt;

&lt;p&gt;It describes the asymptotic nature of a system as the input grows. Usually, we are describing runtime of an algorithm, but it can also be used to describe space complexity or even systems outside the realm of computer science. Here I will assume it describes runtime of an algorithm unless stated otherwise. Asymptotic analysis means that you focus on how the runtime of the algorithm grows as the input grows and approaches infinity. The input is usually denoted as &lt;code&gt;n&lt;/code&gt;. As our datasets get larger, it is the growth function which will be the dominating factor of runtime. For example, O(n) suggests that the runtime changes linearly with the input &lt;code&gt;n&lt;/code&gt;. O(n^2 ) suggests that the runtime changes proportionally to the size of the input squared. With large datasets, this is usually enough information to tell you which one will be faster.&lt;/p&gt;

&lt;p&gt;When you analyze asymptotic characteristics of a function, you want to discount added constants, as well as drop coefficients and lower-order terms. For example, f(n) = 100 * n * lg(n) + n + 10000 is described as O( n * lg(n) ), because as n goes to infinity, the constant and the coefficient become insignificant. Check these graphs out:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Xy-cnaq4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/JTjq1EC.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xy-cnaq4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/JTjq1EC.png" alt="Runtime small"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---4PCocuC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/ygPiblV.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---4PCocuC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/ygPiblV.png" alt="Runtime large"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, in small datasets, big O notation may not be telling the whole story, but even going from 50 to 500 data points in the above graph made the asymptotic nature of the functions take over.&lt;/p&gt;

&lt;p&gt;Certainly, there are merits to optimizing code within a certain asymptotic runtime to maximize performance, but that should be done only after the proper asymptotic algorithm is being used.&lt;/p&gt;

&lt;p&gt;Although it seems that colloquially "big-O" is used to mean the asymptotic runtime which describes a function's 'tight asymptotic' nature, (ie describes both upper and lower bound), this isn't actually accurate. The formal definitions of asymptotic runtime are briefly described below [1]:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Big - ϴ (theta) :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Formally, for ϴ( g(n) ) to describe a function f(n), there exist positive constants c1, c2, and n_o such that

&lt;code&gt;0 &amp;lt;= c1 * g(n) &amp;lt;= f(n) &amp;lt;= c2 * g(n) for all n &amp;gt;= n_o&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;To clarify:&lt;/strong&gt; imagine you have an algorithm that is defined by a complex equation f(n). You can characterize f(n) in big-theta notation by a very simple equation g(n) which has all constants, coefficients, and lower-order terms dropped IF you can re-add 2 arbitrary constants to g(n) which can "sandwich" your original equation f(n) past a certain input data size n_o.&lt;/li&gt;
&lt;li&gt;Example: let's say your f(n) =

&lt;code&gt;100*n^2  + 4*n*lg(n)&lt;/code&gt;

. We can show that n^2 can meet this definition with the following equations and graph&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V9sY4Dcu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/0NIB2lH.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V9sY4Dcu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/0NIB2lH.png" alt="Bounded"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now, if we tried to sandwich our f(n) with nlgn, we see that the upper bound is inevitably passed by f(n) as n grows, regardless of the constant that we set:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--axPUlXgp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/4wEwjhM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--axPUlXgp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/4wEwjhM.png" alt="Not bounded"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;So, technically every time I called a function big-O above, what I should have said is big-theta, ie ϴ(n) instead of O(n).
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Big-O:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only provides an asymptotic upper bound as opposed to an upper and lower bound provided by ϴ notation. &lt;/li&gt;
&lt;li&gt;Formally, for O( g(n) ) to describe a function f(n), there exist positive constants c and n_o such that

&lt;code&gt;0 &amp;lt;= f(n) &amp;lt;= c*g(n) for all n &amp;gt;= n_0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;So it is actually correct to say an algorithm defined by

&lt;code&gt;f(n) = 3*n + 100&lt;/code&gt;

is O(n^3 ), even though it is ϴ(n). &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;There also exist other less-used notations defined similarly as the above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; Ω (big-omega) notation defines an asymptotic lower bound only&lt;/li&gt;
&lt;li&gt; o (little-o) notation defines an upper bound which is NOT asymptotically tight (such as the example above where we describe a ϴ(n) function as O(n^3 ) - that is an asymptotically not-tight definition and you could therefore say it is also o(n^3 ). o(n) would be incorrect)&lt;/li&gt;
&lt;li&gt; ω (little-omega) notation defines a lower bound which must NOT be asymptotically tight.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When describing algorithms, the most used concept is ϴ notation, and it is usually communicated as O notation. &lt;/p&gt;

&lt;p&gt;Although algorithms can be analyzed by their best-case, average-case, and worst-case runtimes, we usually (with a few exceptions below) focus on worst-case for 3 main reasons:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It is easier to calculate the worst-case runtime than the average runtime (fewer factors to account for)&lt;/li&gt;
&lt;li&gt;A worst-case analysis is a guarantee that we will never take any longer&lt;/li&gt;
&lt;li&gt;It is not uncommon that the worst-case scenario happens frequently when implemented&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It turns out that lgn (shorthand for log base 2 of n) is important to a lot of runtime discussions. A quick review of logarithms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A logarithm describes what power the base must be brought to in order to create a certain number. For example, since our base is 2, if we want to find lg(8), we ask ourselves: "To what power can I take 2 to in order to obtain the answer 8?". In this case, since we know 2^3 is 8, we know that lg(8) = 3. You are kind of "deconstructing" an exponential. This is an important concept because if we can make an algorithm that is defined by a log, it grows super slowly! It actually grows as slowly as exponentials grow quickly, which is a lot. 

&lt;ul&gt;
&lt;li&gt;Imagine you have a dataset of size 262144, and you are performing an algorithm with runtime f(n) = n on it. If it grows to 524288, you are doing 262144 more operations! If your f(n) = n^2, you are doing 68719476736 MORE operations! If your f(n) = lgn, you are doing 1 more operation. If your f(n) = lgn, every time your dataset doubles, you do 1 extra operation. &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Why is it important?
&lt;/h2&gt;

&lt;p&gt;When you work with a large dataset or a dataset which may become large as you gain users or gather more information, your runtime will be determined by its asymptotic growth. As described above, constants, coefficients, and lower-order terms have relatively minor significance compared to the highest-order component. The difference between an O(n*lg(n)) algorithm and an O(n^2 ) algorithm can easily be the difference between a well-performing app and an absolutely unusable app. &lt;/p&gt;
&lt;h2&gt;
  
  
  How do you use O-notation practically?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Understand when it is important

&lt;ul&gt;
&lt;li&gt;If you are working on a small dataset and it has absolutely no way of getting big, it may not be worth your time developing super-optimized code or trying to get a better runtime for your algorithm.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;If your dataset is or may get very large, it is important to understand how your algorithms are affecting your runtime (and your memory!). Thus, you have to be able to tell what the asymptotic runtime is of your code. Some ways to do this:

&lt;ul&gt;
&lt;li&gt;Look through your loops. If you are iterating through a collection once, you most likely have a ϴ(n) algorithm. If your loop has an inner loop which iterates through all of your data (or n-1 each time), you most likely have a ϴ(n^2 ) algorithm, which is very dangerous. &lt;/li&gt;
&lt;li&gt;Understand the "behind-the-scenes" code that occurs when you call a function which you did not write yourself or that is native to the language. There could be a better-suited way to do something, and not understanding the guts of the methods you are calling can make it very hard to optimize.&lt;/li&gt;
&lt;li&gt;Look through your code for functions which are linked to the size of the input data, and disregard constants or repetition of that code which is not dependent on data size. This can help you more easily determine your ϴ( g(n) )&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Adopt a &lt;strong&gt;divide and conquer&lt;/strong&gt; mindset

&lt;ul&gt;
&lt;li&gt;(1) Divide the problem into smaller problems, (2) Conquer the subproblems recursively until they are small enough to have a simple solution. (3) Combine the subproblem solutions to create the overall solution.&lt;/li&gt;
&lt;li&gt;Basically when using divide and conquer, if you can keep dividing your problem into equal halves (which is usually the division point) until it is small enough that it is trivial (easy) to solve. Then you can solve that small, easy problem and combine those easy answers into a full answer. It is very possible you have just changed your algorithm from ϴ(n^2 ) to ϴ(nlgn) runtime. &lt;/li&gt;
&lt;li&gt;The reason this transformation happens is that if you break down your code into equal halves, you can make that division lgn times (ie how many times can I multiply by 2 to get my data size n?). Each time you divide your problem by 2, we iterate through our data to do something to it, hence n * lgn. The sorting algorithms below will show instances of this. &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  Sorting
&lt;/h1&gt;

&lt;p&gt;This is a simple application of big O and is something that every programmer should have a basic understanding of.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why is it important?
&lt;/h2&gt;

&lt;p&gt;Most languages have built-in sorting algorithms, but it is still important to understand how sorting works. Why?&lt;/p&gt;

&lt;p&gt;It has a lot of important use cases:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Arguably the biggest use is increasing the speed of search through an array from O(n) to O(lgn) - a huge improvement. (ie ability to use &lt;a href="https://en.wikipedia.org/wiki/Binary_search_algorithm"&gt;binary search&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Delivering data to a user in a certain format (price from high to low)&lt;/li&gt;
&lt;li&gt;Manipulating data based on its location in a sorted list (ie display the most recent posts)
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, although I have never been in one myself, you can apparently get asked about it in technical interviews.&lt;/p&gt;

&lt;p&gt;Sorting algorithms can have vastly different runtimes based on the data on which they are being run. Although many given sorting algorithms work pretty well on most data, it is important to know what different algorithms may work better for your use case. It might not be the best choice to simply use the language's standard sorting algorithm. &lt;/p&gt;

&lt;p&gt;Lastly, and perhaps most importantly, it helps you get an understanding of why big O matters, and how to go about problem-solving in a way more elegant than a brute-force solution.&lt;/p&gt;
&lt;h2&gt;
  
  
  How can we do it, with what time complexity?
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Disclaimers:
&lt;/h3&gt;

&lt;p&gt;These examples are focused on time complexity and space complexity will not be taken into account.&lt;/p&gt;

&lt;p&gt;Also, better metrics for these algorithms are the number of switches and comparisons they make, not the runtime on a specific machine. For ease, intuition, and clarity I will be providing runtimes. My RAM was never fully used, and IO to disk did not factor into the runtimes.&lt;/p&gt;

&lt;p&gt;Algorithms annotated with a &lt;code&gt;!&lt;/code&gt; in the method name sort in place.&lt;/p&gt;
&lt;h2&gt;
  
  
  Algorithms
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Bubble Sort
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Characteristics

&lt;ul&gt;
&lt;li&gt;ϴ(n^2 ) worst-case and average-case

&lt;ul&gt;
&lt;li&gt;Notice the nested loops giving an indication of ϴ(n^2 ) runtime&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ϴ(n) best-case&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Description

&lt;ul&gt;
&lt;li&gt;Iterate through the list checking each element with its adjacent element. Swap them if they are out of order. Repeat this until all are swapped. As an optimization, you can iterate through &lt;code&gt;n&lt;/code&gt; minus &lt;code&gt;i&lt;/code&gt; elements each time, where &lt;code&gt;i&lt;/code&gt; is the number of iterations you have already done. This is because after the first sweep you guaranteed the smallest number has "bubbled" to the top (or largest number has dropped to the bottom, depending on your iteration direction), so you only need to check the indices below (above) it.&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://en.wikipedia.org/wiki/Bubble_sort"&gt;wikipedia page for bubble sort&lt;/a&gt; shows a simpler implementation of bubble sort at first and works its way to the "optimized" version.&lt;/li&gt;
&lt;li&gt;Even while optimized, bubble sort is extremely slow on large datasets. You can program it to &lt;code&gt;return&lt;/code&gt; if no swaps are made, which means that the data is in order, but this only helps if you have a nearly perfectly sorted array. I did not include this optimization - for clarity, and because this characteristic is better utilized in insertion sort than bubble sort.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Code
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bubble_sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; 
                &lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&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;end&lt;/span&gt;
    &lt;span class="n"&gt;coll&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Insertion Sort
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Characteristics

&lt;ul&gt;
&lt;li&gt; ϴ(n^2 ) worst-case and average-case.&lt;/li&gt;
&lt;li&gt;  ϴ(n) best-case

&lt;ul&gt;
&lt;li&gt;  This best-case scenario happens when the list is already sorted (or very close to being sorted)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Description

&lt;ul&gt;
&lt;li&gt;Imagine your collection is broken up into two parts. The farthest index on the left (ie index 0) is a "sorted array" of one element. The rest of the array is an unsorted mess. We can go one by one in our unsorted righthand side and insert that element correctly in the lefthand side of the array in order to maintain the left side sorted and to make the sorted side grow by one. By the time that we get to the end of the array, the whole lefthand side (ie the entire array) is sorted.&lt;/li&gt;
&lt;li&gt;This is ϴ(n^2 ) because, for each index in our unsorted side, we have to search through the sorted side for its correct location. Not only that, but we have to shift every element over on the way to make room for our insertion, which is also costly. 

&lt;ul&gt;
&lt;li&gt;It is important to note both the number of comparisons and the number of swaps.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;For every index in the righthand side of the array, we are looking through 1 up to &lt;code&gt;n&lt;/code&gt; other elements in the lefthand side for the correct insertion position. The summation of 1 to n is of order ϴ(n^2 ) &lt;/li&gt;
&lt;li&gt;We can evaluate this algorithm via a "loop invariant"

&lt;ul&gt;
&lt;li&gt;A loop invariant is a way to prove the correctness of an algorithm which performs repetitive tasks. To do this correctly, we have to show a &lt;em&gt;loop invariant (LI) statement&lt;/em&gt; &lt;strong&gt;&lt;em&gt;correct&lt;/em&gt;&lt;/strong&gt; for:

&lt;ul&gt;
&lt;li&gt;Initialization - your LI statement is true before the first time you loop&lt;/li&gt;
&lt;li&gt;Maintenance - your LI statement is true throughout the duration of each subsequent loop&lt;/li&gt;
&lt;li&gt;Termination - your LI statement is at the end of the program and gives a way to 'prove' your algorithm is correct.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;In this case, a loop invariant can be stated (paraphrased from [1] ): "At the start of each iteration of our for loop, the subarray from 0 to j-1 (inclusive) consists of the elements originally in that range of indices but now in sorted order"

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Initialization&lt;/strong&gt;: Because the lefthand side is a single element (ie 0 to j=1-1=0 inclusive), it is sorted by definition. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintenance&lt;/strong&gt;: Each time you loop, you insert an item from the unsorted side to the correct position on the sorted side. Then you update your indices so you know where that divide is. Your sorted side is bigger by one and still sorted. Before the loop, and after the loop, the subarray 0 to j-1 is sorted, but at the end of the loop, j is one unit larger than before. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Termination&lt;/strong&gt;: Your loop is over when j is equal to your array length minus 1. So, we know that the array from 0 to (array length - 1) inclusive is sorted. That is every index in our array. Our whole array is sorted.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;As you will see below, although most of the time Insertion Sort is very slow, it is a rockstar at sorting almost-sorted data.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Code
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;insertion_sort!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="c1"&gt;# insert coll[j] into sorted sequence coll[0..j-1]&lt;/span&gt;
        &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;
            &lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="n"&gt;coll&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Merge Sort
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Characteristics

&lt;ul&gt;
&lt;li&gt;ϴ(n*lgn) best case, worst case, and average case&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Description

&lt;ul&gt;
&lt;li&gt;Divide and conquer algorithm:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Divide&lt;/strong&gt; the problem by half until the array size is 1&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conquer&lt;/strong&gt; the sorting problem when the size equals one -- its already done for you because there is only one element. This will give you your first return from the &lt;code&gt;merge_sort&lt;/code&gt; function instead of a recursion. This return will always be a sorted array (either of length 1 or &lt;code&gt;merge&lt;/code&gt;d into a sorted array) and allows you to proceed with the algorithm by now just preserving the 'sorted' status of these arrays as you &lt;code&gt;combine&lt;/code&gt; them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Combine&lt;/strong&gt; your two smaller halves which are both of size 1 (and sorted)together by comparison to make a sorted array of length 2.&lt;/li&gt;
&lt;li&gt;One level up the recursion will now have 2 arrays of size 2 which &lt;strong&gt;are sorted&lt;/strong&gt;. &lt;strong&gt;&lt;em&gt;Combine&lt;/em&gt;&lt;/strong&gt; them together to create a new sorted array of length 4, and so on until your entire array is sorted. &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Merge Loop Invariant&lt;/strong&gt; [1], (references the code below):

&lt;ul&gt;
&lt;li&gt;Statement: At the start of the while loop, &lt;code&gt;merged_arr&lt;/code&gt; will contain the smallest (i + j) elements from the arrays &lt;code&gt;left&lt;/code&gt; and &lt;code&gt;right&lt;/code&gt;, in sorted order. &lt;code&gt;left[i]&lt;/code&gt; and &lt;code&gt;right[j]&lt;/code&gt; will contain the smallest numbers in their respective arrays for indices greater than i and j respectively.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Initialization&lt;/strong&gt;: &lt;code&gt;merged_arr&lt;/code&gt; is empty, and i + j = 0. &lt;code&gt;left&lt;/code&gt; and &lt;code&gt;right&lt;/code&gt; are sorted arrays, so both of their 0th elements will be the smallest in their entire arrays.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintenanance&lt;/strong&gt;: The smaller of the two numbers from &lt;code&gt;left[i]&lt;/code&gt; and &lt;code&gt;right[j]&lt;/code&gt; is appended to the end of merged_arr. Since both arrays are in sorted order and i and j are both incremented from 0, we are guaranteed that each iteration of the while loop only considers numbers to append to &lt;code&gt;merged_arr&lt;/code&gt; which are larger or equal to the numbers already appended to &lt;code&gt;merged_arr&lt;/code&gt;, and smaller than or equal to the numbers of higher index remaining in &lt;code&gt;left&lt;/code&gt; and &lt;code&gt;right&lt;/code&gt;. This ensures the sorted condition of &lt;code&gt;merged_arr&lt;/code&gt;. When an element is appended to &lt;code&gt;merged_arr&lt;/code&gt; from &lt;code&gt;left&lt;/code&gt;, only &lt;code&gt;i&lt;/code&gt; is incremented by 1, and when an element is appended to &lt;code&gt;merged_arr&lt;/code&gt; from &lt;code&gt;right&lt;/code&gt; only &lt;code&gt;j&lt;/code&gt; is incremented by 1. This ensures that &lt;code&gt;merged_arr.length&lt;/code&gt; is equal to i + j, that &lt;code&gt;merged_arr&lt;/code&gt;'s values are in sorted order, and the next two numbers &lt;code&gt;left[i]&lt;/code&gt; and &lt;code&gt;right[j]&lt;/code&gt; are greater than or equal to all of the numbers in &lt;code&gt;merged_arr&lt;/code&gt;, and less than or equal to all other values left in their respective arrays. IE, they are the two smallest values their arrays have to offer which have not already been put in &lt;code&gt;merge_arr&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Termination&lt;/strong&gt;: The loop breaks when one of the arrays is 'empty'. We know that at this point &lt;code&gt;merged_arr&lt;/code&gt; is in sorted order, and has all the values of the expended array and all the values of the other array up to the index of &lt;code&gt;i&lt;/code&gt; or &lt;code&gt;j&lt;/code&gt;. This termination is great but requires just a little cleanup. You have to now push the remainder of the array with values left over onto the end of &lt;code&gt;merge_arr&lt;/code&gt;. You know you can just push them at the end, because the array with leftover values is already sorted, and its lowest valued number was determined greater than or equal to the largest value in the other array.

&lt;ul&gt;
&lt;li&gt;Note that sometimes two "sentinels" are placed at the end of &lt;code&gt;left&lt;/code&gt; and &lt;code&gt;right&lt;/code&gt; and given the value of infinity. Then, the while loop is replaced by a for loop which runs &lt;code&gt;left.length + right.length - 2&lt;/code&gt; times, so that only the two infinity sentinel values are left. In Ruby, you can represent infinity with &lt;code&gt;Float::INFINITY&lt;/code&gt;, in Python &lt;code&gt;float("inf")&lt;/code&gt;, in Javascript &lt;code&gt;Infinity&lt;/code&gt;, and in Java &lt;code&gt;Double.POSITIVE_INFINITY&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Code (uncomment to see it in action - this is helpful to see how the sorting works)
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;merge_sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;coll&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;left_sorted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;merge_sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;right_sorted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;merge_sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left_sorted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right_sorted&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;def&lt;/span&gt; &lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;merged_arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;
        &lt;span class="c1"&gt;#puts "Comparing lhs #{left[i]} to rhs #{right[j]}"&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="c1"&gt;#puts "Adding lhs #{left[i]}"&lt;/span&gt;
            &lt;span class="n"&gt;merged_arr&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="c1"&gt;#puts "Adding rhs #{right[j]}"&lt;/span&gt;
            &lt;span class="n"&gt;merged_arr&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="n"&gt;merged_arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;
    &lt;span class="n"&gt;merged_arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;
    &lt;span class="c1"&gt;#puts merged_arr.to_s&lt;/span&gt;
    &lt;span class="n"&gt;merged_arr&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Quick Sort
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Characteristics

&lt;ul&gt;
&lt;li&gt; ϴ(n*lgn) best case, average case&lt;/li&gt;
&lt;li&gt;  ϴ(n^2 ) worst case (when nearly sorted)

&lt;ul&gt;
&lt;li&gt;  If you look at the code below, you can see that this is because the pivot, in the sorted case, splits the problem into two sizes n - 1 and 1, instead of n/2 and n/2. For a randomized array, it is more likely that the pivot will be a value closer to the median value. This will be described more below.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Description&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Divide and Conquer&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Divide&lt;/strong&gt; Choose a 'pivot point' as the last index in the array. Iterate through the array and switch values which are on the 'wrong side' of the pivot value until all values larger or equal than the pivot are on the right side of some index, and all the smaller values are on the left side of that same index. Divide the array by that index to create two smaller subproblems. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conquer&lt;/strong&gt; When the sizes are small enough (ie 1 or 2), this &lt;strong&gt;divide&lt;/strong&gt; procedure will cuase the subsets to be sorted. Grouping the numbers by greater than or less than a pivot on a large scale ensures that the algorithm done on a smaller scale array of 2 (which actually causes sorting of the array) is done at a location in the array that will cause the overall array to be sorted, and not just have clumps of localized sorted data. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Combine&lt;/strong&gt; Just like the &lt;strong&gt;Conquer&lt;/strong&gt; of the Mergesort algorithm was trivial because all of the work was done in the Mergesort &lt;strong&gt;Combine&lt;/strong&gt;, the &lt;strong&gt;Combine&lt;/strong&gt; of quicksort is trivial because all of the work is done in the &lt;strong&gt;Divide&lt;/strong&gt; step. After the array is divided down to sets of 1 and 2, it is sorted in place. And the algorithm will stop recursing when the size of the subarray become equal to or less than zero.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Partition Loop Invariant&lt;/strong&gt; (see code below)

&lt;ul&gt;
&lt;li&gt;Statement: Values of &lt;code&gt;arr&lt;/code&gt; from the original argument value &lt;code&gt;lo&lt;/code&gt; to the current value of &lt;code&gt;lo&lt;/code&gt; are all less than or equal to the pivot value. Values of &lt;code&gt;arr&lt;/code&gt; from the original argument value &lt;code&gt;hi&lt;/code&gt; to the current value of &lt;code&gt;hi&lt;/code&gt; are greater than or equal to the pivot value. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Initialization&lt;/strong&gt; &lt;code&gt;lo&lt;/code&gt; and &lt;code&gt;hi&lt;/code&gt; are initialized to be one lower and greater than their initial values, respectively. Being outside of the array and not associated with values, you trivially meet the requirement that the related values of &lt;code&gt;arr&lt;/code&gt; are as stated in the LI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintenance&lt;/strong&gt; After a single loop, the&lt;code&gt;lo&lt;/code&gt; index value is incremented up past any indices whose value are smaller than the pivot. When the loop finally breaks,&lt;code&gt;lo&lt;/code&gt; is therefore guaranteed to be fixed at an index whose value is greater than or equal to the pivot value, with all values to the left of it guaranteed to be less than the pivot value (or equal to the pivot value if it was swapped to the left of &lt;code&gt;lo&lt;/code&gt;). 'hi' is decremented in the same manner, stopping on an index whose value is less than or equal to the pivot value, guaranteeing that all values to the right of 'hi' are greater than the pivot value (or equal to the pivot value if it was swapped to the right of &lt;code&gt;hi&lt;/code&gt;). If &lt;code&gt;hi&lt;/code&gt; &amp;gt; &lt;code&gt;lo&lt;/code&gt;, we swap them because we know that the inner loops stopped on values which should be associated with 'the other side' or the 'middle' of an array divided by the pivot value, and we have not yet reached the 'middle'. This means that the new value for &lt;code&gt;arr[lo]&lt;/code&gt; must meet the requirement for the &lt;code&gt;arr[hi]&lt;/code&gt; loop to break (ie &lt;code&gt;&amp;lt;= pivot&lt;/code&gt;), and the new value for &lt;code&gt;arr[hi]&lt;/code&gt; must meet the requirement for the &lt;code&gt;arr[lo]&lt;/code&gt; loop to break (ie &lt;code&gt;&amp;gt;= pivot&lt;/code&gt;). So, it is maintained that all values at index &lt;code&gt;lo&lt;/code&gt; and below are either less than the pivot (if they passed over by the loop) or less than or equal to the pivot value (if they were swapped from a point previously at an index &lt;code&gt;hi&lt;/code&gt;). In other words, they are all less than or equal to the pivot value. Conversely, it is maintained that all values at index 'hi' and greater are either greater than the pivot value or equal to the pivot value. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Termination&lt;/strong&gt; If &lt;code&gt;lo&lt;/code&gt; &amp;gt;= &lt;code&gt;hi&lt;/code&gt;, we know we have hit the place in the array which is divided numerically by the pivot value. We return the higher of the two indices, allowing us to create a subdivision of the array in which all values below the &lt;code&gt;partition_index - 1&lt;/code&gt; are less than or equal to the pivot and all values above the &lt;code&gt;partition&lt;/code&gt; are greater than or equal to the pivot. Also, by subdividing the array the way that we do in &lt;code&gt;quicksort!&lt;/code&gt; we prevent an infinite loop by preventing a partition index to subdivide into an empty array and the original array. When the subarray is of size 1 or 2, &lt;code&gt;partition&lt;/code&gt; results in a sorted subarray section, which is also in its correct position relative to the entire array. &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Code&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;quicksort!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;hi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;hi&lt;/span&gt;
        &lt;span class="n"&gt;partition_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;partition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;quicksort!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;partition_index&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;quicksort!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;partition_index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hi&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="c1"&gt;#Hoar Partition&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;partition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;pivot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;hi&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="kp"&gt;loop&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="kp"&gt;loop&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
            &lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;pivot&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;

        &lt;span class="kp"&gt;loop&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
            &lt;span class="n"&gt;hi&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;pivot&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;hi&lt;/span&gt;
        &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lo&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;Algorithm runtime on randomized and nearly-sorted data&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;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="mi"&gt;1000000&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="n"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500000&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;Random Numbers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Bubble sort (1 million numbers): 33323.8596392 s, (555.4 mins)

Insertion sort (1 million numbers): 13213.5302226 s, (220.2 mins)

Merge sort (1 million numbers): 2.0483875 s

Quick sort (1 million numbers): 3.6877069 s

Ruby's native #sort (1 million numbers): 1.0330547 s, (a very optimized Quicksort algorithm)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It is a very common use case to have to sort a collection which is already mostly sorted. Let's see how the algorithms do with that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ruby's native #sort (mostly sorted 1 million nums): 0.6229407 s (a very optimized Quicksort algorithm)

Merge sort (mostly sorted 1 million nums): 1.5681328 s 

Insertion sort (mostly sorted 1 million nums): 0.1712918 s
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;If you know you need to frequently sort a collection which is very nearly already sorted and you want to have the fastest possible sort time, a simple Insertion Sort algorithm actually beats out the fully-optimized built-in Ruby #sort, in this case by a factor of about 3.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;QuickSort: Avoiding Worst Case

&lt;ul&gt;
&lt;li&gt;When I attempted to run QuickSort on the mostly-sorted list, it crashed the program until I brought the dataset size all the way down from 1 million to about 15,000.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Quick sort (mostly sorted 15670 nums): 3.8133098 s 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;At this point, the runtime for these 15,000 sorted elements was the same as QuickSort running on 1 MILLION randomized elements, and while the number of quicksort recursions was smaller, the number of loops which occurred in the partition method was drastically larger.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As described above this happens because the pivot point is at the end of the array, so every single other element in &lt;code&gt;arr&lt;/code&gt; is less than the pivot point! Instead of making two even subproblems to achieve the nlgn runtime, we are creating 2 subproblems of size 1 and n-1. The summation of 1 to n is ϴ( n^2 ). Think about the summation of 1 to 10. It is &lt;code&gt;(10 + 1) * (10 / 2) = 55&lt;/code&gt;. Replacing 10 with n, &lt;code&gt;(n + 1) * (n/2) = (n^2 )/2 + n/2&lt;/code&gt;. Drop coefficients and lower order terms to get &lt;code&gt;n^2&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To solve this problem of ϴ(n^2 ) runtime for a nearly sorted list, we can be smart about how we choose a pivot element. If I run optimize_pivot to choose my pivot point, I find the median value between the values of the low, hi, and med indices in the subarray. I then switch that value with &lt;code&gt;arr[hi]&lt;/code&gt; and continue to use &lt;code&gt;hi&lt;/code&gt; as my pivot index. If the array is already sorted, I am now using the median value of the list rather than an extreme and can achieve ϴ(n * lgn) runtime on a sorted list because I am back to breaking my problem in halves rather than subtracting one from the size.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Better QuickSort Code&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;quicksort_opt!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;hi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;hi&lt;/span&gt;
        &lt;span class="n"&gt;partition_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;partition_opt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;quicksort_opt!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;partition_index&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;quicksort_opt!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;partition_index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hi&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;partition_opt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="n"&gt;optimize_pivot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="n"&gt;pivot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
     &lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
     &lt;span class="n"&gt;hi&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
     &lt;span class="kp"&gt;loop&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
         &lt;span class="kp"&gt;loop&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
             &lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
             &lt;span class="k"&gt;break&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;pivot&lt;/span&gt;
         &lt;span class="k"&gt;end&lt;/span&gt;

         &lt;span class="kp"&gt;loop&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
             &lt;span class="n"&gt;hi&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
             &lt;span class="k"&gt;break&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;pivot&lt;/span&gt;
         &lt;span class="k"&gt;end&lt;/span&gt;
         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;hi&lt;/span&gt;
         &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lo&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;optimize_pivot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;hi&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;Here is a second performance metric of all the algorithms including the optimized quicksort&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ruby's native sort (1 million numbers): 1.1003078 s
Merge sort (1 million nums): 2.1523891 s
Quick sort (1 million nums): 3.8681517 s
Quick sort optimized (1 million nums): 3.8711199 s
Ruby sort (mostly sorted 1 million nums): 0.5628704 s
Merge sort (mostly sorted 1 million nums): 1.453362 s
Optimized quicksort (mostly sorted 1 million nums): 2.6978179 s
Insertion sort (mostly sorted 1 million nums): 0.1951487 s
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;






&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;[1] &lt;em&gt;Introduction to Algorithms&lt;/em&gt;, Cormen, Leiserson, Rivest, Stein&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>computerscience</category>
      <category>programming</category>
    </item>
    <item>
      <title>Developing Style: Sinatra Security, Decorator Design Pattern</title>
      <dc:creator>Micah Shute</dc:creator>
      <pubDate>Tue, 25 Sep 2018 01:32:04 +0000</pubDate>
      <link>https://forem.com/micahshute/developing-style-sinatra-security-decorator-design-pattern-4lao</link>
      <guid>https://forem.com/micahshute/developing-style-sinatra-security-decorator-design-pattern-4lao</guid>
      <description>&lt;p&gt;I intend on documenting all that I learn in these early stages of my programming education for 3 reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If nothing else, to solidify what I learn&lt;/li&gt;
&lt;li&gt;Receive negative feedback from those more experienced&lt;/li&gt;
&lt;li&gt;Help other beginners through what I write and the feedback I receive.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The most important part to me is item 2 - I am a firm believer that negative feedback is one of if not the most important ingredient to intellectual growth. I have never had a programming mentor, and I don't see the possibility for one in the near future, so I want to make up for the lack of that feedback element as much as I can.  So I encourage any experienced developer reading this, if you see something inaccurate or inefficient in what I am writing, please feel free to drop some knowledge bombs on me. In this article specifically, I am open to feedback on security best practices, because that seems like a too-often neglected area, and one in which I have a lot to learn.&lt;/p&gt;

&lt;p&gt;That being said, I am writing today on lessons learned from making my first web app, which I did using the Sinatra framework. I will touch on what I learned about implementing proper application security, and then on a Decorator Design Pattern which I utilized in the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security
&lt;/h2&gt;

&lt;p&gt;I was really excited to learn about and try to implement an OOP design pattern, but that wasn't the first area of further study I encountered while making the app. Instead, it was the hurdle of instituting proper security. While this perhpas didn't have the elegance that I was hoping for,&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2yh2LZTA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/7wqhs6w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2yh2LZTA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/7wqhs6w.png" alt="Lightsaber"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;it is an essential tool which is extremely practical and needs to be taken as seriously as any new algorithm or efficient design pattern.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UiDLpMoW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/xeDiQuR.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UiDLpMoW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/xeDiQuR.jpg" alt="Blaster"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even in a simple web app, proper authentication and authorization are not trivial. If not taken seriously, you risk exposing your users' information, your app's information, and even compromising your server. [2] Furthermore, you don't develop the skills and the muscle memory which you may need later on to secure a more sensitive application.&lt;/p&gt;

&lt;p&gt;So, what steps are necessary for a simple Sinatra App? Well, we have to consider how users are authorized and authenticated. We check their username and password at login against the database. Then we persist a session with cookies. These are the two major areas of vulnerability for our use-case. Fortunately, using ActiveRecord abstracts away guarding against &lt;a href="https://en.wikipedia.org/wiki/SQL_injection"&gt;SQL injection&lt;/a&gt; at login by using prepared statements (using parameterized queries) &lt;a href="https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet"&gt;OWASP's SQL Injection Cheat Sheet&lt;/a&gt;. Sinatra also provides us (almost) all of the tools we need to keep our cookies secure if we take the time to properly use it. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bGavk42U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/Kx0Lxfv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bGavk42U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/Kx0Lxfv.png" alt="Cookies"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you may or may not know, cookies are hashes (which are just dictionaries) sent to the user from the server to store on their browser. This is so subsequent HTTP requests from the user to the server can be sent with that cookie, and the server can know information about this user - for example, that they have been previously authenticated (ie, it is used to persist state). &lt;/p&gt;

&lt;p&gt;One problem is that cookies which are altered by the user or a third party can cause unexpected, and potentially "bad" things to happen, especially if these changes were done with malicious intent. To help stop "intelligently" transforming cookie data in a specific way to harm the operation of the application, we could encrypt our cookies. That would still potentially allow changing the data, but the person will probably not know how they are changing it. Sinatra does one better by encrypting our cookies by default AND signing them, which encrypts the data AND can tell the server if the data has been tampered with. This is done via the "session_secret". &lt;/p&gt;

&lt;p&gt;So, if Sinatra does this, why do we care about doing anything else?     &lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Note: you can also have your cookies stolen, and then used by a third party pretending they are you even through your own browser - this is something I learned after making the site, and I will discuss it below. Sinatra provides some protection against this by making the cookies HTTP only)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Rack (Sinatra Middleware) signs cookies using &lt;a href="https://en.wikipedia.org/wiki/HMAC"&gt;HMAC-SHA1&lt;/a&gt; via &lt;a href="https://en.wikipedia.org/wiki/OpenSSL"&gt;OpenSSL&lt;/a&gt;, using the session_secret and the encoded data in the session. While the HMAC-SHA1 hashing is a one-way process (which means an attacker can't reverse it), it is also a very fast process - which means that an attacker can run it over and over very quickly with different guesses to what your secret word is. They can get your session_secret by running their guess and their cookie data through the same HMAC-SHA1 algorithm and seeing if their output hash equals your cookie hash. If it does, their guess was correct, and now they can fool the server. This is called a dictionary attack. And they don't have to code this process themselves; they can &lt;a href="https://github.com/hashcat/hashcat"&gt;download software&lt;/a&gt; made to do this quickly and efficiently. They can also get pre-assembled dictionaries of common passwords and secret phrases. I saw an example where someone cracked a Sinatra app with a session_secret of "super secret" within 45 seconds of a dictionary attack [2]. This is the danger of HMAC-SHA1 being fast - the shorter our string we use, the faster we can get hacked. Sinatra's GitHub page recommends at least a 32-byte session_secret. At one byte per character&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="s2"&gt;"a"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bytesize&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we are significantly undershooting that recommendation by using "secret" or "super secret" (which are 6 bytes and 13 bytes respectively).&lt;/p&gt;

&lt;p&gt;Also, it should go without saying, that if we make our session_secret available publicly (i.e. put it on GitHub by accident during a commit), no guessing would even have to be done to hack your cookies. &lt;/p&gt;

&lt;p&gt;So, what did I do to combat this? &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[X] Obtain a random 64-bit hex that won't be in a dictionary. Generate it via the sysrandom gem which creates the hex using the Native OS's method, which is more secure. Copy the output of the code below to obtain a random 64-byte hex string.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ruby &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"require 'sysrandom/securerandom'; puts SecureRandom.hex(64)"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It should be noted that this is a 64 bit &lt;a href="https://en.wikipedia.org/wiki/Hexadecimal"&gt;hex&lt;/a&gt; value, so each character (even though as a string it is 1 byte) represents 4 bits (or half a byte) per character. (Note that 2^4 = 16, which is the number of possible symbols in a single hex character). So the output as a string is actually 128 bytes (ie there are 128 hex symbols).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; [X] Save my session_secret 64-byte hex string as an environment variable as recommended by &lt;a href="https://12factor.net/config"&gt;The 12 Factor App&lt;/a&gt; along with my API Key, so they don't end up anywhere I don't want them to, I can change them easily, and they are language and OS-agnostic. Retrieve it for your app by saying:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:session_secret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'SESSION_SECRET'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Read more about &lt;a href="http://blog.honeybadger.io/ruby-guide-environment-variables/"&gt;Environment Variables here&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;A few days after making the app, I was reading about Cross-Site Request Forgery, (&lt;a href="https://en.wikipedia.org/wiki/Cross-site_request_forgery"&gt;CSRF&lt;/a&gt;). I read that people can use posts on sites that do not properly sanitize user input to cause a user to cause a user's browser to visit a site without the user's knowledge (usually via using an img tag with a src to that site). I know very little about Javascript, AJAX, etc, but this prompted me to learn more about it (which I will be sharing soon). Anyway, I decided to go to my site and do some messing around, and I found that I was able to insert scripts into the site via posting comments. This allows an attacker a whole host of options, from stealing other user's cookies, conducting CSRF attacks on them, or writing over that web page. I decided I was going to pretend to be someone trying to sow discontent among the users of the site (I got all of the query information by inspecting the site in the browser, not from the process of making it): &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bEFHtXGk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/XQty8t7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bEFHtXGk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/XQty8t7.png" alt="script in post"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZN1l1u1E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/trgsg9s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZN1l1u1E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/trgsg9s.png" alt="post output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To fix this problem, I needed to sanitize my input. At first I was going to filter it myself, but the best way is probably to use an established method. So I ended up using the sanitize gem, and now my hacking attempts look like this: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fxhf8Wqe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/002rLv4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fxhf8Wqe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/002rLv4.png" alt="sanitized"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;I am dissapointed that I got to the point of making a web app and this very basic concept slipped by me. It should be prerequisite knowledge to anyone designing a web app.   &lt;/p&gt;


&lt;h2&gt;
  
  
  My First Design Pattern - The Decorator
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;My App:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let users follow and react to entities with a lot of information being pulled from an API&lt;/li&gt;
&lt;li&gt;Allow users to post and react to posts, as well as react to entities within the app.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Complications:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;My app will be displaying LOTS of data from the API calls - all of which can change rapidly. So, I don't want to save this in my database, because:

&lt;ul&gt;
&lt;li&gt;The information would have to be pulled from the API frequently and overwritten in the database frequently - it would be too much redundant work for it to be useful.&lt;/li&gt;
&lt;li&gt;It is too much information for the size of my free cloud database. &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;But, I need my database objects for these entities to keep track of what users decide to follow, all posts related to them, likes and dislikes, etc. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Problem To Solve:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I want to access my database relations and all of my API data in one class for each type of object. For example, I want my Entity class to have all of the ActiveRecord::Base functionality, AND have all of my API data available via method calls. But I want to do this without saving extraneous information.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This problem is solvable in some elementary ways. But Design Patterns aren't always used to transform a problem from being un-solvable to solvable - lots of times they are to make a problem's solution elegant, flexible, and easy for us as developers once it's instantiated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My Answer&lt;/strong&gt; The Decorator.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Decorator: Attach additional responsibilities to an object dynamically. Decorators define a higher-level interface that makes the subsystem easier to use. [1]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Coming to a decision of what design patterns to use seems to me to be just as hard as implementing them, if not harder - here's a graphical representation of how they interrelate, helping us to decide which one to use in relation to others:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Iy63fBxF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/vQXBIko.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Iy63fBxF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/vQXBIko.png" alt="Design Pattern Relationships"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That is a lot to take in for my first time. So this is how I came to my decision.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Design Patterns [1] provides a methodology for choosing a pattern. This methodology includes a list of general problems which you may be trying to solve, and corresponding possible design pattern solutions. Reading this list, I came across &lt;em&gt;Extending functionality by subclassing&lt;/em&gt;. I wanted to extend functionality, but I didn't want to subclass. Check.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I compiled the listed possible design pattern solutions: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bridge &lt;/li&gt;
&lt;li&gt;Chain of Responsibility&lt;/li&gt;
&lt;li&gt;Composite&lt;/li&gt;
&lt;li&gt;Decorator&lt;/li&gt;
&lt;li&gt;Observer&lt;/li&gt;
&lt;li&gt;Strategy&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I analyzed the intents of each, as described in [1]:&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  Bridge
&lt;/h2&gt;

&lt;p&gt;Decouple an abstraction from its implementation so that the two can vary independently&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This wasn't quite right. Neither the API nor the database model was an abstraction of the other.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  Chain of Responsibility
&lt;/h2&gt;

&lt;p&gt;Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not applicable.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  Composite
&lt;/h2&gt;

&lt;p&gt;Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I wasn't working with hierarchical structures. This one wasn't correct for my particular situation.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  Observer
&lt;/h2&gt;

&lt;p&gt;Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No, because I am not trying to ensure unified actions between connected objects.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  Strategy
&lt;/h2&gt;

&lt;p&gt;Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I think I could have solved the problem using a Strategy design pattern. I was unsure which one would work best, and I ended up deciding to go with the decorator.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  Decorator
&lt;/h2&gt;

&lt;p&gt;Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sounds about right. &lt;/p&gt;

&lt;p&gt;However, I want to add here that my use for a decorator here (even though it worked well for me) is probably not the &lt;em&gt;perfect&lt;/em&gt; one. A decorator as a concept is fully utilized when you specifically want &lt;em&gt;dynamic&lt;/em&gt; responsibilities allocated (ie they can be given and withdrawn whenever you want) to many &lt;em&gt;individual objects&lt;/em&gt;, not whole classes. This prevents this augmentation of functionality affecting other objects. That being said, I do have a plan to refactor to better use the design pattern, and by using it already, it is easier to refactor now.&lt;/p&gt;

&lt;p&gt;So first let's do a simple example which explains a 'perfect' scenario for a decorator: imagine I'm buying ice cream. How does a decorator help us?&lt;/p&gt;

&lt;p&gt;Set up our Universe:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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;PriceError&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;StandardError&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"That is not a valid price"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;super&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;class&lt;/span&gt; &lt;span class="nc"&gt;IceCream&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;price: &lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="vi"&gt;@price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;price&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;price&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;PriceError&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;amt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_a?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;amt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_a?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="vi"&gt;@price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;amt&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;price&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="vi"&gt;@price&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;ingredients&lt;/span&gt;
        &lt;span class="s2"&gt;"Ice Cream"&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;Now, we want to be able to choose the ice cream we want and change ingredients and price accordingly. To do this, we can create Decorator classes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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;WithJimmies&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="vi"&gt;@item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item&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;price&lt;/span&gt;
        &lt;span class="vi"&gt;@item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;price&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.5&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;ingredients&lt;/span&gt;
        &lt;span class="vi"&gt;@item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ingredients&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;", Jimmies"&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;class&lt;/span&gt; &lt;span class="nc"&gt;WithChocolateSyrup&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="vi"&gt;@item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item&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;price&lt;/span&gt;
        &lt;span class="vi"&gt;@item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;price&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.2&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;ingredients&lt;/span&gt;
        &lt;span class="vi"&gt;@item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ingredients&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;", Chocolate Syrup"&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;class&lt;/span&gt; &lt;span class="nc"&gt;WithOreos&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="vi"&gt;@item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item&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;price&lt;/span&gt;
        &lt;span class="vi"&gt;@item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;price&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;1.0&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;ingredients&lt;/span&gt;
        &lt;span class="vi"&gt;@item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ingredients&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;", Oreos"&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;So now we can make our ice cream!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;my_snack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;IceCream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;my_snack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;WithJimmies&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="n"&gt;my_snack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;my_snack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;WithOreos&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="n"&gt;my_snack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;my_snack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ingredients&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; "Ice Cream, Jimmies, Oreos"&lt;/span&gt;
&lt;span class="n"&gt;my_snack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;price&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 2.5&lt;/span&gt;

&lt;span class="n"&gt;my_friends_snack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;IceCream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;my_friends_snack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;WithChocolateSyrup&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="n"&gt;my_friends_snack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;my_friends_snack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ingredients&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; "Ice Cream, Chocolate Syrup"&lt;/span&gt;
&lt;span class="n"&gt;my_friends_snack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;price&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 1.2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's the functionality we want. I start out with just an IceCream class which is a dollar. That's all I want the class to do. I can check out with just an ice cream, without specifying I don't want the other stuff. I can manually change or 'decorate'  my ice cream without the original class having to do anything except for it to adhere to the interface of having price and ingredients attributes. My friend can do the same thing with the same class, but choose different options, getting his own personalized outcome.&lt;/p&gt;

&lt;p&gt;I can even add other classes into the mix which can be decorated by the same decorators, provided they adhere to the &lt;em&gt;'interface'&lt;/em&gt; requiring them to have a price and ingredients. Other than that, they can be completely different!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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;FroYo&lt;/span&gt; 
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;price: &lt;/span&gt;&lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="vi"&gt;@price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;price&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;price&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="vi"&gt;@price&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;price_to_s&lt;/span&gt; 
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;"$&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="s1"&gt;'%.2f'&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="vi"&gt;@price&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&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;ingredients&lt;/span&gt;
        &lt;span class="s2"&gt;"Froyo"&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;Now just replace the first line in the last example with my_snack = FroYo.new, and you can have the same output except with froyo instead of ice cream!&lt;/p&gt;

&lt;p&gt;"So why can't you just program that functionality in as methods into a superclass and then subclass out the functionality?" Well, you can. But a big goal of the implementation of design patterns in OOP design is to &lt;strong&gt;favor object composition over class inheritance&lt;/strong&gt; Why?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Object composition is also called black-box reuse. It is where we use a bunch of different types of objects to accomplish larger tasks through the way in which they are related to each other at runtime. It's a more modular and flexible way to do things. &lt;/li&gt;
&lt;li&gt;Inheritance can arguably be said to "break encapsulation" - changes to the parent class can (unexpectedly) alter the way the child behaves due to unnecessary overlap.&lt;/li&gt;
&lt;li&gt;It is easier to re-use compositional patterns than inheritance patterns.&lt;/li&gt;
&lt;li&gt;[1] states: "Ideally, you shouldn't have to create new components to achieve reuse. You should be able to get all the functionality you need just by assembling existing components through object composition." It goes on to admit that this is not always feasible, however.&lt;/li&gt;
&lt;li&gt;All that being said, inheritance is easy to use and supported by the language, so there is a benefit to using it at times.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While both ways can solve a problem, object composition helps to prevent large, unwieldy superclasses, allows easier dynamic appropriation of responsibilities, and helps us adhere to the &lt;a href="https://en.wikipedia.org/wiki/Single_responsibility_principle"&gt;single responsibility principle&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we have an intuition of what a decorator is, I think it is important to see a formal definition, in the form of a &lt;a href="https://courses.cs.washington.edu/courses/cse403/11sp/lectures/lecture08-uml1.pdf"&gt;Class Diagram&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AfTFPIxq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://i.imgur.com/XADKZbN.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AfTFPIxq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://i.imgur.com/XADKZbN.gif" alt="Decorator Pattern UML"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, how did I use a decorator? &lt;/p&gt;

&lt;p&gt;I wanted a lightweight database, so I only wanted to save an entity's string identifier in the database, which is enough to get all of the information from the API. Furthermore, I didn't want to save EVERY entity identifier in the database, only ones that users were interested in and interacting with. So, I built a decorator, which took as an initialize argument a class with the API's unique identifier as an attribute. This class needed in the Decorator's initialize method could be one of two things: a "Placeholder" class (which I made), or an ActiveRecord instance (both of which were required to have the entity_identifier attribute). The ability to use a Placeholder or an ActiveRecord class was the main reason I chose using a Decorator over a Strategy, because it allowed me to only save into the database entities users were actually interacting with (ie have an interface which allowed me to use an ActiveRecord class an a "throwaway" class). I gave the decorator the ability to retrieve its relationships (if it was an ActiveRecord::Base instance) by mirroring the ActiveRecord methods. For example, I still wanted &lt;code&gt;entity.user_likes&lt;/code&gt; to return ActiveRecord user instances. I wanted to be able to create new database relationships and to call &lt;code&gt;.save&lt;/code&gt; on the decorator class as if it were an ActiveRecord object. I also wanted any user interaction to cause the entity to be saved into the database if it had not yet been saved while simultaneously replacing the Placeholder object with an actual ActiveRecord object in the Decorator so I could save and retrieve all relationships. So I included methods in the decorator to do this. Some examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;entity_identifier&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entity_identifier&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;save&lt;/span&gt;
    &lt;span class="n"&gt;saved&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt; 
    &lt;span class="c1"&gt;# note: the EntityPlaceholder #save method returns an ActiveRecord object&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;saved&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_a?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;EntityPlaceholder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="n"&gt;saved&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;following_users&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_a?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;EntityPlaceholder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;following_users&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also gave the decorator the ability to retrieve information from the API via an APIManager class. The decorator would populate itself with that extra data upon instantiation. &lt;/p&gt;

&lt;p&gt;This pattern will let me extend functionality of my app when I have reprisentations of entities in different parts of my app where I will want to display different attributes, get its information from different API endpoints, and interact with the user differently. Any new functionality I want changed / added can be done so on an ActiveRecord object or a Placeholder object via different decorators.&lt;/p&gt;

&lt;p&gt;While maybe not the &lt;em&gt;best&lt;/em&gt; use-case for a decorator, or I may have implemented it sloppily, or there may be some design pattern that may have worked better, using this pattern certainly made my code easy to work with, gave me practice searching through and choosing design patterns, and awarded me a better understanding of the decorator design pattern. Next time I have a problem, I will be able to have a new way to potentially tackle it, and I will be able to improve on my concrete implementation of the idea.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NNF6xX-x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/OOZKmer.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NNF6xX-x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/OOZKmer.png" alt="larger world"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;[1] "Design Patterns Elements of Reusable Object-Oriented Software", Gamma, Helm, Johnson, Vlissides, 1995&lt;br&gt;&lt;br&gt;
[2] &lt;a href="https://martinfowler.com/articles/session-secret.html"&gt;One Line of Code that Compromises Your Server&lt;/a&gt;&lt;br&gt;&lt;br&gt;
[3] &lt;a href="https://github.com/sinatra/sinatra#session-secret-security"&gt;Sinatra GitHub README&lt;/a&gt;&lt;br&gt;&lt;br&gt;
[4] &lt;a href="https://github.com/cryptosphere/sysrandom"&gt;SysRandom GitHub README&lt;/a&gt;&lt;br&gt;&lt;br&gt;
[5] &lt;a href="http://blog.honeybadger.io/ruby-guide-environment-variables/"&gt;A Rubyist's Guide to Environment Variables&lt;/a&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>webdev</category>
      <category>ruby</category>
      <category>security</category>
    </item>
    <item>
      <title>Understanding the Monty Hall Problem</title>
      <dc:creator>Micah Shute</dc:creator>
      <pubDate>Fri, 21 Sep 2018 14:30:11 +0000</pubDate>
      <link>https://forem.com/micahshute/understanding-the-monty-hall-problem-3mgf</link>
      <guid>https://forem.com/micahshute/understanding-the-monty-hall-problem-3mgf</guid>
      <description>&lt;p&gt;This isn't exactly about development or coding, but it is an exercise in problem solving, logic and probability, all of which are fundamentals of our trade. As engineers and programmers, logic and mathematics, particularly probability and induction, are areas in which we should pursue mastery.&lt;/p&gt;

&lt;p&gt;I was recently listening to a podcast that was recommended by a blogger on this site, and during one episode discussing big-O theory, the Monty Hall problem was mentioned. The commentators talked a little about it, at which point they admitted to not 'getting it' and moved on. This motivated me to share my understanding of the problem because I think that as engineers we should be the ones who are able to grasp this concept and problems like it.    &lt;/p&gt;

&lt;p&gt;So here's how I 'got it'. It took some thinking, but in the end, it's actually not too complicated.&lt;/p&gt;

&lt;p&gt;In case you are unfamiliar with the problem, the Monty Hall problem is as follows:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You are presented with 3 doors. Behind only one is a prize.
&lt;/li&gt;
&lt;/ul&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%2Ftxe872kzoah3ynxycj3k.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%2Ftxe872kzoah3ynxycj3k.png" alt="3 doors"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You pick a door which you think the prize may be behind.
&lt;/li&gt;
&lt;/ul&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%2Fz84dm0puooe6pvyv9oyr.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%2Fz84dm0puooe6pvyv9oyr.png" alt="initial choice"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;After you pick the door, a 3rd party (ie the gameshow host) opens up a door which does NOT have the prize. &lt;/li&gt;
&lt;li&gt;You are then given the option to either stay with your initial guess or switch your guess to the door which the game show host did NOT open. &lt;/li&gt;
&lt;/ul&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%2Fruv6l2o6tzz9e5hrijta.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%2Fruv6l2o6tzz9e5hrijta.png" alt="final choice"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which should you do? Switch or stay? Does it matter?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The initial intuition for most people is that once you are shown the door with no prize, the possibility is now 50-50 between the two remaining doors, so it doesn't matter if you switch or not. But this is not the case. It is actually probabilistically in your best interest to switch to the other door. But let's be good engineers and follow the scientific process with an initial hypothesis that you have a 50% chance of winning either way.&lt;/p&gt;

&lt;p&gt;We have our hypothesis, so let's experiment.&lt;/p&gt;

&lt;p&gt;Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;rand_gen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;prize_locations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;switch_wins&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;stay_wins&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="c1"&gt;#generate winning spots&lt;/span&gt;
&lt;span class="mi"&gt;10000&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="c1"&gt;# rand_gen.rand(3) returns  0, 1, or 2&lt;/span&gt;
    &lt;span class="n"&gt;prize_locations&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rand_gen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


&lt;span class="n"&gt;prize_locations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&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;prize_loc&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="c1"&gt;# contestant chooses a random location&lt;/span&gt;
    &lt;span class="n"&gt;initial_choice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rand_gen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="c1"&gt;# monty opens a door without a prize -&amp;gt; init. choice is prize ? (random opening of one of the remaining 2 doors) : (since 1, 2, and 3 must all be an option, 6 minus the other two will always give us the leftover one)&lt;/span&gt;
    &lt;span class="n"&gt;opened_door&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;initial_choice&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt;  &lt;span class="n"&gt;prize_loc&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prize_loc&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;rand_gen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;initial_choice&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;prize_loc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Universe split 1: I decide to stay with my choice.&lt;/span&gt;
    &lt;span class="n"&gt;stay_wins&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;prize_loc&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;initial_choice&lt;/span&gt;
    &lt;span class="c1"&gt;# Universe split 2: I switch &lt;/span&gt;
    &lt;span class="n"&gt;switch_wins&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;prize_loc&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;initial_choice&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;opened_door&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Total wins if you stay: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;stay_wins&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, which is &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;stay_wins&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;10000.0&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;%"&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Total wins if you switch: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;switch_wins&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, which is &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;switch_wins&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;10000.0&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;%"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[07:28:18] monty_hall  
//⚓   [⚛ micah] ruby monty_hall.rb  
Total wins if you stay: 3344, which is 0.3344%  
Total wins if you switch: 6656, which is 0.6656%  

[07:28:20] monty_hall  
//⚓   [⚛ micah] ruby monty_hall.rb  
Total wins if you stay: 3316, which is 0.3316%  
Total wins if you switch: 6684, which is 0.6684%  

[07:28:21] monty_hall  
//⚓   [⚛ micah] ruby monty_hall.rb  
Total wins if you stay: 3348, which is 0.3348%  
Total wins if you switch: 6652, which is 0.6652%  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another way you could do it which can give you a litte more info is randomly switch between staying and switching your doors:&lt;/p&gt;

&lt;p&gt;Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;rand_gen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;prize_locations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;switch_wins&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;stay_wins&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="c1"&gt;#generate winning spots&lt;/span&gt;
&lt;span class="mi"&gt;10000&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="c1"&gt;#rand_gen.rand(3) returns  0, 1, or 2&lt;/span&gt;
    &lt;span class="n"&gt;prize_locations&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rand_gen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


&lt;span class="n"&gt;prize_locations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&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;prize_loc&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="c1"&gt;#contestant chooses a random location&lt;/span&gt;
    &lt;span class="n"&gt;initial_choice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rand_gen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="c1"&gt;#monty opens a door without a prize -&amp;gt; init. choice is prize ? (random opening of one of the remaining 2 doors) : (since 1,2, and 3 must all be an option, 6 minus the other two will always give us the leftover one)&lt;/span&gt;
    &lt;span class="n"&gt;opened_door&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;initial_choice&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt;  &lt;span class="n"&gt;prize_loc&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prize_loc&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;rand_gen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;initial_choice&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;prize_loc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;#This time, let's just keep one universe and randomly choose&lt;/span&gt;
    &lt;span class="n"&gt;switch_or_stay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rand_gen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 0 means stay, 1 means switch&lt;/span&gt;
    &lt;span class="n"&gt;stay_wins&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;prize_loc&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;initial_choice&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;switch_or_stay&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;switch_wins&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;prize_loc&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;initial_choice&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;opened_door&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;switch_or_stay&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Total wins from when you stay: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;stay_wins&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, which is &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;stay_wins&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;10000.0&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;%"&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Total wins from when you switch: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;switch_wins&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, which is &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;switch_wins&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;10000.0&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;%"&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Total wins: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;wins&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;switch_wins&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;stay_wins&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, which is &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;wins&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;10000.0&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;%"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[07:43:07] monty_hall
//⚓   [⚛ micah] ruby monty_hall.rb
Total wins from when you stay: 1685, which is 0.1685%
Total wins from when you switch: 3303, which is 0.3303%
Total wins: 4988, which is 0.4988%

[07:43:08] monty_hall
//⚓   [⚛ micah] ruby monty_hall.rb
Total wins from when you stay: 1689, which is 0.1689%
Total wins from when you switch: 3307, which is 0.3307%
Total wins: 4996, which is 0.4996%

[07:43:09] monty_hall
//⚓   [⚛ micah] ruby monty_hall.rb
Total wins from when you stay: 1662, which is 0.1662%
Total wins from when you switch: 3398, which is 0.3398%
Total wins: 5060, which is 0.506%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, our hypothesis is wrong. Looks like we should probably switch doors. Time to refine my hypothesis and this time rely on more than just naive intuition. (Maybe you saw some new intuition above: that the only way you get a stay_win is if you guessed right initially)&lt;/p&gt;

&lt;p&gt;There are a few ways to look at the problem. First, let's look at a split universe timeline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have 3 doors and a prize behind one of them. So, for your initial pick, what is the probability that you correctly choose where the prize is? 

&lt;ul&gt;
&lt;li&gt;That's right - 1/3&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Let's freeze time right here and do a little more analysis. There are 2 possibilities that just happened in your choice. So let's split our universe.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Universe 1&lt;/strong&gt;: You fell within the 33.3% chance and chose correctly. Now, the game show host can open either of the remain doors, as neither of them has a prize. Now you have ANOTHER CHOICE (another split!)

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Universe 1.1&lt;/strong&gt; You stay with your initial pick. (Human factor, let's say 50%)

&lt;ul&gt;
&lt;li&gt;You win. (100%)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Universe 1.2&lt;/strong&gt; You switch. (50%) 

&lt;ul&gt;
&lt;li&gt;You lose. (100%)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Universe 2&lt;/strong&gt; You initially choose wrong, which happens 66.7% of the time. Now, the game show host can ONLY open the door without the prize behind it (leaving the other door with the prize) &lt;strong&gt;SPLIT Universe 2&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Universe 2.1&lt;/strong&gt; You stay with your initial pick. (50%)

&lt;ul&gt;
&lt;li&gt;You lose (100%)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Universe 2.2&lt;/strong&gt; You switch. (50%)

&lt;ul&gt;
&lt;li&gt;You win. (100%)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Analyzing mathematically&lt;/strong&gt;: So what's our problem statement? We want to know whether we win more if we switch or stay, right? So let's calculate the probability of winning given that you stay with your initial door, and then the probability of winning given that you switch doors. Note that we are giving the person a random 50% chance that they choose to switch or stay with their original door.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;P(win | stay) = [P(win) * P(stay | win)] / P(stay)  

P(win) = (Universe 1 &amp;amp;&amp;amp; Universe 1.1) || (Universe 2 &amp;amp;&amp;amp; Universe 2.2) =  (1/3) * (1/2) + (2/3) * (1/2) = 1/2    

P(stay | win) = Out of wins possibilities only, what percentage of those did you stay for?  
=  (Universe 1 &amp;amp;&amp;amp; Universe 1.1)  / [(Universe 1 &amp;amp;&amp;amp; Universre 1.1) || (Universe 2 &amp;amp;&amp;amp; Universe 2.2)] = (1/3) * (1/2) / (1/2) = 1/3

P(stay) = (Universe 1 &amp;amp;&amp;amp; Universe 1.1) || (Universe 2 &amp;amp;&amp;amp; Universe 2.1) = (1/3) * (1/2) + (2/3) * (1/2) = 1/2

P(win | stay) = [1/2 * 1/3] / 1/2 = 1/3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You could also say "Out of the times that I stay, how many times did I win?" That would give you the same answer: &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;P(win | stay): all wins which lie within stay universes
P(win | stay) = (Universe 1 &amp;amp;&amp;amp; Universe 1.1) / [(Universe 1 &amp;amp;&amp;amp; Universe 1.1) || (Universe 2 &amp;amp;&amp;amp; Universe 2.2)] = (1/3) * (1/2) / [(1/3) * (1/2) + (2/3) * (1/2)] = (1/3) * (1/2) / (1/2) = 1/3
P(win | stay) = 1/3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now, let's see the probability of winning given you switch. (While Baye's doesn't really buy us anything since we have a short timeline which describes everything for us, I'll do it both ways for the sake of thoroughness).  &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;P(win | switch) =  [P(win) * P(switch | win)] / P(switch)  

P(win) = (Universe 1 &amp;amp;&amp;amp; Universe 1.1) || (Universe 2 &amp;amp;&amp;amp; Universe 2.2) =  (1/3) * (1/2) + (2/3) * (1/2) = 1/2    

P(switch | win) = Out of wins possibilities only, what percentage of those did you switch for?  
=  (Universe 2 &amp;amp;&amp;amp; Universe 2.2)  / [(Universe 1 &amp;amp;&amp;amp; Universre 1.1) || (Universe 2 &amp;amp;&amp;amp; Universe 2.2)] = (2/3) * (1/2) / (1/2) = 2/3

P(switch) = (Universe 1 &amp;amp;&amp;amp; Universe 1.2) || (Universe 2 &amp;amp;&amp;amp; Universe 2.2) = (1/3) * (1/2) + (2/3) * (1/2) = 1/2

P(win | switch) = [1/2 * 2/3] / 1/2 = 2/3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Or, you could say:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;P(win | switch) : all wins which lie within switch universes
P(win | switch) = (Universe 2 &amp;amp;&amp;amp; Universe 2.2) / [(Universe 1 &amp;amp;&amp;amp; Universe 1.1) || (Universe 2 &amp;amp;&amp;amp; Universe 2.2)]
P(win | switch) = [(2/3) * (1/2)] / [(1/3) * (1/2) + (2/3) * (1/2)] 
P(win | switch) = (2/3) * (1/2) / (1/2) = 2/3

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

&lt;/div&gt;



&lt;p&gt;From our mathematical analysis, we can see that you are twice as likely to win if you switch than if you stay. You will also win more (2/3 of the time) if you switch every time than if you randomly choose to switch or stay (in which case you win 1/2 of the time)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analyzing with logic&lt;/strong&gt;: If you choose to &lt;strong&gt;always switch&lt;/strong&gt;, you will &lt;strong&gt;always&lt;/strong&gt; be right if you &lt;strong&gt;initially&lt;/strong&gt; chose the wrong door. So, since you initially choose wrong ( 1- 1/3 = ) 66.67% of the time, you will be guaranteed to choose the &lt;strong&gt;correct&lt;/strong&gt; door 66.67% of the time if you &lt;strong&gt;always&lt;/strong&gt; switch. If you choose &lt;strong&gt;never&lt;/strong&gt; to switch, you are guaranteed to be correct &lt;strong&gt;only if&lt;/strong&gt; you initially picked the correct door out of the 3 on your first try, which was a 33.3% chance.   &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expanding this problem out to get a better intuition&lt;/strong&gt;: Sometimes when a problem seems hard to grasp, I like to take the numbers to extremes while maintaining the necessary relationships. In this case, we know that after your choice of 1 door, the host will open &lt;strong&gt;all of the doors&lt;/strong&gt; but &lt;strong&gt;one other&lt;/strong&gt; (even though in our case with 3 doors, this is just him opening one door) AND these doors must have no prize. So, using this relationship, let's expand our situation to 1 million doors with one prize. Now after you choose a door, the game show host has to open &lt;strong&gt;all the rest but one&lt;/strong&gt;. And he can't open the one with the prize. So, unless you think you chose right on your first try with a million to one odds, don't you think this is a pretty good deal, as the host is practically forced to show you where the prize is?! This is the exact same concept, except now our odds for getting the prize when we switch are 999,999/1,000,000 instead of 2/3. It's much easier to have intuition on this concept when it is expanded in this way.&lt;/p&gt;

&lt;p&gt;Now, our hypothesis matches our experimental data, and we can call it a day.&lt;/p&gt;

</description>
      <category>logic</category>
      <category>math</category>
      <category>problemsolving</category>
    </item>
    <item>
      <title>Setting up Windows Subsytem for Linux</title>
      <dc:creator>Micah Shute</dc:creator>
      <pubDate>Wed, 19 Sep 2018 19:27:15 +0000</pubDate>
      <link>https://forem.com/micahshute/setting-up-windows-subsytem-for-linux-3b7n</link>
      <guid>https://forem.com/micahshute/setting-up-windows-subsytem-for-linux-3b7n</guid>
      <description>&lt;p&gt;I am relatively new in the world of programming, and I have decided to document new concepts and other things that took me a while to figure out - not only to solidify my learning but to help others who may be trying to learn or accomplish the same things. &lt;/p&gt;

&lt;p&gt;I set up Windows Subsystem for Linux (WSL) using a conglomerate of different blogs and resources, with varying levels of being out of date. I did not come across one that was recent and had all I needed in it, so hopefully this can serve that purpose for someone. &lt;/p&gt;

&lt;h1&gt;
  
  
  Setting up Windows Subsystem for Linux for Development
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;It is no longer necessary to enable developer mode for Windows Subsystem Linux to work&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Windows Ready
&lt;/h2&gt;

&lt;p&gt;1) Make sure you are running Windows 10. Windows Subsystem Linux (WSL) is &lt;strong&gt;not&lt;/strong&gt; automatically enabled on windows. So, to start off, we need to enable it!&lt;br&gt;&lt;br&gt;
    a) Go to your Windows Search bar and type in &lt;code&gt;turn windows features on or off&lt;/code&gt;  &lt;/p&gt;

&lt;p&gt;b)  Click on the result that matches your query. It will be in your Control Panel.  You should see something like this:    &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%2Fk4x418deogy16bqva8ab.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%2Fk4x418deogy16bqva8ab.png" alt="toggle windows features"&gt;&lt;/a&gt;   &lt;/p&gt;

&lt;p&gt;c)  Scroll down until you see "Windows Subsystem for Linux" - ensure its box is checked!   &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%2F2wkiufnn6iisl3h9dfm2.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%2F2wkiufnn6iisl3h9dfm2.png" alt="wsl checkbox"&gt;&lt;/a&gt;    &lt;/p&gt;

&lt;p&gt;2)  Restart your computer  &lt;/p&gt;

&lt;p&gt;3)  Check your Windows 10 version by going to &lt;code&gt;System Information&lt;/code&gt; and checking your Version. If your build is earlier than 16215, skip step 4 and proceed to step 5.  &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%2F6v6riw4zlxkcs52tiia1.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%2F6v6riw4zlxkcs52tiia1.png" alt="windows version"&gt;&lt;/a&gt;    &lt;/p&gt;

&lt;p&gt;4)  Open up Microsoft Store. Search for "Ubuntu"   &lt;/p&gt;

&lt;p&gt;a) Choose "Ubuntu" (I didn't use 16.04 or 18.04 LTS)  &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%2F7yp5rdmlaz4vbzbr15xa.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%2F7yp5rdmlaz4vbzbr15xa.png" alt="ubuntu choice in microsoft store"&gt;&lt;/a&gt;    &lt;/p&gt;

&lt;p&gt;5) If you run into errors or if you have an early version of Windows 10, see further information &lt;a href="https://docs.microsoft.com/en-us/windows/wsl/install-win10" rel="noopener noreferrer"&gt;here&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;6) Open up the Ubuntu app. Follow the prompts, which will include making a username and password. Don't forget your password!  &lt;/p&gt;

&lt;p&gt;Note: if you get an error at this step that says &lt;code&gt;Windows Subsystem for Linux has no installed distributions. Distributions can be installed by visiting the Windows Store: https://aka.ms/wslstore Press any key to continue...&lt;/code&gt;, try manually starting or restarting LxssManager in your Services Desktop App (just search &lt;code&gt;services&lt;/code&gt; in your windows search bar). In the &lt;code&gt;L&lt;/code&gt; section, you can right-click &lt;code&gt;LxssManager&lt;/code&gt;  and choose &lt;code&gt;Restart&lt;/code&gt; or &lt;code&gt;Start&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start Outfitting your new Linux Subsystem: RVM / Ruby, git, NodeJS, and Rails
&lt;/h2&gt;

&lt;p&gt;1) Once everything is set up, we can start setting up our system! Start off by running the following to download our dependencies: &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt-get update    
sudo apt-get install git-core curl zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev software-properties-common libffi-dev libpq-dev libgdbm-dev libncurses5-dev automake libtool bison gnupg postgresql postgresql-contrib
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;2) Install RVM by running:  &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;followed by    &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   \curl -sSL https://get.rvm.io | bash -s stable --ruby  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;and finally    &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   source ~/.rvm/scripts/rvm  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;3)  Let's install the bundler gem:  &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    gem install bundler  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;4)  And set up git:  &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    git config --global color.ui true     
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;For the next few commands, make sure to input your specific information:  &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    git config --global user.name "your_name"
    git config --global user.email "your_email@example.com"    
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can either communicate with your remote repositories via HTTPS or SSH. If you want to use SSH (which means you will not have to authenticate with your GitHub username and password before each push) - &lt;a href="https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/" rel="noopener noreferrer"&gt;follow these instructions.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;5)  Now let's get NodeJS installed, and then Rails so we can make a bunch of stuff!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;First, nodejs:  &lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
sudo apt-get install -y nodejs  
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Next, Ruby on Rails:  &lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gem install rails
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Choose your programming editor: VSCode
&lt;/h2&gt;

&lt;p&gt;You can use any editor you want, but I am going to be walking through setting up VSCode.&lt;/p&gt;

&lt;p&gt;1) Download VSCode &lt;a href="https://code.visualstudio.com/download" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Choose the Windows download, not the Linux download. Any required Linux downloads will be done via the Ubuntu terminal, and everything else should be downloaded for your Windows OS.&lt;/p&gt;

&lt;p&gt;2) To configure your Ubuntu terminal to be available in VSCode: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;open up VSCode&lt;/li&gt;
&lt;li&gt;open the Command Palette via &lt;code&gt;F1&lt;/code&gt; or &lt;code&gt;Ctrl&lt;/code&gt;+&lt;code&gt;Shift&lt;/code&gt;+&lt;code&gt;p&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;begin typing the following: &lt;code&gt;Terminal: Select Default Shell&lt;/code&gt;  until you see it. Select that option.&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%2Fk2a2ft8ycroujlqxp7qj.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%2Fk2a2ft8ycroujlqxp7qj.png" alt="command palette"&gt;&lt;/a&gt;  &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Once you select it, a few options will pop up. You want to select WSL&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%2F4dl6urgzipp4ah689dqf.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%2F4dl6urgzipp4ah689dqf.png" alt="WSL Terminal"&gt;&lt;/a&gt;  &lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;3) Now, you can use your Ubuntu terminal in VSCode. Select "New Terminal" in the "Terminal" drop-down, or type &lt;code&gt;Ctrl&lt;/code&gt;+&lt;code&gt;Shift&lt;/code&gt;+` in order to use it!&lt;/p&gt;

&lt;p&gt;4) Additional User Settings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can add a few things to your User Settings to customize and improve your programming experience. Most importantly, we can make VSCode treat .erb files like .html files, allowing us to use all the same shortcuts and get the same syntax highlighting. &lt;/li&gt;
&lt;li&gt;To open up user settings, again open up the Command Palette using &lt;code&gt;F1&lt;/code&gt; or &lt;code&gt;Ctr&lt;/code&gt;+&lt;code&gt;Shift&lt;/code&gt;+&lt;code&gt;p&lt;/code&gt; and type &lt;code&gt;Preferences: Open Settings (JSON)&lt;/code&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%2Fokltvl78r5au5lpnc88c.png" alt="Preferences - settings"&gt;
&lt;/li&gt;
&lt;li&gt;You will see a screen like this:
&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%2F2hfprtkic7220pdvanzv.png" alt="Preferences - settings"&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To have your erb files treated like html, add the following to your user settings (circled above):&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    "emmet.includeLanguages": {
        "erb": "html"
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Some optional personal preferences that I like:&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    "window.zoomLevel": -1,
    "editor.acceptSuggestionOnEnter": false,
    "editor.fontSize": 11,
    "editor.fontFamily": "Hack, Consolas, 'Courier New', monospace",
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Note that for the Hack font to be usable, you have to download it. You can check it out &lt;a href="https://sourcefoundry.org/hack/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Important Knowledge: Basic Use
&lt;/h2&gt;

&lt;p&gt;Your terminal is actually accessing an Ubuntu Virtual Machine which is running inside of your Windows OS. If you ever &lt;code&gt;&lt;/code&gt;&lt;code&gt;cd&lt;/code&gt;&lt;code&gt;&lt;/code&gt; in your terminal, you will be sent to the 'user home' of your Linux VM. That is also the default location you will be in when you open your Ubuntu app. You actually want to do all of your business inside of your normal Windows file space, not your Linux VM file space. So, you will need to know how to navigate in your terminal from your Ubuntu file system to your Windows file system. This is pretty simple if you understand how the system is set up, so let's go over that quickly. &lt;/p&gt;

&lt;p&gt;To allow you to access the functionality of a Linux machine, Windows stores the Ubuntu OS and file system inside of its own file system. You should NEVER access your Ubuntu files via your Windows machine. What you SHOULD do is save everything you are working on in your normal Windows file space, and access that via your Ubuntu terminal. So, how do you do that? Well, from the Ubuntu's point of view, it is just a normal Linux machine, but Microsoft has made a pathway between the Linux VM and your Windows OS via the &lt;code&gt;/mnt&lt;/code&gt; directory in your Ubuntu's root. &lt;/p&gt;

&lt;p&gt;Here is a quick visual of what the first few levels of any Linux file system look like:&lt;br&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F4bua64p5b3buagyyspgs.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%2F4bua64p5b3buagyyspgs.png" alt="linux file system"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the &lt;code&gt;mnt&lt;/code&gt; directory is made for other filesystems, so that is where Microsoft connected your Linux to your Windows machine:&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%2Fcfjnsjkfm0shewhzxiio.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%2Fcfjnsjkfm0shewhzxiio.png" alt="linux file system"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, you can get there from your starting point by typing:  &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd /mnt/c/users/your_windows_username
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;or &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd ../../mnt/c/users/your_windows_username
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If you put either of those lines as an &lt;code&gt;alias&lt;/code&gt; in your .bashrc file (found in &lt;code&gt;/home/your_linux_username/.bashrc&lt;/code&gt;) you can quickly move into your windows home directory (in the example below by just typing &lt;code&gt;home&lt;/code&gt; into your terminal):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;alias home="cd /mnt/c/users/your_windows_username"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can easily change your .bashrc file by navigating to your Linux home (by running just &lt;code&gt;cd&lt;/code&gt;) and typing:  &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nano .bashrc  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You are going to want to backup your .bashrc file first though so you don't mess it up. You can do that by copying a backup using   &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cp .bashrc .bashrc.bak  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You save a file you have modified in &lt;code&gt;nano&lt;/code&gt; by following the directions at the bottom of the screen: click &lt;code&gt;Ctrl&lt;/code&gt;+&lt;code&gt;X&lt;/code&gt; and then &lt;code&gt;y&lt;/code&gt; and then &lt;code&gt;Enter&lt;/code&gt; to save your changes.&lt;/p&gt;

&lt;p&gt;If you feel uncomfortable with these commands, check out the basic Linux commands link below in the resources. &lt;/p&gt;

&lt;p&gt;Remember, put all of your stuff in your windows directories! That way, you have access to it via your Linux Terminal or your Windows OS, and your VSCode editor can open to the correct location when you use&lt;/p&gt;

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

&lt;/div&gt;

&lt;p&gt;(if you are in your Linux file system, VSCode will open, but not to the right spot).&lt;/p&gt;

&lt;h2&gt;
  
  
  PostgreSQL Database Setup
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Setting up PostgreSQL allows simple production-level database integration into a Rails project. This allows easy hosting on Heroku with only a little setup.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;1) First, we want to &lt;a href="https://www.postgresql.org/download/windows/" rel="noopener noreferrer"&gt;Download PostgreSQL for Windows&lt;/a&gt; - download the Interactive Installer.&lt;br&gt;
2) Once everything is downloaded and installed, you can verify proper operation by typing in your terminal&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;psql -p 5432 -h localhost -U postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;once connection is verified, you can quit by typing&lt;/p&gt;

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

&lt;/div&gt;

&lt;p&gt;3) There are a few ways to do the next few steps but the easiest way is to use pgAdmin. Open up pgAdmin, which is a Graphical User Interface for PostgreSQL. &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%2Fjfzek5lgz9hx0jmyp5yi.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%2Fjfzek5lgz9hx0jmyp5yi.png" alt="PGAdmin in start"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This should open up pgAdmin in your browser. Start a server by right-clicking "PostgreSQL" and selecting "Connect Server"&lt;/li&gt;
&lt;/ul&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%2Fpmjzy3vigf8vti6ydp5b.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%2Fpmjzy3vigf8vti6ydp5b.png" alt="PostgreSQL selection"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ffzj55nwefbnhfldekkzq.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%2Ffzj55nwefbnhfldekkzq.png" alt="PostgreSQL connect"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enter the password you defined during the download&lt;/li&gt;
&lt;li&gt;Your PostgreSQL server is running, and can now be integrated into your projects.&lt;/li&gt;
&lt;li&gt;You also want to set up a new user/role and password that you want to use with your rails app. Ensure you give your user/role all available permissions during setup.&lt;/li&gt;
&lt;li&gt;During setup, ensure to fill out &lt;code&gt;Name&lt;/code&gt; in the &lt;code&gt;General&lt;/code&gt; tab, &lt;code&gt;Password&lt;/code&gt; in the &lt;code&gt;Definition&lt;/code&gt; tab, and enable all permissions in the &lt;code&gt;Privileges&lt;/code&gt; tab.&lt;/li&gt;
&lt;/ul&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%2Fjvyrq5y7vt1gzel4mxma.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%2Fjvyrq5y7vt1gzel4mxma.png" alt="create user"&gt;&lt;/a&gt;  &lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;EXAMPLE: CONNECTING YOUR POSTGRESQL SERVER TO YOUR RAILS APP&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make sure your server is connected and roles are configured as described above.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Make sure you are in a suitable directory (in your Windows file system space) and create a Rails app configured to use PostgreSQL:&lt;/p&gt;

&lt;p&gt;rails new my-first-app --database=postgresql&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now, let's configure our &lt;code&gt;database.yml&lt;/code&gt; file to allow our app to connect to our database. Add the following to your &lt;code&gt;config/database.yml&lt;/code&gt; file under BOTH &lt;code&gt;development:&lt;/code&gt; and &lt;code&gt;test:&lt;/code&gt; You will need to add a user and password which will correspond to the roles we created in pgAdmin.&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;host: localhost
user: your-postgres-username
password: your-postgres-usernames-password
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We can now test our database and rails interoperability by first setting up some architecture in our app:   &lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails g scaffold Post title:string body:text
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;now create and migrate a database: &lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rake db:create
rake db:migrate  
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If these fail, ensure you have added your database.yml configurations under both the development AND test sections&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now, start a server:  &lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails s  
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you navigate to &lt;code&gt;localhost:3000&lt;/code&gt; you should see that we are on Rails!  &lt;/p&gt;&lt;/li&gt;
&lt;/ul&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%2Fccqm9f1z94jagsld82o4.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%2Fccqm9f1z94jagsld82o4.png" alt="on Rails"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let's test our database by going to 'localhost:3000/posts'
&lt;/li&gt;
&lt;/ul&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%2Fsrkjlem5cr07d3m8jh0y.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%2Fsrkjlem5cr07d3m8jh0y.png" alt="posts"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now just follow the crud links and try to make a post! We should be seeing our database working great with our rails app!&lt;/li&gt;
&lt;/ul&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%2Feh5lv6c4t1owo1ua5onl.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%2Feh5lv6c4t1owo1ua5onl.png" alt="database works"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hopefully, everything is working for you! Now you're ready to develop using WSL!&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/wsl/install-win10" rel="noopener noreferrer"&gt;Microsoft Documentation: Windows Subsystem for Linux&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://help.github.com/articles/adding-a-new-ssh-key-to-your-github-account/" rel="noopener noreferrer"&gt;Setting up a SSH Key with GitHub&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://maker.pro/linux/tutorial/basic-linux-commands-for-beginners" rel="noopener noreferrer"&gt;Basic Linux Commands&lt;/a&gt;&lt;/p&gt;

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