<?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: Felice Forby</title>
    <description>The latest articles on Forem by Felice Forby (@morinoko).</description>
    <link>https://forem.com/morinoko</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%2F54419%2Fe90e11bf-b8f8-41c4-8425-5e7201138f19.jpg</url>
      <title>Forem: Felice Forby</title>
      <link>https://forem.com/morinoko</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/morinoko"/>
    <language>en</language>
    <item>
      <title>Database Video Notes</title>
      <dc:creator>Felice Forby</dc:creator>
      <pubDate>Fri, 25 Oct 2024 12:11:14 +0000</pubDate>
      <link>https://forem.com/morinoko/database-video-notes-55nb</link>
      <guid>https://forem.com/morinoko/database-video-notes-55nb</guid>
      <description>&lt;h2&gt;
  
  
  SQL Basics (M04 L01)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=02Ij-oqNr5s" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=02Ij-oqNr5s&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://drive.google.com/file/d/15rd4SP0DIqsSxvOlKCKZhiEw1yIoGcv5/view?usp=drive_link" rel="noopener noreferrer"&gt;https://drive.google.com/file/d/15rd4SP0DIqsSxvOlKCKZhiEw1yIoGcv5/view?usp=drive_link&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Basic SELECT (M04 L02)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=Xwqk5fvC8M0" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=Xwqk5fvC8M0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://drive.google.com/file/d/1zjdwegcW4CVJ_efdt4R5qaFs0z2tAobg/view?usp=drive_link" rel="noopener noreferrer"&gt;https://drive.google.com/file/d/1zjdwegcW4CVJ_efdt4R5qaFs0z2tAobg/view?usp=drive_link&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  DATES, Order By, NULLS (M04 L03)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=cjwvKBZSPYw" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=cjwvKBZSPYw&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://drive.google.com/file/d/1o8e7-Z18RJYHHRU0eDQxIeQNXoR3dG_J/view?usp=drive_link" rel="noopener noreferrer"&gt;https://drive.google.com/file/d/1o8e7-Z18RJYHHRU0eDQxIeQNXoR3dG_J/view?usp=drive_link&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SQL statements can be divided into 2 categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data definition language (DDL) statements: used for creating tables, relationships, and other structures.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Data manipulation language (DML) statements: used for queries, inserting, and data modification.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SQL is not procedural: it does not execute one statement at a time in a sequence, rather, it executes the entire query all at once.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All inputs to a SQL query are tables and the output from a query is another table called the Answer Set.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Some queries can produce interim/temporary answer sets. Note that these aren't seen but they consume resources&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Optimizer calculates the optimal execution plan for a query.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Combine conditions with AND and OR, use parentheses when needed&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Group Functions (M04 L04)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=v-ZUPvNAwuk" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=v-ZUPvNAwuk&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://drive.google.com/file/d/18QiIO69xnHsYOgkXutHZFxQtIeRBQTlf/view?usp=drive_link" rel="noopener noreferrer"&gt;https://drive.google.com/file/d/18QiIO69xnHsYOgkXutHZFxQtIeRBQTlf/view?usp=drive_link&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When you combine a GROUP function w/ a WHERE clause, the WHERE clause reduces the number of rows in the interim answer set before the GROUP function does its calculation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A GROUP function w/o a GROUP BY returns only one row in the answer set&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A GROUP function w/ a GROUP BY returns multiple summary rows in the answer set showing a subtotal across all rows from the interim answer set summed by the column on which we GROUP BY&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;RULE: When using a GROUP BY, every column in the SELECT statement must either be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a column to which you apply the group function (note this column does not have to be in the group by)&lt;/li&gt;
&lt;li&gt;a column that you are grouping by&lt;/li&gt;
&lt;li&gt;(Strict mode will fail with errors)
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="o"&gt;@@&lt;/span&gt;&lt;span class="n"&gt;sql_mode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- strict mode&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;sql_mode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ONLY_FULL_GROUP_BY'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- relaxed mode&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;sql_mode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;HAVING&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Like a WHERE clause against the interim answer set when you use a GROUP BY&lt;/li&gt;
&lt;li&gt;Returns a subset of rows from the interim answer set &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;5 group functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SUM (only numeric)&lt;/li&gt;
&lt;li&gt;AVG (only numeric)&lt;/li&gt;
&lt;li&gt;COUNT (any column, or * to count rows)&lt;/li&gt;
&lt;li&gt;MIN (work with any type of column)&lt;/li&gt;
&lt;li&gt;MAX (work with any type of column)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  SQL Subqueries (M05 L01)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=upn-DCyeQuo" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=upn-DCyeQuo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://drive.google.com/file/d/1qDgKW1L0fs7vczArPexPkFpZKatxYueI/view?usp=drive_link" rel="noopener noreferrer"&gt;https://drive.google.com/file/d/1qDgKW1L0fs7vczArPexPkFpZKatxYueI/view?usp=drive_link&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Query within a query:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Subquery in WHERE: answer set to the inner query is used as a predicate in a WHERE clause in the outer query

&lt;ul&gt;
&lt;li&gt;Can also be used to get list for IN clause&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Subquery in SELECT: answer set to the inner query is used as column in a SELECT

&lt;ul&gt;
&lt;li&gt;Need to name the subquery column&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Subquery in FROM: answer set to the inner query is used as "virtual" table in a FROM clause&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Need to name the subquery alias name&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Subquery must always be enclosed in parentheses!&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Can select from a different table&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Co-Related SubQuery&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inner query references a value from outer query&lt;/li&gt;
&lt;li&gt;Inner query is re-executed w/ each row returned by outer query&lt;/li&gt;
&lt;li&gt;Rare, can be very slow performance!
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  SQL JOINs (M05 L02)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=rEqK2_RoHb8" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=rEqK2_RoHb8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://drive.google.com/file/d/1HxuR4ieks1m_yjr1c0Ux0W-feM6aUWat/view?usp=drive_link" rel="noopener noreferrer"&gt;https://drive.google.com/file/d/1HxuR4ieks1m_yjr1c0Ux0W-feM6aUWat/view?usp=drive_link&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Used for getting data from multiple tables.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Joining two tables requires that they have a common key (usually FK relationship) that appears in both tables. Keys must be same length and data type, but don't need to have the same name.&lt;/li&gt;
&lt;li&gt;Joins consume extra resources&lt;/li&gt;
&lt;li&gt;Need to prefix identical column names with the table name
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OrderID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="s1"&gt;'Orders'&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Employees&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Orders&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;Employees&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EmployeeId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EmployeeID&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FirstName&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OrderID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Cartesian Product (M05 L03)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=vXOLWJuG2-0" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=vXOLWJuG2-0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://drive.google.com/file/d/14pDedK8XgdVNQq6XeH2dG70oteuVjBm3/view?usp=drive_link" rel="noopener noreferrer"&gt;https://drive.google.com/file/d/14pDedK8XgdVNQq6XeH2dG70oteuVjBm3/view?usp=drive_link&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Product = one table multiplied by another table&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JOIN often creates a product, then selects rows from the product where keys match (most rows are meaning less)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NEED TO AVOID by fully qualifying the JOIN with a WHERE, e.g. matching all the joined IDs in the where. Can happen if a join clause is missing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For every X tables you are joining, you must have X - 1 JOIN conditions, If not you may generate a meaningless answer set due to creation of a Cartesian product.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  More SQL JOINs (M05 L04)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=U5ut9oJXIbU" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=U5ut9oJXIbU&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://drive.google.com/file/d/1Hp9YL_DLo8vZaaxuD66TQmX97RGGVzdt/view?usp=drive_link" rel="noopener noreferrer"&gt;https://drive.google.com/file/d/1Hp9YL_DLo8vZaaxuD66TQmX97RGGVzdt/view?usp=drive_link&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using the JOIN keyword as an alternate. The below are equivalent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OrderID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="s1"&gt;'Orders'&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Employees&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Orders&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;Employees&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EmployeeID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EmployeeID&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FirstName&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OrderID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OrderID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="s1"&gt;'Orders'&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Employees&lt;/span&gt; 
&lt;span class="k"&gt;INNER&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;Orders&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;Employees&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EmployeeID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EmployeeID&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FirstName&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OrderID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Every pair of tables being joined must have a common key&lt;/li&gt;
&lt;li&gt;Every pair of common keys must have a condition stated in a WHERE clause or in the ON clause of the JOIN (if not could get Cartesian product)&lt;/li&gt;
&lt;li&gt;Note that joins are expensive! If joining multiple tables, it could be better to do multiple queries and have the output of a join query saved as a temporary table, then bring that temp table into the next join query.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Joining multiple tables&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UnitPrice&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Quantity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="s1"&gt;'OrderValue'&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Employees&lt;/span&gt; 
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;Orders&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;Employees&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EmployeeID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EmployeeID&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;OrderDetails&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;Orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OrderID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;OrderDetails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OrderID&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- With WHERE&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;Employees&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EmployeeID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EmployeeID&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;Orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OrderID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;OrderDetails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OrderID&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;By default, a JOIN is an INNER JOIN&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explicit JOIN&lt;/strong&gt;: when the JOIN keyword is used&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implicit JOIN&lt;/strong&gt;: when WHERE is used to define the join&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  SQL Outer Join (M05 L05)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=fLaLIZpdsM8" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=fLaLIZpdsM8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://drive.google.com/file/d/1l_sTJIBjoRPKa3z4jc9mSbkFN_-D6YgK/view?usp=drive_link" rel="noopener noreferrer"&gt;https://drive.google.com/file/d/1l_sTJIBjoRPKa3z4jc9mSbkFN_-D6YgK/view?usp=drive_link&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;INNER JOIN: the intersection between 2 tables. Returns all the rows that match between the tables&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;RIGHT OUTER JOIN: All of the rows where the keys match between both tables PLUS all the rows from the "right" table. All the rows of the right table and matching rows from left table&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;LEFT OUTER JOIN: All of the rows where the keys match between both tables PLUS all the rows from the "left" table. All the rows of the left table and matching rows from right table&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F2cepjkh9vlw2ajikmuzk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F2cepjkh9vlw2ajikmuzk.png" alt="Image description" width="800" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Outer JOIN is useful for analyzing data&lt;/p&gt;

&lt;h3&gt;
  
  
  Left outer join
&lt;/h3&gt;

&lt;p&gt;Left table is the one mentioned first in the SELECT FROM. Below, Employees is left and Department is right. All rows from Employees (left) and only matching rows from Department (right) are shown.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Employees&lt;/span&gt; &lt;span class="n"&gt;E&lt;/span&gt;
&lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;OUTER&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;Department&lt;/span&gt; &lt;span class="n"&gt;D&lt;/span&gt;
&lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DepartmentID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;D&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DepartmentID&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Right outer join
&lt;/h3&gt;

&lt;p&gt;All rows from Department (right) and only matching rows from Employees (left)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Employees&lt;/span&gt; &lt;span class="n"&gt;E&lt;/span&gt;
&lt;span class="k"&gt;RIGHT&lt;/span&gt; &lt;span class="k"&gt;OUTER&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;Department&lt;/span&gt; &lt;span class="n"&gt;D&lt;/span&gt;
&lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DepartmentID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;D&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DepartmentID&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Note on UNION
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Assemble multiple queries connected by a UNION&lt;/li&gt;
&lt;li&gt;Combine multiple answer sets&lt;/li&gt;
&lt;li&gt;Each answer set must have same # of columns&lt;/li&gt;
&lt;li&gt;Each column in all answer sets must have same domain (same set of data values)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Execution Plans
&lt;/h2&gt;

&lt;p&gt;With any join, the DB engine optimizer must calculate the most efficient query execution plan. There are 3 basic methods in MySQL:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nested Loop Join: when one join input table has a small number of rows and the other input table is large and indexed on the join key. Most efficient.&lt;/li&gt;
&lt;li&gt;Merge Join: when tables being joined are both sorted on the join key. Next efficient.&lt;/li&gt;
&lt;li&gt;Hash Join: when large, unsorted, non-indexed inputs are joined with an inner join with an "=" condition. Least efficient -&amp;gt; creates a product&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Explain Plan option will show you an analysis of the execution plan calculation by the query optimizer&lt;/p&gt;

&lt;h2&gt;
  
  
  SQL DDL - CREATE (M06 L01)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=aAzsSODmuIU" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=aAzsSODmuIU&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://drive.google.com/file/d/1bHfqs6eyTZAwWltShCjI92o1bGtIdnT2/view?usp=drive_link" rel="noopener noreferrer"&gt;https://drive.google.com/file/d/1bHfqs6eyTZAwWltShCjI92o1bGtIdnT2/view?usp=drive_link&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Data Definition Language: Statements that CREATE and MODIFY database structures (tables, etc.)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create, Alter, Drop&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Create
&lt;/h3&gt;

&lt;p&gt;Creates a new table or view&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;defines table name and its columns&lt;/li&gt;
&lt;li&gt;defines data type, length for each column&lt;/li&gt;
&lt;li&gt;defines constraints for each column&lt;/li&gt;
&lt;li&gt;Usually drop table (if it exists) before creating
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;table_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;column_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;DATATYPE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;L&lt;/span&gt;&lt;span class="p"&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;column_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;DATATYPE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;L&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;column_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;DATATYPE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;L&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;constraint_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;TYPE&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;shippers&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;ShipperID&lt;/span&gt;   &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;CompanyName&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;Phone&lt;/span&gt;       &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="s1"&gt;'0'&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;NOT NULL&lt;/strong&gt;: Prevent inserting a row when the column has no value, can provide a default value.&lt;/p&gt;

&lt;h3&gt;
  
  
  DROP
&lt;/h3&gt;

&lt;p&gt;Drops named DB table&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;table_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;DATA TYPES available depend on the DB engine (MySQL, Oracle, Posgres, etc.)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CHAR: fixed width string, shorter strings get padded&lt;/li&gt;
&lt;li&gt;VARCHAR: variable width string, longer strings get truncated, shorter strings does NOT store blanks&lt;/li&gt;
&lt;li&gt;FLOAT: floating-point data type that stores approx. values for real numbers&lt;/li&gt;
&lt;li&gt;DECIMAL: fixed-precision data type that stores exact values, often for dollar cents. DECIMAL(9, 2) means 9 total digits with 2 digits to the right of the decimal point.&lt;/li&gt;
&lt;li&gt;INT: number w/o decimal places (also TINYINT, SMALLINT, etc)&lt;/li&gt;
&lt;li&gt;BLOB: binary large object (binary image, etc)&lt;/li&gt;
&lt;li&gt;DATE: Just year, month, day&lt;/li&gt;
&lt;li&gt;DATETIME: Year, month, day, with time&lt;/li&gt;
&lt;li&gt;TIMESTAMP&lt;/li&gt;
&lt;li&gt;ENUM: like a small array&lt;/li&gt;
&lt;li&gt;BOOLEAN: actually tinyint(1)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  SQL DDL - ALTER (M06 L02)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=8coYgskYJeo" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=8coYgskYJeo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://drive.google.com/file/d/12um9jq4W2WvLc46mLSlHD8l5uxIyXkkc/view?usp=drive_link" rel="noopener noreferrer"&gt;https://drive.google.com/file/d/12um9jq4W2WvLc46mLSlHD8l5uxIyXkkc/view?usp=drive_link&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ALTER allows you to change different characteristics of database structures like tables, columns, and views&lt;/p&gt;

&lt;p&gt;Alter a table:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ADD or DROP columns&lt;/li&gt;
&lt;li&gt;ADD or DROP constraints&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Alter a column:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SET or DROP a default&lt;/li&gt;
&lt;li&gt;SET a DATA_TYPE
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Change table name&lt;/span&gt;
&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="k"&gt;RENAME&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Change name of column&lt;/span&gt;
&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt;
&lt;span class="k"&gt;RENAME&lt;/span&gt; &lt;span class="k"&gt;COLUMN&lt;/span&gt; &lt;span class="n"&gt;itemCode&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="n"&gt;itemRef&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Add column&lt;/span&gt;
&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt;
&lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;COLUMN&lt;/span&gt; &lt;span class="n"&gt;scanCode&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Change column data type&lt;/span&gt;
&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt;
&lt;span class="k"&gt;MODIFY&lt;/span&gt; &lt;span class="k"&gt;COLUMN&lt;/span&gt; &lt;span class="n"&gt;itemCode&lt;/span&gt; &lt;span class="nb"&gt;CHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Drop column&lt;/span&gt;
&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt;
&lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;COLUMN&lt;/span&gt; &lt;span class="n"&gt;itemCode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  DML - Insert, Update, Delete (M06 L03)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=6-VRucq0yvk" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=6-VRucq0yvk&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://drive.google.com/file/d/1QUArLzfLvQhA-lSzA1_tgjkGBYtpJVUg/view?usp=drive_link" rel="noopener noreferrer"&gt;https://drive.google.com/file/d/1QUArLzfLvQhA-lSzA1_tgjkGBYtpJVUg/view?usp=drive_link&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Data Manipulation Language - Populates and modify the data&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Insert, Update, Delete&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Insert
&lt;/h3&gt;

&lt;p&gt;Two formats:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- if no column &amp;amp; value are specified, NULL or default is assigned)&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;table_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;column&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;column&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;column&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- must have a value or NULL for every column in table&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;table_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Update
&lt;/h3&gt;

&lt;p&gt;UPDATE statement assigns new values to specific columns based on a condition&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;table_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;column&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;new_value&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If no condition is given, it updates all rows! (check if this is correct)&lt;/p&gt;

&lt;p&gt;Example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;Employees&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;"timmy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;"Mr."&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;employeeID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TRUNCATE
&lt;/h3&gt;

&lt;p&gt;TRUNCATE statement removes all rows, but keeps structure of table&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;TRUNCATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;table_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  DROP
&lt;/h3&gt;

&lt;p&gt;DROP statement removes all rows and the table structure (completely removes table)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;table_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  DELETE
&lt;/h3&gt;

&lt;p&gt;Removes rows in a table based on WHERE clause&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;table_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Employees&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;employeeID&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;NOTE: a DELETE without a WHERE is the same as TRUNCATE!&lt;/p&gt;

&lt;h2&gt;
  
  
  SQL Constraints (M07 L01)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=N8qQzSvA9TM" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=N8qQzSvA9TM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://drive.google.com/file/d/1KVHoXCUgxAZkolJrFdH3AdJP0774WCdN/view?usp=drive_link" rel="noopener noreferrer"&gt;https://drive.google.com/file/d/1KVHoXCUgxAZkolJrFdH3AdJP0774WCdN/view?usp=drive_link&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Constraints can be defined within the CREATE TABLE statement&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can be added to able after creation with ALTER TABLE statement&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Five types of constraints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PRIMARY KEY&lt;/li&gt;
&lt;li&gt;NULL/NOT NULL&lt;/li&gt;
&lt;li&gt;UNIQUE&lt;/li&gt;
&lt;li&gt;CHECK&lt;/li&gt;
&lt;li&gt;FOREIGN KEY&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Primary key constraint
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;can be defined at column level if one column

&lt;ul&gt;
&lt;li&gt;comes with unique constraint, not null constraint&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Must be defined at table level if more than one column
&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;persons&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;LastName&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;FirstName&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;persons&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;LastName&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;FirstName&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="n"&gt;Phone&lt;/span&gt; &lt;span class="nb"&gt;CHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Phone&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To make a constraint modifiable (via ALTER), you must give it a name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;persons&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;LastName&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;FirstName&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="n"&gt;Phone&lt;/span&gt; &lt;span class="nb"&gt;CHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;PK_Person&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;Persons&lt;/span&gt; &lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;PK_Person&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;Persons&lt;/span&gt; 
&lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;PK_Person&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;most shops always name constaints and have standards for naming them.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  UNIQUE
&lt;/h3&gt;

&lt;p&gt;May be defined at column level if one column&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;persons&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;LastName&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;FirstName&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;Email&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;persons&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;LastName&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;FirstName&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="n"&gt;Phone&lt;/span&gt; &lt;span class="nb"&gt;CHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;UNIQUE&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;-- or with name&lt;/span&gt;
  &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;UN_Name&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  CHECK
&lt;/h3&gt;

&lt;p&gt;Applies a condition to a column. Rules for conditions same as WHERE clause&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;persons&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;LastName&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;FirstName&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="n"&gt;Age&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;CK_Age&lt;/span&gt; &lt;span class="k"&gt;CHECK&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Will only insert if age is &amp;gt; 18 &lt;/p&gt;

&lt;h3&gt;
  
  
  FOREIGN KEY
&lt;/h3&gt;

&lt;p&gt;Defined at column level&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;persons&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;LastName&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;FirstName&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="n"&gt;DepartmentNumber&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;FOREIGN&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;
     &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;Department&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DeptID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;Age&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Table level: allows you to give name&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;persons&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;LastName&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;FirstName&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="n"&gt;DepartmentNumber&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;Age&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;FK_Department&lt;/span&gt; &lt;span class="k"&gt;FOREIGN&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DepartmentNumber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;Department&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DeptID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Can add later with an Alter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;Persons&lt;/span&gt;
&lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;FK_Department&lt;/span&gt;
&lt;span class="k"&gt;FOREIGN&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Department&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;Department&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DeptID&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Foreign key constraints used to maintain Referential Integrity (RI). There are rules that can be set on Parent tables for when an update or delete is done, for what to do with the child row:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SET NULL: sets child value NULL&lt;/li&gt;
&lt;li&gt;SET DEFAULT: sets child value to column default&lt;/li&gt;
&lt;li&gt;CASCADE:  deletes or updates the child (if parent is deleted, deletes child, or if parent id is updated it will update child ref id)&lt;/li&gt;
&lt;li&gt;NO ACTION/RESTRICT: prevents action on table
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;persons&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;LastName&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;FirstName&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="n"&gt;DepartmentNumber&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;Age&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;FK_Department&lt;/span&gt; &lt;span class="k"&gt;FOREIGN&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DepartmentNumber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;Department&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DeptID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
     &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="k"&gt;CASCADE&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depending on the data model and the optionality, the foreign key can be NULL.&lt;/p&gt;

&lt;h2&gt;
  
  
  SQL Triggers (MO7 L02)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=MFDZlmc0dZw" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=MFDZlmc0dZw&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://drive.google.com/file/d/1dcwXv47urxvKHBp2nHLmzvSMB502TCBK/view?usp=drive_link" rel="noopener noreferrer"&gt;https://drive.google.com/file/d/1dcwXv47urxvKHBp2nHLmzvSMB502TCBK/view?usp=drive_link&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Triggers are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a pieces of SQL code stored with a table&lt;/li&gt;
&lt;li&gt;associated with a table&lt;/li&gt;
&lt;li&gt;associated with an event&lt;/li&gt;
&lt;li&gt;the code fires when the event happens&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why use triggers&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;enforce business rules&lt;/li&gt;
&lt;li&gt;moves code from an application program to the DB&lt;/li&gt;
&lt;li&gt;Performance improvement - all work done on server&lt;/li&gt;
&lt;li&gt;convenient for DB people to store these rules in the DB and not the application, helps to enforce business rules. Advantagious from the DB perspective to store code related to the DB or effects the DB in the database itself instead of the app.&lt;/li&gt;
&lt;li&gt;Gives DB more control over DB&lt;/li&gt;
&lt;li&gt;Note: trigger is stored with the table, so when table is dropped trigger is dropped&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Trigger events:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Insert, update, delete&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Trigger timer&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Before, after, instead of&lt;/li&gt;
&lt;li&gt;Depends on the DB on what is available&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of: E.g. Instead of doing an insert, fire the trigger&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TRIGGER&lt;/span&gt; &lt;span class="k"&gt;trigger_name&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;BEFORE&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="k"&gt;AFTER&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;DELETE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;table_name&lt;/span&gt; &lt;span class="n"&gt;trigger_type&lt;/span&gt;
&lt;span class="k"&gt;BEGIN&lt;/span&gt;
  &lt;span class="c1"&gt;-- trigger_logic&lt;/span&gt;
&lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;First, specify the name of the trigger after the CREATE TRIGGER clause.&lt;/li&gt;
&lt;li&gt;Next, use either BEFORE or AFTER keyword to determine when to the trigger should occur in response to a specific event e.g., INSERT, UPDATE, or DELETE.&lt;/li&gt;
&lt;li&gt;Then, specify the name of the table to which the trigger binds.&lt;/li&gt;
&lt;li&gt;After, specify the type of trigger using either FOR EACH ROW or FOR EACH STATEMENT. We will discuss more on this in the next section.&lt;/li&gt;
&lt;li&gt;Finally, put the logic of the trigger in the BEGIN ... END block.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Row level trigger vs. statement level trigger
&lt;/h4&gt;

&lt;p&gt;There are two types of triggers: row and statement level triggers.&lt;/p&gt;

&lt;p&gt;A row level trigger executes each time a row is affected by an UPDATE statement. If the UPDATE statement affects 10 rows, the row level trigger would execute 10 times, each time per row. If the UPDATE statement does not affect any row, the row level trigger is not executed at all.&lt;/p&gt;

&lt;p&gt;Different from the row level trigger, a statement level trigger is called once regardless of how many rows affect by the UPDATE statement. Note that if the UPDATE statement did not affect any rows, the trigger will still be executed.&lt;/p&gt;

&lt;p&gt;When creating a trigger, you can specify whether a trigger is row or statement level by using the FOR EACH ROW or FOR EACH STATEMENTrespectively.&lt;/p&gt;

&lt;h4&gt;
  
  
  Special features
&lt;/h4&gt;

&lt;p&gt;When trigger is fired, DBMS supplies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OLD and NEW values for the update&lt;/li&gt;
&lt;li&gt;NEW values for inserts&lt;/li&gt;
&lt;li&gt;OLD values for deletes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can reference OLD and/or NEW value of a column within the code of the trigger&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Archival data before a delete&lt;/li&gt;
&lt;li&gt;E.g. move data to an archival orders table
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Gets fired when an Orders record is deleted&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TRIGGER&lt;/span&gt; &lt;span class="n"&gt;before_order_delete&lt;/span&gt;
  &lt;span class="k"&gt;BEFORE&lt;/span&gt; &lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;Orders&lt;/span&gt;
  &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="k"&gt;EACH&lt;/span&gt; &lt;span class="k"&gt;ROW&lt;/span&gt;
&lt;span class="k"&gt;BEGIN&lt;/span&gt;
  &lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;OrdersArchive&lt;/span&gt;
  &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;OrderID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;OLD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OrderID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;CustomerID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;OLD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CustomerID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;EmployeeID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;OLD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EmployeeID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;OrderDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;OLD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OrderDate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;ArchiveDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example from Lab:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TRIGGER&lt;/span&gt; &lt;span class="n"&gt;update_student_gpa&lt;/span&gt;
&lt;span class="k"&gt;AFTER&lt;/span&gt; &lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;ClassGrade&lt;/span&gt;
&lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="k"&gt;EACH&lt;/span&gt; &lt;span class="k"&gt;ROW&lt;/span&gt;
&lt;span class="k"&gt;BEGIN&lt;/span&gt;
  &lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;Student&lt;/span&gt;
  &lt;span class="c1"&gt;-- Use subquery to calculate the new GPA and then use result to set the student's gpa column.&lt;/span&gt;
  &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;gpa&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;Class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;units&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ClassGrade&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;grade&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;units&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
             &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;ClassGrade&lt;/span&gt;
             &lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="k"&gt;Class&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;ClassGrade&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;Class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cID&lt;/span&gt;
             &lt;span class="c1"&gt;-- New.sID is the student ID from the newly inserted ClassGrade&lt;/span&gt;
             &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;ClassGrade&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;NEW&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;-- Make sure to update the student referenced in the newly inserted ClassGrade&lt;/span&gt;
  &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;Student&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;NEW&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sID&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  SQL Case and View (MO7 L03)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=kVzharmPioU" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=kVzharmPioU&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://drive.google.com/file/d/1y99V4RYwjxTUdxWTN3A_vKJ9Ku5L-hgn/view?usp=drive_link" rel="noopener noreferrer"&gt;https://drive.google.com/file/d/1y99V4RYwjxTUdxWTN3A_vKJ9Ku5L-hgn/view?usp=drive_link&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  CASE
&lt;/h3&gt;

&lt;p&gt;CASE expression allows SQL to process conditionals like IF/THEN/ELSE in other programming languages (there is no if/then/else in SQL)&lt;/p&gt;

&lt;p&gt;The CASE is an expression that can be used anywhere in teh SQL where an expression is allowed&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CASE&lt;/span&gt;
  &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;condition_1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;result_1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;condition_2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;result_2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;condition_3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;result_3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;else_result&lt;/span&gt;&lt;span class="o"&gt;&amp;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;If a WHEN condition is true, the WHEN ends with that result&lt;/li&gt;
&lt;li&gt;If the WHEN condition is false, control passes to next WHEN&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- adds "category" to answer set&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;productID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;productName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unitPrice&lt;/span&gt;
&lt;span class="k"&gt;CASE&lt;/span&gt;
  &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;unitPrice&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="nv"&gt;"Economy"&lt;/span&gt;
  &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;unitPrice&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="nv"&gt;"Standard"&lt;/span&gt;
  &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="nv"&gt;"Premium"&lt;/span&gt;
&lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Products&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Views
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;VIEW is an empty shell of a table definition&lt;/li&gt;
&lt;li&gt;The view contains no data until it's queried&lt;/li&gt;
&lt;li&gt;Kind of like a "Virtual Table"&lt;/li&gt;
&lt;li&gt;Each time view is queried, the underlying query that populates the view is re-executed&lt;/li&gt;
&lt;li&gt;Data in the view table does not persist&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why use views?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Security, maintaining confidentiality

&lt;ul&gt;
&lt;li&gt;View can prevent unauthorized users from seeing data that must be kept secure or confidential&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Complexity

&lt;ul&gt;
&lt;li&gt;The view can hide complex SQL from unauthorized or inexperienced users&lt;/li&gt;
&lt;li&gt;Can instruct people to use views
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Hiding salary from an employees table&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;VIEW&lt;/span&gt; &lt;span class="n"&gt;EmployeeSecure&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt;
  &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;EmployeeID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HireDate&lt;/span&gt;
  &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Employees&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Using a view&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;Employees&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;VIEW&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;view_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;view_query&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Auto-increment and UNION (MO7 L04)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=pRrDLYZCgio" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=pRrDLYZCgio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://drive.google.com/file/d/12yb8YpAN5hkR0WR75Mtm6CKGyZL91QxX/view?usp=drive_link" rel="noopener noreferrer"&gt;https://drive.google.com/file/d/12yb8YpAN5hkR0WR75Mtm6CKGyZL91QxX/view?usp=drive_link&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Auto-increment
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Can assign the AUTO_INCREMENT "constraint" to a column when creating a table&lt;/li&gt;
&lt;li&gt;Auto increment typically is used as surrogate key when no other keys are available&lt;/li&gt;
&lt;li&gt;Auto-increment columns are ints that automatically increment by 1 when a new row is inserted&lt;/li&gt;
&lt;li&gt;Created and managed by DB&lt;/li&gt;
&lt;li&gt;Guarantees a unique key value for each new row
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;Shoppers&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;ShopperID&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="n"&gt;AUTO_INCREMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;ShopperName&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Auto-increment keys are not reused when a row is deleted and a new one is inserted. It goes up from the last used key&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  UNION
&lt;/h3&gt;

&lt;p&gt;SQL UNION operator allows SQL to combine multiple answer sets into a single answer set.&lt;/p&gt;

&lt;p&gt;When combining multiple answer sets into one, you must be sure that both sets contain the same number of columns and that the columns in the sets have the same data types.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- First query&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;categoryName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unitsInStock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"Total units"&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Categories&lt;/span&gt; &lt;span class="k"&gt;C&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;Products&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;categoryID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;categoryID&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;categoryName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Second query&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="nv"&gt;"Total"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unitsInStock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"Total units"&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Products&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Unioned query&lt;/span&gt;
&lt;span class="c1"&gt;-- Both have same number columns and they are the same datatype&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;categoryName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unitsInStock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"Total units"&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Categories&lt;/span&gt; &lt;span class="k"&gt;C&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;Products&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;categoryID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;categoryID&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;categoryName&lt;/span&gt;
&lt;span class="k"&gt;UNION&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="nv"&gt;"Total"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unitsInStock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"Total units"&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Products&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Understanding Rails Polymorphic Associations: A Case Study</title>
      <dc:creator>Felice Forby</dc:creator>
      <pubDate>Tue, 16 Jul 2024 13:21:04 +0000</pubDate>
      <link>https://forem.com/morinoko/understanding-polymorphic-associations-in-rails-through-a-case-study-17je</link>
      <guid>https://forem.com/morinoko/understanding-polymorphic-associations-in-rails-through-a-case-study-17je</guid>
      <description>&lt;p&gt;I recently got to implement a polymorphic table in Rails at work. I've read about polymorphism a few times in books or blogs, but I never quite understood it. Having a real-life situation to apply the concept to at work, along with some conversations with my team's lead engineer finally made it click!&lt;/p&gt;

&lt;p&gt;A lot of the examples in other articles and in even in the documentation are somewhat contrived, so I'd like to share what I did on the job as a real-world mini case study in hopes that this helps someone else. &lt;/p&gt;

&lt;h2&gt;
  
  
  The situation
&lt;/h2&gt;

&lt;p&gt;My company provides employee benefits (e.g. dental and vision insurance) for other companies and we have many types of users that can interact with our platform such as company HR admins, brokers who sell insurance, and the members who have insurance. Naturally, we need to send a lot of emails to these people. The goal of my work project was to consolidate the different email categories we have and better keep track of the recipients for emails that we send out. For example, we have emails related to invoicing and insurance renewals, and they are sent to different people depending on their role within the system.&lt;/p&gt;

&lt;p&gt;In regards to modeling, I needed to model a table that represented recipients of a set of emails under a certain category, where one category like "Invoicing" could contain several different specific emails. I named the model &lt;code&gt;EmailCategoryRecipient&lt;/code&gt;, and each "recipient" could be associated with different kinds of user profiles we have in the system: a &lt;code&gt;CompanyContact&lt;/code&gt; (e.g. an HR person at a company) and a &lt;code&gt;BrokerProfile&lt;/code&gt; (e.g. the broker who sold the insurance to the company). An &lt;code&gt;EmailCategoryRecipient&lt;/code&gt; belongs to a profile, where the profiles could be different classes.&lt;/p&gt;

&lt;p&gt;Considering the model relationships, it sounded exactly like the kind of situation a model with a polymorphic association could help with!&lt;/p&gt;

&lt;h2&gt;
  
  
  The polymorphic association and database table
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Creating the polymorphic association
&lt;/h3&gt;

&lt;p&gt;A polymorphic association lets you create a model that can belong to more than one class, but uses only one &lt;code&gt;belongs_to&lt;/code&gt; association instead of multiple. This multifaceted association is usually represented by the name of the concept + the &lt;code&gt;-able&lt;/code&gt; prefix. In my case, the associations were different kinds of profiles so I called it &lt;code&gt;profileable&lt;/code&gt;, but you can name these associations anything you want.&lt;/p&gt;

&lt;p&gt;Here's what it would look like to set up the polymorphic relationship in the models I mentioned above:&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;EmailCategoryRecipient&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:profileable&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;span class="k"&gt;end&lt;/span&gt; 

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CompanyContact&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:email_category_recipients&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;as: :profileable&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;BrokerProfile&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:email_category_recipients&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;as: :profileable&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, even though &lt;code&gt;EmailCategoryRecipient&lt;/code&gt; only has one &lt;code&gt;belongs_to&lt;/code&gt; for &lt;code&gt;profileable&lt;/code&gt;, it can represent different types of classes—a &lt;code&gt;CompanyContact&lt;/code&gt; or  a &lt;code&gt;BrokerProfile&lt;/code&gt;. This is possible because I used the &lt;code&gt;polymorphic: true&lt;/code&gt; option on the &lt;code&gt;belongs_to&lt;/code&gt; association. As you can imagine, there could be many other things that need to have email recipients associated to them as well, like a &lt;code&gt;Member&lt;/code&gt; or an &lt;code&gt;Admin&lt;/code&gt; profile. Any number of these associations could be captured in the polymorphic &lt;code&gt;profileable&lt;/code&gt; attribute.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a migration to set up the polymorphic association
&lt;/h3&gt;

&lt;p&gt;To make the above relationships work, you need to create a migration that sets up a table that can handle the polymorphic associations. Rails gives us handy shortcuts to do so. It would look something like this:&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;CreateEmailCategoryRecipients&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Migration&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;7.1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;change&lt;/span&gt;
    &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="ss"&gt;:email_category_recipients&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="ss"&gt;:category_name&lt;/span&gt; &lt;span class="c1"&gt;# just to keep track of category, this has nothing to do with the polymorphic piece&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;references&lt;/span&gt; &lt;span class="ss"&gt;:profileable&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;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timestamps&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even though it's only one line, the &lt;code&gt;t.references :profileable, polymorphic: true&lt;/code&gt; will actually create two columns and an index. The columns created are an &lt;code&gt;*_id&lt;/code&gt; column and &lt;code&gt;*_type&lt;/code&gt; column which are based on the polymorphic name. (in this case &lt;code&gt;profileable&lt;/code&gt;). This one-liner is a nice shortcut method, but you could also write the migration explicitly like below. It would be equivalent to the migration above:&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;CreateEmailCategoryRecipients&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Migration&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;7.1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;change&lt;/span&gt;
    &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="ss"&gt;:email_category_recipients&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;  &lt;span class="ss"&gt;:category_name&lt;/span&gt; &lt;span class="c1"&gt;# again, this is just an additional attribute not related to polymorphic columns&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="ss"&gt;:profileable_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="ss"&gt;:profileable_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;timestamps&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;add_index&lt;/span&gt; &lt;span class="ss"&gt;:email_category_recipients&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:profileable_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:profileable_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let me explain the two columns &lt;code&gt;profileable_id&lt;/code&gt; and &lt;code&gt;profileable_type&lt;/code&gt;. The &lt;code&gt;profileable_id&lt;/code&gt; holds the &lt;code&gt;id&lt;/code&gt; (primary key) of the associated object while the &lt;code&gt;profileable_type&lt;/code&gt; keeps track of what kind of object it is, which is the stringified class name of that object (&lt;code&gt;"CompanyContact"&lt;/code&gt; or &lt;code&gt;"BrokerProfile"&lt;/code&gt; in this case). We need the &lt;code&gt;*_type&lt;/code&gt; column in addition to the &lt;code&gt;*_id&lt;/code&gt; column because Rails needs to know what database table to look in to fetch the associated record, as the different types are stored in separate database tables. When you assign an object as a &lt;code&gt;profileable&lt;/code&gt;, Rails will take care of filling out these two columns automatically with that object's id and class.&lt;/p&gt;

&lt;h3&gt;
  
  
  Something to think about: Polymorphism is not the only way to do this
&lt;/h3&gt;

&lt;p&gt;While polymorphic relationships are pretty cool and can provide an elegant solution, I want to call out that you don't actually &lt;em&gt;need&lt;/em&gt; to use it every time you have to associate multiple similar classes to a model. In fact, there are a lot of times when it's not the right tool for the job.&lt;/p&gt;

&lt;p&gt;The alternative is to just associate each thing separately with the standard &lt;code&gt;belongs_to&lt;/code&gt; and respective &lt;code&gt;*_id&lt;/code&gt; column.&lt;/p&gt;

&lt;p&gt;Modeling &lt;code&gt;EmailCategoryRecipient&lt;/code&gt; as a non-polymorphic relationship would look like this:&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;EmailCategoryRecipient&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:company_contact&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:broker_profile&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;CompanyContact&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:email_category_recipients&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;BrokerProfile&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:email_category_recipients&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The migration for the above setup would look like this:&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;CreateEmailCategoryRecipients&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Migration&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;7.1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;change&lt;/span&gt;
    &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="ss"&gt;:email_category_recipients&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="ss"&gt;:category_name&lt;/span&gt;
      &lt;span class="c1"&gt;# t.belongs_to is another shortcut method that will create indices for you too, unless specified not to&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;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:company_contact&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;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:broker_profile&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Or alternatively with out using the shortcut &lt;code&gt;t.belongs_to&lt;/code&gt;:&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;CreateEmailCategoryRecipients&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Migration&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;7.1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;change&lt;/span&gt;
    &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="ss"&gt;:email_category_recipients&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="ss"&gt;:category_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;bigint&lt;/span&gt; &lt;span class="ss"&gt;:company_contact_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;bigint&lt;/span&gt; &lt;span class="ss"&gt;:broker_profile_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;timestamps&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;add_index&lt;/span&gt; &lt;span class="ss"&gt;:email_category_recipients&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:company_contact_id&lt;/span&gt;
    &lt;span class="n"&gt;add_index&lt;/span&gt; &lt;span class="ss"&gt;:email_category_recipients&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:broker_profile_id&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you were to go this route, you would need to assign any &lt;code&gt;BrokerProfile&lt;/code&gt; objects directly to the &lt;code&gt;EmailCategoryRecipient&lt;/code&gt;'s &lt;code&gt;broker_profile&lt;/code&gt; attribute (or the id to the &lt;code&gt;broker_profile_id&lt;/code&gt;) and the same goes for &lt;code&gt;CompanyContact&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  When would you NOT want to use polymorphism
&lt;/h2&gt;

&lt;p&gt;The big benefits of using polymorphic associations are that it helps keep the code clean, simple, and flexible. &lt;/p&gt;

&lt;p&gt;That being said, I think that polymorphism can also make your code more abstract and therefore harder to understand at a glance, especially for people who aren't familiar with how polymorphic tables work or for someone who doesn't yet understand that model's relationship to other models. For example, it's not immediately obvious what classes &lt;code&gt;profileable&lt;/code&gt; should refer to unless you just "know" from the get go. You may need to go searching through the codebase to find what classes can be associated with the polymorphic one.&lt;/p&gt;

&lt;p&gt;Another thing to think about is whether the polymorphic objects you plan to associate with polymorphic type are similar or not. That is, do they share similar interface (attributes and methods) in places where it matters? It depends on the use case, but it may be extra hassle if the different classes aren't similar in their interface. &lt;/p&gt;

&lt;p&gt;For example, if you needed to pull email off of &lt;code&gt;CompanyContact&lt;/code&gt; and &lt;code&gt;BrokerProfile&lt;/code&gt; but one model used the attribute name &lt;code&gt;email&lt;/code&gt; and the other &lt;code&gt;email_address&lt;/code&gt;, you would have to check the class type to figure out what method could be called, alias the method in one class to match the other, or come up with another solution to avoid getting errors if the wrong method gets called on the wrong object. If you need to do this for multiple attributes on these classes, it may defeat the purpose of using a polymorphic association in the first place.&lt;/p&gt;

&lt;p&gt;You could also run into data integrity issues if the "wrong" kind of object gets saved into the polymorphic table or if a non-existent object gets saved into the table. With polymorphic associations, Rails does not check the referential integrity of the record, that is, does it actually exist in the database. Queries will generally be slower as well, since Rails needs to check both the id and the type of the object. &lt;/p&gt;

&lt;h2&gt;
  
  
  The final outcome
&lt;/h2&gt;

&lt;p&gt;To bring this case study to an end, I want to touch on the final decision I made, which was actually &lt;em&gt;not&lt;/em&gt; to use the polymorphic association. I ended up using explicit id columns for each associated object instead. Though I had already migrated the new tables, it was easy to changed because we hadn't started using them yet.&lt;/p&gt;

&lt;p&gt;There are a couple reasons why I went the other direction. The main reason is that I found out we needed to have an additional association with the &lt;code&gt;EmailCategoryRecipient&lt;/code&gt; model that was called &lt;code&gt;PlatformConfig&lt;/code&gt;. The purpose of this model is to store configurations of the insurance partner platforms we work with, including the contact email for that partner. For our company, it represents another kind of recipient, but it is not a type of profile, and therefore it didn't make sense to consider it a &lt;code&gt;profileable&lt;/code&gt; type. It also seemed awkward to have both a polymorphic entity for profiles and a separate non-polymorphic entity for the platforms.&lt;/p&gt;

&lt;p&gt;The second reason is that the &lt;code&gt;CompanyContact&lt;/code&gt; and &lt;code&gt;BrokerProfile&lt;/code&gt; models were originally created at different times for different purposes. &lt;code&gt;CompanyContact&lt;/code&gt; was implemented long before our concept of a user "profile" was even introduced. For our use case, it would have been ideal if we could "trust" that the different &lt;code&gt;profileable&lt;/code&gt; objects have similar interfaces, but that wasn't necessarily the case, so we decided the explicit &lt;code&gt;belongs_to&lt;/code&gt; relationships were more appropriate. &lt;/p&gt;

&lt;p&gt;One of the drawbacks here is that when we need to associate another type of profile to &lt;code&gt;EmailCategoryRecipient&lt;/code&gt; in the future, we will need to change the table in order to add another &lt;code&gt;belongs_to&lt;/code&gt; relationship. On the other hand, having explicit relationships makes it more obvious what kind of object we are dealing with at any given time.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://guides.rubyonrails.org/association_basics.html#polymorphic-associations" rel="noopener noreferrer"&gt;Rails documentation&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>polymorphism</category>
      <category>database</category>
    </item>
    <item>
      <title>Linux Command Line Notes</title>
      <dc:creator>Felice Forby</dc:creator>
      <pubDate>Mon, 15 Jan 2024 14:33:14 +0000</pubDate>
      <link>https://forem.com/morinoko/linux-command-line-notes-4lgm</link>
      <guid>https://forem.com/morinoko/linux-command-line-notes-4lgm</guid>
      <description>&lt;p&gt;Reference for basic command line commands for Linux, because I always forget a lot of these.&lt;/p&gt;

&lt;h2&gt;
  
  
  Show current working directory
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;h2&gt;
  
  
  See username
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Changing directories
&lt;/h2&gt;

&lt;p&gt;Move to root/top directory&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Move to user home directory&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;or just&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Go up one directory level&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Print to screen
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "Hello world!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating directories and file
&lt;/h2&gt;

&lt;p&gt;Create new directory&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Create multiple directories&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir dir1 dir2 dir3 dir4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can't make new nested directories with &lt;code&gt;mkdir&lt;/code&gt;. To do so, use the &lt;code&gt;-p&lt;/code&gt; flag for "make parent directories"&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir -p new_directory/test_files/dir1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create new file&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Use redirect to create simple files for testing etc. This will create a file if it's not already there. If there is already a file with the same name present, it will overwrite it so be careful!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "Hello world" &amp;gt; test.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Appending to a file
&lt;/h2&gt;

&lt;p&gt;Using &lt;code&gt;&amp;gt;&lt;/code&gt; to add something to a file will overwrite what was there before. Use &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt; to append to the end of file without overwriting everything.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "Appending some text!" &amp;gt;&amp;gt; myfile.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  View directory contents
&lt;/h2&gt;

&lt;p&gt;List all directories and files in current working directory excluding hidden ones&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Also show hidden files:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;See file permissions and more info (long format)&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Viewing files
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;cat&lt;/code&gt; to simply print the all the contents to the screen&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This can be done with multiple file names to see contents of multiple files&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat config.txt test.txt hello.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use the &lt;code&gt;less&lt;/code&gt; pager program to view files in an interactive pager.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using Wildcards * and ?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;?&lt;/code&gt; will match any single character.&lt;/p&gt;

&lt;p&gt;For example, if you have multiple files like &lt;code&gt;test_1.txt&lt;/code&gt;, &lt;code&gt;test_2.txt&lt;/code&gt; and &lt;code&gt;test_3.txt&lt;/code&gt;, you could print out all files like so:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;*&lt;/code&gt; will match zero or more characters.&lt;/p&gt;

&lt;p&gt;For example, remove all &lt;code&gt;mp3&lt;/code&gt; files:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Moving and renaming files and directories
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;mv&lt;/code&gt; to move or rename files&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mv &amp;lt;file_to_move&amp;gt; &amp;lt;destination_to_move_it&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example: move &lt;code&gt;test.txt&lt;/code&gt; to the &lt;code&gt;testing&lt;/code&gt; directory one level above&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;You can move multiple files/directories at once. List all the files/directories to move first. The last item will serve as the destination directory. The command below will move &lt;code&gt;file.txt&lt;/code&gt;, &lt;code&gt;dir1&lt;/code&gt;, and &lt;code&gt;file2.txt&lt;/code&gt; to the &lt;code&gt;dir2&lt;/code&gt; directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mv file.txt dir1 file2.txt dir2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example: rename &lt;code&gt;test.txt&lt;/code&gt; to &lt;code&gt;unit_tests.txt&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Example: rename &lt;code&gt;testing&lt;/code&gt; directory to &lt;code&gt;unit_tests&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mv testing unit_tests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Copying file
&lt;/h2&gt;

&lt;p&gt;Copy to a new directory&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cp &amp;lt;file_to_copy&amp;gt; &amp;lt;direcory_to_copy_to&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example: Make a copy of &lt;code&gt;config.txt&lt;/code&gt; in the &lt;code&gt;backup&lt;/code&gt; directory&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Copy a file to the same directory with a new name&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cp &amp;lt;file_to_copy&amp;gt; &amp;lt;new_name_for_copied_file&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example: Create a copy of &lt;code&gt;essay.txt&lt;/code&gt; in the current directory and name it &lt;code&gt;essay_edit.txt&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Removing (Deleting) files and directories
&lt;/h2&gt;

&lt;p&gt;CAUTION: These commands will permanently delete things without a way to retrieve them, so make sure you're very careful!&lt;/p&gt;

&lt;p&gt;Delete one or more files&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rm test1.txt
rm text2.txt test3.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Delete a directory. This only works for empty directories.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Delete a directory and any empty sub-directories using the &lt;code&gt;-p&lt;/code&gt; flag. This will not delete files contained in the directories. Below would delete the &lt;code&gt;my_folder&lt;/code&gt; directory and any empty subfolders it contains.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rmdir -p my_folder
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remove all directories and files in the given location (Dangerous):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rm -r folder_to_delete
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Word and line counts
&lt;/h2&gt;

&lt;p&gt;Show line count, word count, and byte count of a file (in that order)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wc test_1.txt
&amp;gt;   5      10      56 test_1.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above output tells us that &lt;code&gt;test_1.txt&lt;/code&gt; has 5 lines, 10 words, and 56 bytes.&lt;/p&gt;

&lt;p&gt;To show only line count, use the &lt;code&gt;-l&lt;/code&gt; flag&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wc -l test_1.txt
&amp;gt;   5 test_1.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Sort command
&lt;/h2&gt;

&lt;p&gt;Sort a file by line, that is, matching lines will be grouped together.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Piping
&lt;/h2&gt;

&lt;p&gt;Pipes &lt;code&gt;|&lt;/code&gt; allow you to feed the output of one command into the next command.&lt;/p&gt;

&lt;p&gt;Example: See how many files/folders there are in the user's home directory&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ls ~ | wc -l
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ls ~&lt;/code&gt; would list all the files in the directory. Putting a pipe after it feeds the output into the &lt;code&gt;wc&lt;/code&gt; word count command.&lt;/p&gt;

&lt;p&gt;Example: Count the number of unique lines in a file. Note that &lt;code&gt;uniq&lt;/code&gt; will give you only the unique lines in a file, but it only does so if the duplicated lines are next to each other.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sort my_file.txt | uniq | wc -l
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;man&lt;/code&gt;: See documentation on a command
&lt;/h2&gt;

&lt;p&gt;Get info about how to use a command and the available options with &lt;code&gt;man&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Run a command as the super user
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;sudo&lt;/code&gt; followed by the command you want to run. Do this only when absolutely necessary!&lt;/p&gt;

</description>
      <category>commandline</category>
      <category>linux</category>
    </item>
    <item>
      <title>Sidekiq's sidekiq_retries_exhausted hook</title>
      <dc:creator>Felice Forby</dc:creator>
      <pubDate>Thu, 12 Aug 2021 13:07:41 +0000</pubDate>
      <link>https://forem.com/morinoko/sidekiq-s-sidekiqretriesexhausted-hook-3d0e</link>
      <guid>https://forem.com/morinoko/sidekiq-s-sidekiqretriesexhausted-hook-3d0e</guid>
      <description>&lt;p&gt;&lt;code&gt;sidekiq_retries_exhausted&lt;/code&gt; is a Sidekiq hook that you can use to do something after Sidekiq has used up all of its retries but the job still failed. It's a good way to make sure you send a failure notification or log an error that might be causing the job to fail instead of it just failing silently.&lt;/p&gt;

&lt;p&gt;In the worker, you can set a specific number of retries if you want with &lt;code&gt;sidekiq_options retry: &amp;lt;some_number&amp;gt;&lt;/code&gt;. The default is 25 times.&lt;/p&gt;

&lt;p&gt;Here are a couple of examples but there are ton of ways to configure this which can be found in the documentation.&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="c1"&gt;# Retry 3 times before giving up&lt;/span&gt;
&lt;span class="n"&gt;sidekiq_options&lt;/span&gt; &lt;span class="ss"&gt;retry: &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="c1"&gt;# Don't retry at all&lt;/span&gt;
&lt;span class="n"&gt;sidekiq_options&lt;/span&gt; &lt;span class="ss"&gt;retry: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the job has used up (exhausted) all of its retries, Sidekiq moves it to the "Dead set" and it will eventually get discarded.&lt;/p&gt;

&lt;p&gt;Sidekiq will call the &lt;code&gt;sidekiq_retries_exhausted&lt;/code&gt; hook right before moving the job to the dead set if you define it in the worker. &lt;code&gt;sidekiq_retries_exhausted&lt;/code&gt; takes a block and receives the queued message as an argument so you can use it to compose a log message. See below for an example:&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;MyWorker&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Worker&lt;/span&gt;
  &lt;span class="n"&gt;sidekiq_options&lt;/span&gt; &lt;span class="ss"&gt;retry: &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;

  &lt;span class="n"&gt;sidekiq_retries_exhausted&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;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="c1"&gt;# example with using Rails' logger&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;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Failed &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'class'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; with &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'args'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'error_message'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;error: &lt;/span&gt;&lt;span class="n"&gt;exception&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;perform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# do some work&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;This hook is worker specific, so you would define &lt;code&gt;sidekiq_retries_exhausted&lt;/code&gt; for each worker you need. There is also a way to send a job "death" notice for all workers globally by adding some configuration in the initializer (in Rails that would be the &lt;code&gt;config/initializers/sidekiq.rb&lt;/code&gt; file).&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="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure_server&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;config&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="c1"&gt;# other config stuff...&lt;/span&gt;

  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;death_handlers&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&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;job&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&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;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt; &lt;span class="s2"&gt;"Uh oh, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'class'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"jid"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; just died with error &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;message&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;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/mperham/sidekiq/wiki/Error-Handling" rel="noopener noreferrer"&gt;Sidekiq error handling documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mperham/sidekiq/blob/3575ccb44c688dd08bfbfd937696260b12c622fb/lib/sidekiq/worker.rb#L59-L61" rel="noopener noreferrer"&gt;Source code for sidekiq_retries_exhausted&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.rubydoc.info/gems/sidekiq/Sidekiq/JobRetry" rel="noopener noreferrer"&gt;Sidekiq job retries documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>sidekiq</category>
    </item>
    <item>
      <title>Rename a Rails app (including database, Github, and Heroku names)</title>
      <dc:creator>Felice Forby</dc:creator>
      <pubDate>Fri, 10 Jul 2020 01:13:32 +0000</pubDate>
      <link>https://forem.com/morinoko/rename-a-rails-app-including-database-github-and-heroku-names-3lch</link>
      <guid>https://forem.com/morinoko/rename-a-rails-app-including-database-github-and-heroku-names-3lch</guid>
      <description>&lt;p&gt;Recently I started working on a Rails project without having a good name picked out, so I gave the application a temporary one for the time being. I ended up with a Github repository and a Heroku app that used that temporary name, but after finally thinking of the perfect name, I naturally wanted to update it everywhere. This is how I did it!&lt;/p&gt;

&lt;p&gt;I'll go over how I changed the repository name on Github and the name of the app on Heroku, and how you can go about changing the name of the databases used by Rails.&lt;/p&gt;

&lt;p&gt;For reference, this is the setup of my app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rails 6.0.3.2&lt;/li&gt;
&lt;li&gt;Ruby 2.7.1&lt;/li&gt;
&lt;li&gt;Code on Github&lt;/li&gt;
&lt;li&gt;Deployment to Heroku&lt;/li&gt;
&lt;li&gt;PostgreSQL database in both production and development&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Rename the Github repository
&lt;/h2&gt;

&lt;p&gt;To change the name on Github, simply go to the repository page online, navigate to repository's Settings page and change the name using the "Repository name" field.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftvn6yu2lizm32hf3rbxl.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%2Fi%2Ftvn6yu2lizm32hf3rbxl.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Github will take care of forwarding to the new URL whenever the old URL is accessed, for example when you push or pull, but I think it would be better to make sure the remote URLs on your local machine also match up. &lt;/p&gt;

&lt;p&gt;To update the remote on your computer, first, grab the new url from the repository page on Github, which you can get from the "Clone with SSH" button. &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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fff0b67biu15fb4ntjm95.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%2Fi%2Fff0b67biu15fb4ntjm95.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It should look something like this:&lt;/p&gt;

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

git@github.com:your-username/reponame.git


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

&lt;/div&gt;

&lt;p&gt;Next, navigate to the directory where your Rails app lives on your local machine.&lt;/p&gt;

&lt;p&gt;You can check the currently registered remote URL that connects the git repository to Github with the following command (assuming remote is named "origin", which it should be unless you changed it):&lt;/p&gt;

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

git config --get remote.origin.url


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

&lt;/div&gt;

&lt;p&gt;At this point, it should still display the old remote URL, something like &lt;code&gt;git@github.com:your-username/old-repo-name.git&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To update it, enter the following command using the URL you copied from Github:&lt;/p&gt;

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

git remote set-url origin git@github.com:your-username/new-reponame.git


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

&lt;/div&gt;

&lt;p&gt;You can double check that it got updated by running the &lt;code&gt;git config --get remote.origin.url&lt;/code&gt; command again.&lt;/p&gt;

&lt;p&gt;Okay! That should take care of the Github side! Next, let's update things on the Heroku side.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rename the app on Heroku
&lt;/h2&gt;

&lt;p&gt;This is done easiest from the command line because it will also automatically update the remote URL for Heroku as well. Type the following command in the command line from within the app's directory, replacing &lt;code&gt;new-name&lt;/code&gt; with new name of your app:&lt;/p&gt;

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

heroku apps:rename new-name


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

&lt;/div&gt;

&lt;p&gt;Simple as that! You can check to make sure the remote URL for Heroku has been updated with the following command:&lt;/p&gt;

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

git config --get remote.heroku.url


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

&lt;/div&gt;

&lt;p&gt;It should look something like &lt;code&gt;https://git.heroku.com/new-name.git&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you navigate to your Heroku dashboard online, you will see that everything has been updated! &lt;/p&gt;

&lt;p&gt;Well, almost everything... If you had the Github repository connected to Heroku under the "Deploy" settings, it will still have the old Github URL. Though Github will automatically redirect any access to this URL, you might want to update it here too. Just use the "disconnect" button to disconnect and then reconnect to the newly renamed repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rename the Rails databases
&lt;/h2&gt;

&lt;p&gt;Although you don't technically have to rename the databases, you may want to anyways just to be consistent.&lt;/p&gt;

&lt;p&gt;When you first ran &lt;code&gt;rails new&lt;/code&gt; command, it creates a file for database configuration, the &lt;code&gt;config/database.yml&lt;/code&gt; file. The databases are named after the app name you passed along to the &lt;code&gt;rails new&lt;/code&gt; command, so in the &lt;code&gt;database.yml&lt;/code&gt; file you will find settings that look something like this (where &lt;code&gt;app_name&lt;/code&gt; is the name of the app):&lt;/p&gt;

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

&lt;span class="c1"&gt;# config/database.yml&lt;/span&gt;

&lt;span class="c1"&gt;# ... other code&lt;/span&gt;

&lt;span class="na"&gt;development&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*default&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app_name_development&lt;/span&gt;

&lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*default&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app_name_test&lt;/span&gt;

&lt;span class="na"&gt;production&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*default&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app_name_production&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app_name&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= ENV['APP_NAME_DATABASE_PASSWORD'] %&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  Development/Test database configuration
&lt;/h3&gt;

&lt;p&gt;Depending on how you set up your data for the development environment (if at all), you can run into a few different situations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have a &lt;code&gt;db/seeds.rb&lt;/code&gt; file that sets up all the data.&lt;/li&gt;
&lt;li&gt;You did not use the &lt;code&gt;db/seeds.rb&lt;/code&gt; file, but the data created while testing out the app in development isn't that important and you don't care if it gets erased.&lt;/li&gt;
&lt;li&gt;You did not use the &lt;code&gt;db/seeds.rb&lt;/code&gt; file, but you want to keep the data created while testing out the app in development, so it should NOT get erased.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Situation 1: You have a &lt;code&gt;db/seeds.rb&lt;/code&gt; file for all your data
&lt;/h3&gt;

&lt;p&gt;First, drop (= destroy) the database with this rails command:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

rails db:drop


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

&lt;/div&gt;

&lt;p&gt;If successful, you'll see the following output:&lt;/p&gt;

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

$ rails db:drop
Dropped database 'app_name_development'
Dropped database 'app_name_test'


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

&lt;/div&gt;

&lt;p&gt;Rename the development and test databases in the &lt;code&gt;config/database.yml&lt;/code&gt; file, replacing &lt;code&gt;new_name&lt;/code&gt; with the actual name you want to use:&lt;/p&gt;

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

&lt;span class="c1"&gt;# config/database.yml&lt;/span&gt;

&lt;span class="c1"&gt;# ... other code&lt;/span&gt;

&lt;span class="na"&gt;development&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*default&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;new_name_development&lt;/span&gt;

&lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*default&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;new_name_test&lt;/span&gt;

&lt;span class="c1"&gt;# ... more code&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Run &lt;code&gt;rails db:setup&lt;/code&gt; to recreate the databases and fill it with your seed data.&lt;/p&gt;

&lt;p&gt;That's it! Everything should work like before.&lt;/p&gt;

&lt;h3&gt;
  
  
  Situation 2: You don't have seed data, but don't care if everything is erased
&lt;/h3&gt;

&lt;p&gt;First, drop (= destroy) the database with this rails command:&lt;/p&gt;

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

rails db:drop


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

&lt;/div&gt;

&lt;p&gt;If successful, you'll see the following output:&lt;/p&gt;

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

$ rails db:drop
Dropped database 'app_name_development'
Dropped database 'app_name_test'


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

&lt;/div&gt;

&lt;p&gt;Rename the test and development databases in the &lt;code&gt;config/database.yml&lt;/code&gt; file as described above.&lt;/p&gt;

&lt;p&gt;Then run &lt;code&gt;rails db:create&lt;/code&gt; and &lt;code&gt;rails db:migrate&lt;/code&gt; to set up a sparkling new database with a new name.&lt;/p&gt;

&lt;h3&gt;
  
  
  Situation 3: You don't have seed data, but you want to make sure no data gets erased.
&lt;/h3&gt;

&lt;p&gt;I am using a PostgreSQL database in my development environment and have PostgreSQL installed locally, so this explanation will be specific to this setup. If you're using a different database locally like Sqlite, you'll have to look up the specific methods for that database. &lt;/p&gt;

&lt;h4&gt;
  
  
  Using a database dump (backup) file
&lt;/h4&gt;

&lt;p&gt;If you do need to backup data you had for development, you can use the &lt;code&gt;pg_dump&lt;/code&gt; tool provided by your PostgreSQL database.&lt;/p&gt;

&lt;p&gt;I used this tutorial, &lt;a href="http://tutorials.jumpstartlab.com/topics/devops/backing_up_and_restoring_a_database.html" rel="noopener noreferrer"&gt;Backing Up and Restoring A Database&lt;/a&gt;, as a reference, so check it out for more in-depth explanation. &lt;/p&gt;

&lt;h5&gt;
  
  
  Create the database dump file
&lt;/h5&gt;

&lt;p&gt;Create the backup file with the following command on the command line from within the Rails app directory, replacing &lt;code&gt;app_name_development&lt;/code&gt; with the actual name of your database listed in the &lt;code&gt;config/database.yml&lt;/code&gt; file:&lt;/p&gt;

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

pg_dump -F t app_name_development &amp;gt; development_backup.tar


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

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;-F t&lt;/code&gt; formats the file into a &lt;code&gt;tar&lt;/code&gt; file. &lt;code&gt;development_backup.tar&lt;/code&gt; is the name for the backup file, which you can name it anything you want. &lt;/p&gt;

&lt;p&gt;Learn more about the &lt;code&gt;pg_dump&lt;/code&gt; command in the &lt;a href="https://www.postgresql.org/docs/9.1/app-pgdump.html" rel="noopener noreferrer"&gt;PostgreSQL documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the running the above command, a database backup file should have been created in the root directory of your Rails app.&lt;/p&gt;

&lt;h5&gt;
  
  
  Drop the current database
&lt;/h5&gt;

&lt;p&gt;Drop (= destroy) the database with the Rails command (this will erase everything, so make sure your backup was created):&lt;/p&gt;

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

rails db:drop


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

&lt;/div&gt;

&lt;p&gt;If successful, you'll see the following output:&lt;/p&gt;

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

$ rails db:drop
Dropped database 'app_name_development'
Dropped database 'app_name_test'


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

&lt;/div&gt;

&lt;p&gt;If you run the Rails server and try to access the app, you'll also see a &lt;code&gt;ActiveRecord::NoDatabaseError&lt;/code&gt;.&lt;/p&gt;

&lt;h5&gt;
  
  
  Rename and recreate the database
&lt;/h5&gt;

&lt;p&gt;Rename the development and test databases in the &lt;code&gt;config/database.yml&lt;/code&gt; file, which still contains the old database names.&lt;/p&gt;

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

&lt;span class="c1"&gt;# config/database.yml&lt;/span&gt;

&lt;span class="c1"&gt;# ... other code&lt;/span&gt;

&lt;span class="na"&gt;development&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*default&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;old_app_name_development&lt;/span&gt;

&lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*default&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;old_app_name_test&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Rename all the things with the &lt;code&gt;old_app_name&lt;/code&gt; to the new app name.&lt;/p&gt;

&lt;p&gt;After that, run &lt;code&gt;rails db:create&lt;/code&gt; in the command line to create the newly named database. You will see output like this:&lt;/p&gt;

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

$ rails db:create
Created database 'new_name_development'
Created database 'new_name_test'


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

&lt;/div&gt;
&lt;h5&gt;
  
  
  Restore the database from the backup file
&lt;/h5&gt;

&lt;p&gt;To restore from the database backup, you can use &lt;code&gt;pg_restore&lt;/code&gt; command, replacing &lt;code&gt;new_name_development&lt;/code&gt; with actual name in your &lt;code&gt;database.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

pg_restore -d new_name_development development_backup.tar


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

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;-d new_name_development&lt;/code&gt; option lets you connect to given database (here it's &lt;code&gt;new_name_development&lt;/code&gt;) and restore directly into it. &lt;code&gt;development_backup.tar&lt;/code&gt; specifies the name and location of the dump file that you created earlier.&lt;/p&gt;

&lt;p&gt;And there you go! Your development and test database are now renamed and the previous data has been restored for development.&lt;/p&gt;

&lt;h3&gt;
  
  
  Production database configuration
&lt;/h3&gt;

&lt;p&gt;The production database is the one that Heroku uses when running the deployed app. Rails generated the following production database configuration when I first created the app:&lt;/p&gt;

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

&lt;span class="c1"&gt;# config/database.yml&lt;/span&gt;

&lt;span class="c1"&gt;# ... other code&lt;/span&gt;

&lt;span class="na"&gt;production&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*default&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app_name_production&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app_name&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= ENV['APP_NAME_DATABASE_PASSWORD'] %&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;In my case, I just have a basic Heroku setup and don't have any custom database configurations. If that is the case, then you don't actually need this configuration because Heroku uses it's own configuration through an environment variable set as &lt;code&gt;ENV["DATABASE_URL"]&lt;/code&gt;, which will override the above configuration in the yaml file.&lt;/p&gt;

&lt;p&gt;In other words, renaming the production database here doesn't do anything. Instead, I would recommend changing the configuration to explicitly say that you are using the environment variable (also recommended in the &lt;a href="https://guides.rubyonrails.org/configuring.html#configuring-a-database" rel="noopener noreferrer"&gt;Rails Guides&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;In fact, you may have a comment in your &lt;code&gt;database.yml&lt;/code&gt; just above the &lt;code&gt;production&lt;/code&gt; settings that tells you how to do this depending on how the Rails app was initially set up:&lt;/p&gt;

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

&lt;span class="c1"&gt;# config/database.yml&lt;/span&gt;

&lt;span class="c1"&gt;# ... Other settings&lt;/span&gt;

&lt;span class="c1"&gt;# On Heroku and other platform providers, you may have a full connection URL&lt;/span&gt;
&lt;span class="c1"&gt;# available as an environment variable. For example:&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;#   DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase"&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# You can use this database configuration with:&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;#   production:&lt;/span&gt;
&lt;span class="c1"&gt;#     url: &amp;lt;%= ENV['DATABASE_URL'] %&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;So, as a last step, change the production database configuration inside &lt;code&gt;database.yml&lt;/code&gt; so that it looks like this:&lt;/p&gt;

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

&lt;span class="c1"&gt;# config/database.yml&lt;/span&gt;

&lt;span class="c1"&gt;# ... Other settings&lt;/span&gt;

&lt;span class="na"&gt;production&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= ENV['DATABASE_URL'] %&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;And we are finished! Everything should now be renamed to the correct app name :D&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://guides.rubyonrails.org/configuring.html#configuring-a-database" rel="noopener noreferrer"&gt;Rails Guides: Configuring a database&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://tutorials.jumpstartlab.com/topics/devops/backing_up_and_restoring_a_database.html" rel="noopener noreferrer"&gt;Backing Up and Restoring A Database&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.postgresql.org/docs/9.1/app-pgdump.html" rel="noopener noreferrer"&gt;PostgreSQL pg_dump documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.postgresql.org/docs/9.2/app-pgrestore.html" rel="noopener noreferrer"&gt;PostgreSQL pg_restore documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>postgres</category>
      <category>heroku</category>
    </item>
    <item>
      <title>Stopping a Webcam with JavaScript</title>
      <dc:creator>Felice Forby</dc:creator>
      <pubDate>Mon, 30 Mar 2020 08:14:47 +0000</pubDate>
      <link>https://forem.com/morinoko/stopping-a-webcam-with-javascript-4297</link>
      <guid>https://forem.com/morinoko/stopping-a-webcam-with-javascript-4297</guid>
      <description>&lt;p&gt;I recently had to manually get a running web camera to turn off using JavaScript for a project at work.&lt;/p&gt;

&lt;p&gt;I had a hard time figuring out JavaScript's MediaStream API so here are some quick notes on how I got the camera to stop.&lt;/p&gt;

&lt;p&gt;If the camera is running through a video element, you can stop the video by getting its &lt;code&gt;MediaStreamTrack&lt;/code&gt; object and using the &lt;code&gt;stop()&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;video&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;video&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// A video's MediaStream object is available through its srcObject attribute&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mediaStream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;srcObject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Through the MediaStream, you can get the MediaStreamTracks with getTracks():&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tracks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mediaStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTracks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Tracks are returned as an array, so if you know you only have one, you can stop it with: &lt;/span&gt;
&lt;span class="nx"&gt;tracks&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="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Or stop all like so:&lt;/span&gt;
&lt;span class="nx"&gt;tracks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;track&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;track&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another way to get all the MediaStreams is to use &lt;code&gt;mediaDevices.getUserMedia()&lt;/code&gt; which is called on &lt;code&gt;navigator&lt;/code&gt; tracks. It prompts the user for permission (if not already granted) to access the media devices. It will return a Promise so you can write the necessary code within the Promise's &lt;code&gt;then&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mediaDevices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getUserMedia&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;video&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mediaStream&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mediaStream&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tracks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTracks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;tracks&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="nx"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure you only call &lt;code&gt;getUserMedia&lt;/code&gt; once or &lt;code&gt;stop()&lt;/code&gt; won't work, so if your code or a library you're using calls &lt;code&gt;getUserMedia&lt;/code&gt; on the page to activate a camera, then you probably won't be able to use this method.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack" rel="noopener noreferrer"&gt;MDN MediaStreamTrack Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack" rel="noopener noreferrer"&gt;MDN MediaStreamTrack Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia" rel="noopener noreferrer"&gt;MDN MediaDevices.getUserMedia()
Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>QR Code Reader on Rails</title>
      <dc:creator>Felice Forby</dc:creator>
      <pubDate>Fri, 21 Feb 2020 00:06:40 +0000</pubDate>
      <link>https://forem.com/morinoko/qr-code-reader-on-rails-5816</link>
      <guid>https://forem.com/morinoko/qr-code-reader-on-rails-5816</guid>
      <description>&lt;h1&gt;
  
  
  Intro and getting started
&lt;/h1&gt;

&lt;p&gt;I recently had to implement a QR code reader in Rails at work and in this article, I'll take you through how I did it by creating a demo featuring two different ways of handling scanned QR codes: One simply scans a QR code and displays the scanned data on the screen and the other sends the QR data to a Rails controller for processing.&lt;/p&gt;

&lt;p&gt;Let's get started right away! We'll do so by creating a new Rails project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails new qr-code-reader-demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we'll install a JavaScript library that will allow us to scan QR codes with a video camera on a phone or computer.&lt;/p&gt;

&lt;h1&gt;
  
  
  Install the QR code reader: ZXing-js
&lt;/h1&gt;

&lt;p&gt;After research different QR code scanning libraries, I decided to use the &lt;a href="https://github.com/zxing-js/library" rel="noopener noreferrer"&gt;ZXing JS library&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Why ZXing?&lt;/p&gt;

&lt;p&gt;Ideally, it would have been nice to use a ruby gem. Although there are a few QR code reader gems available, they are no longer maintained (no updates for a couple of years).&lt;/p&gt;

&lt;p&gt;The next option was using a JavaScript library. There are several JS libraries that handle QR code scanning, but ZXing is actively maintained and is a popular choice among developers. ZXing-js is actually a port of an "open-source, multi-format 1D/2D barcode image processing library implemented in Java." &lt;/p&gt;

&lt;p&gt;Let's get it installed into Rails.&lt;/p&gt;

&lt;p&gt;Simply use npm to install the package and then update yarn:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Install with npm
npm i @zxing/library --save

# Update yarn packages
yarn install --check-files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Basic QR code reader: Scan and display on the screen
&lt;/h1&gt;

&lt;p&gt;First, we'll create a super simple scanner that just takes the data decoded from the QR code and displays it on the page.&lt;/p&gt;

&lt;p&gt;Let's set up a route and a controller. You can, of course, name the route and controller whatever you want, but I'm going to make the path &lt;code&gt;/basic-qr-code-reader&lt;/code&gt; and route it the &lt;code&gt;#index&lt;/code&gt; action of a controller called the &lt;code&gt;BasicQrCodesController&lt;/code&gt;:&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="c1"&gt;# config/routes.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;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;draw&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s1"&gt;'basic-qr-code-reader'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s1"&gt;'basic_qr_codes#index'&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 js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/controllers/basic_qr_codes_controller.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BasicQrCodesController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&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;The controller won't be doing anything special except for rendering a view, so it's just a barebones action.&lt;/p&gt;

&lt;p&gt;Here is the basic JavaScript code—borrowing from &lt;a href="https://zxing-js.github.io/library/examples/qr-camera/" rel="noopener noreferrer"&gt;one of ZXing's demos&lt;/a&gt;—that will get the job done. We'll put it into a file under &lt;code&gt;app/javascript/packs/&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/javascript/packs/basic-qr-code-reader.js&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BrowserQRCodeReader&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@zxing/library&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;codeReader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BrowserQRCodeReader&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;codeReader&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decodeFromInputVideoDevice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;video&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&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="c1"&gt;// process the result&lt;/span&gt;
    &lt;span class="nx"&gt;console&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="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;result&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;codeReader&lt;/code&gt; is an instance of the ZXing's &lt;code&gt;BrowserQRCodeReader&lt;/code&gt; class. In our case, we want to use a camera on some kind of device, so we'll use the &lt;code&gt;decodeFromInputVideoDevice()&lt;/code&gt; method, which takes a device ID and a video element id as arguments. Passing in &lt;code&gt;undefined&lt;/code&gt; chooses the default camera (if there are multiple cameras, you could allow the user to choose which one they want to use, for example. Check ZXing's documentation for more info). &lt;/p&gt;

&lt;p&gt;&lt;code&gt;decodeFromInputVideoDevice()&lt;/code&gt; will return a promise with the data (a string) that was decoded from the QR code.&lt;/p&gt;

&lt;p&gt;In our HTML view, we need to make sure we have a &lt;code&gt;video&lt;/code&gt; element with the given id (in our case it's just &lt;code&gt;video&lt;/code&gt;). The JavaScript will decode the QR code from there.&lt;/p&gt;

&lt;p&gt;Also, since we plan on displaying the result on the page, we need a place to put it. Examining the JavaScript above, you can see that the result is going to be injected into the HTML via an element that has an id of &lt;code&gt;result&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;result&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is a basic view that includes all of the necessary elements as well as our QR code reader JavaScript inserted with a Rails &lt;code&gt;javascript_pack_tag&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;%# app/views/basic_qr_codes/index.html.erb%&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;QR Code Reader Demo&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;video&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"video"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"500"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"400"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/video&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;Result:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;pre&amp;gt;&amp;lt;code&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"result"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&lt;/span&gt;

&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;javascript_pack_tag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"basic-qr-code-reader"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, that's it for the basic version! Start up the rails server with &lt;code&gt;rails s&lt;/code&gt; and navigate to &lt;code&gt;http://localhost:3000/basic-qr-code-reader&lt;/code&gt;. Try scanning a QR code and it should appear right there on the screen. &lt;/p&gt;

&lt;h1&gt;
  
  
  QR Code Reader on Rails: Processing scan data in Rails
&lt;/h1&gt;

&lt;p&gt;The basic QR code scanner above is fun to play around with but it doesn't let us doing anything with the data we decoded.&lt;/p&gt;

&lt;p&gt;In this section, we're going to get the JavaScript to handover the code data to Rails so we can process it and go further.&lt;/p&gt;

&lt;p&gt;For this demo, we'll be set up a simple ActiveRecord model and controller that lets us use the data to create QR code objects and save them to the database. We'll also have a page that shows a history of our most recent scans.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up a QR code model
&lt;/h2&gt;

&lt;p&gt;Let's start off by creating a model called &lt;code&gt;QrCode&lt;/code&gt; and database table where we can save the data.&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;rails g migration CreateQrCodes data:string&lt;/code&gt; and then open up the generated file to check it's contents:&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="c1"&gt;# Migration for QrCodes&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreateQrCodes&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Migration&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;change&lt;/span&gt;
    &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="ss"&gt;:qr_codes&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="ss"&gt;:data&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;rails db:migrate&lt;/code&gt; to set up the table. &lt;/p&gt;

&lt;p&gt;For the model, we just need the bare minimum for now:&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="c1"&gt;# app/models/qr_code.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;QrCode&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Initial routes and controller set up
&lt;/h2&gt;

&lt;p&gt;To get things moving, we need to add some routes and a couple of controller actions. &lt;/p&gt;

&lt;p&gt;We'll keep the flow basic: Open the scanner camera and get the data (&lt;code&gt;new&lt;/code&gt; action), use the data to create a QrCode object (&lt;code&gt;create&lt;/code&gt; action), and display the newly scanned QR code data (&lt;code&gt;show&lt;/code&gt; action).&lt;/p&gt;

&lt;p&gt;Add the necessary routes to &lt;code&gt;routes.rb&lt;/code&gt; with the following line:&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;resources&lt;/span&gt; &lt;span class="ss"&gt;:qr_codes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:new&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:create&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:show&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;routes.rb&lt;/code&gt; should look like this now:&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="c1"&gt;# config/routes.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;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;draw&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s1"&gt;'basic-qr-code-reader'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s1"&gt;'basic_qr_codes#index'&lt;/span&gt;

  &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:qr_codes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:new&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:create&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:show&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll go ahead and stub out the controller actions, too. Create a file called &lt;code&gt;qr_codes_controller.rb&lt;/code&gt; in the &lt;code&gt;app/controllers&lt;/code&gt; directory:&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="c1"&gt;# app/controllers/qr_codes_controller.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;QrCodesController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;
  &lt;span class="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;Okay, that takes care of the wiring. Now on to the JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript: Send the QR code scan data to Rails
&lt;/h2&gt;

&lt;p&gt;We need to do a few extra things in the QR code reader JavaScript in order to get it to communicate with our controller. (We'll put the new version of the QR reader JavaScript in another pack file, &lt;code&gt;app/javascript/packs/rails-qr-code-reader.js&lt;/code&gt;, for the purpose of this demonstration.)&lt;/p&gt;

&lt;p&gt;Here's the code and I'll explain below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/javascript/packs/rails-qr-code-reader.js&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BrowserQRCodeReader&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@zxing/library&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Rails&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@rails/ujs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Use to make an ajax post request to Rails&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;codeReader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BrowserQRCodeReader&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;codeReader&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decodeFromInputVideoDevice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;video&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;qrDataFromReader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Prepare a post request so it can be sent to the Rails controller&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;qrCodeParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;qr_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;qrDataFromReader&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;qr_code_json_data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;qrCodeParams&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="c1"&gt;// Send QR code data as JSON to the &lt;/span&gt;
    &lt;span class="c1"&gt;// qr_codes#create action using Rails ujs&lt;/span&gt;
    &lt;span class="nx"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ajax&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/qr_codes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;post&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The plan is to send the QR code data to the &lt;code&gt;create&lt;/code&gt; action of the QrCodes controller, which we'll do by making a POST request with ajax. To make that easier, we'll use Rails' ujs library. It needs to be imported into the JavaScript with &lt;code&gt;import Rails from '@rails/ujs';&lt;/code&gt; at the top of the file.&lt;/p&gt;

&lt;p&gt;After getting the data from the code reader, we'll save it into variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;qrDataFromReader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we'll prepare the data with by creating a new JavaScript &lt;code&gt;FormData&lt;/code&gt; object, parameterizing the data, and converting it to JSON:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Create a new FormData object&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Prepare the data params&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;qrCodeParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;qr_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;qrDataFromReader&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt; 

&lt;span class="c1"&gt;// Add the params to the FormData object, making sure to convert it to JSON&lt;/span&gt;
&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;qr_code_json_data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;qrCodeParams&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, we just need to use the &lt;code&gt;.ajax&lt;/code&gt; method of Rails ujs to send the data to the controller!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ajax&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/qr_codes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;post&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the &lt;code&gt;url&lt;/code&gt; is the POST path for the &lt;code&gt;QrCodesController&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Set up a view for the QR code reader in &lt;code&gt;app/views/qr_codes/new.html.erb&lt;/code&gt; and make sure the JavaScript pack gets included:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;QR Code Reader Demo&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;QR Code Reader on Rails&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;video&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"video"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"500"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"400"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/video&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;javascript_pack_tag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"rails-qr-code-reader"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that the scanner is ready, next we'll catch the scan data in the controller and process it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Processing the QR code data
&lt;/h2&gt;

&lt;p&gt;The data will arrive in the QrCodes controller &lt;code&gt;create&lt;/code&gt; action. Because it comes in as JSON, we need to parse the JSON so we can use it. Let's add a before action that does that for us:&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="c1"&gt;# app/controllers/qr_codes_controller.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;QrCodesController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="n"&gt;before_action&lt;/span&gt; &lt;span class="ss"&gt;:set_qr_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: :create&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&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;new&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;
  &lt;span class="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;set_qr_data&lt;/span&gt;
    &lt;span class="n"&gt;qr_code_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:qr_code_json_data&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;with_indifferent_access&lt;/span&gt;

    &lt;span class="vi"&gt;@qr_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;qr_code_params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:qr_data&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;Here, &lt;code&gt;JSON.parse&lt;/code&gt; gets the data into a usable form and &lt;code&gt;.with_indifferent_access&lt;/code&gt; allows us to access the data using symbols (&lt;code&gt;qr_code_params[:qr_data]&lt;/code&gt;) instead of quotes (&lt;code&gt;qr_code_params['qr_data']&lt;/code&gt;). Not necessary, but I prefer symbols.&lt;/p&gt;

&lt;p&gt;The params are available with &lt;code&gt;params[:qr_code_json_data]&lt;/code&gt; because we named them that in the JavaScript above with this line: &lt;code&gt;formData.append("qr_code_json_data", JSON.stringify(qrCodeParams));&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Inside of the QR code params, the qr data is available through the &lt;code&gt;qr_data&lt;/code&gt; key, also because of the way we set up the data earlier in the JavaScript (&lt;code&gt;let qrCodeParams = { qr_data: qrDataFromReader };&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;After the everything is parsed, assign the data to an instance variable like so &lt;code&gt;@qr_data = qr_code_params[:qr_data]&lt;/code&gt; and now we can treat the data as usual and use it to create new QrCode objects!&lt;/p&gt;

&lt;p&gt;Let's do so in the &lt;code&gt;create&lt;/code&gt; action and then redirect to a show page where we can see the new database entry.&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="c1"&gt;# app/controllers/qr_codes_controller.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;QrCodesController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="n"&gt;before_action&lt;/span&gt; &lt;span class="ss"&gt;:set_qr_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: :create&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&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;new&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
    &lt;span class="n"&gt;qr_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;QrCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;content: &lt;/span&gt;&lt;span class="vi"&gt;@qr_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;qr_code_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qr_code&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;show&lt;/span&gt;
    &lt;span class="vi"&gt;@qr_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;QrCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

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

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;set_qr_data&lt;/span&gt;
    &lt;span class="n"&gt;qr_code_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:qr_code_json_data&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;with_indifferent_access&lt;/span&gt;

    &lt;span class="vi"&gt;@qr_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;qr_code_params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:qr_data&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;We just need to set up a basic show view where we can display the data, which we'll put in a new view file at &lt;code&gt;app/views/qr_codes/new.html.erb&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;QR Code Show Page&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;QR data: &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="vi"&gt;@qr_code&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;content&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Scanned on &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="vi"&gt;@qr_code&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%Y-%m-%d'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing special here, but it lets us see the scanned data and the day it was scanned on.&lt;/p&gt;

&lt;p&gt;It might also be nice to have an index page that lists all the recent scans, so let's set up the &lt;code&gt;index&lt;/code&gt; action in the controller. We'll keep it simple and just show the 20 most recent scans:&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="c1"&gt;# app/controllers/qr_codes_controller.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;QrCodesController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="n"&gt;before_action&lt;/span&gt; &lt;span class="ss"&gt;:set_qr_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: :create&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;
    &lt;span class="vi"&gt;@qr_codes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;QrCode&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="ss"&gt;created_at: :desc&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&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;new&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
    &lt;span class="n"&gt;qr_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;QrCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;content: &lt;/span&gt;&lt;span class="vi"&gt;@qr_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;qr_code_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qr_code&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;show&lt;/span&gt;
    &lt;span class="vi"&gt;@qr_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;QrCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

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

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;set_qr_data&lt;/span&gt;
    &lt;span class="n"&gt;qr_code_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:qr_code_json_data&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;with_indifferent_access&lt;/span&gt;

    &lt;span class="vi"&gt;@qr_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;qr_code_params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:qr_data&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;We also need the view for the index (&lt;code&gt;app/views/qr_codes/index.html.erb&lt;/code&gt;), which we'll set up to be a simple list of scans that links to each scan's show page. It also has a button that links to the QR code scanner:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Recent QR Code Scans&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;link_to&lt;/span&gt; &lt;span class="s1"&gt;'New Scan'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_rails_qr_code_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="s1"&gt;'button'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;&lt;/span&gt;20 most recent scans:&lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="vi"&gt;@qr_codes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with_index&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;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;qr_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="s2"&gt;"Scan &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: "&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;link_to&lt;/span&gt; &lt;span class="n"&gt;qr_code&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rails_qr_code_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qr_code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it! You just made a QR coder reader on Rails! I have the full code on &lt;a href="https://github.com/morinoko/qr-code-reader-demo" rel="noopener noreferrer"&gt;Github&lt;/a&gt; if you'd like to explore.&lt;/p&gt;

&lt;p&gt;This is a somewhat contrived and simple example, but there are plenty of applications for scanning QR codes and using their data. For example, for the project I did at work, the scanned QR codes contained the manufacturer serial numbers of certain machines. The serial codes were used to find specific models based on the serial number (which was done in the controller) and take the user to that model's information page for troubleshooting.&lt;/p&gt;

&lt;p&gt;Anyway, have fun with it and enjoy :D&lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
    </item>
    <item>
      <title>Using MySQL with Rails 6 and installing MySQL on Mac (macOS Mojave)</title>
      <dc:creator>Felice Forby</dc:creator>
      <pubDate>Thu, 26 Sep 2019 06:34:19 +0000</pubDate>
      <link>https://forem.com/morinoko/using-mysql-with-rails-6-and-installing-mysql-on-mac-macos-mojave-di3</link>
      <guid>https://forem.com/morinoko/using-mysql-with-rails-6-and-installing-mysql-on-mac-macos-mojave-di3</guid>
      <description>&lt;p&gt;I recently had to switch databases from Sqlite to MySQL after already creating a Rails app. I also had to install MySQL on my Mac.&lt;/p&gt;

&lt;p&gt;This article goes over how I did this and fixed a weird OS-related error I got when trying to install the &lt;code&gt;mysql&lt;/code&gt; gem.&lt;/p&gt;

&lt;h1&gt;
  
  
  Install MySQL on your Mac (with homebrew)
&lt;/h1&gt;

&lt;p&gt;If you use homebrew for package management, you can install MySQL by using the following command on the command line:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;After it finishes installing, make sure you go over the instructions that homebrew gives you:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;We've installed your MySQL database without a root password. To secure it run:
    mysql_secure_installation

MySQL is configured to only allow connections from localhost by default

To connect run:
    mysql -uroot

To have launchd start mysql now and restart at login:
  brew services start mysql
Or, if you don't want/need a background service you can just run:
  mysql.server start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can set up a password with the &lt;code&gt;mysql_secure_installation&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;You can start up MySQL right away with the &lt;code&gt;brew services start mysql&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;Next, let's set up Rails to use MySQL!&lt;/p&gt;

&lt;h1&gt;
  
  
  Use MySQL with a brand new Rails app
&lt;/h1&gt;

&lt;p&gt;If you haven't created your application yet, you can run the &lt;code&gt;rails new&lt;/code&gt; command with a flag that configures your database to use MySQL instead of the default Sqlite:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails new appname -d mysql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That will set up the Gemfile to use the &lt;code&gt;mysql2&lt;/code&gt; gem and make a &lt;code&gt;config/database.yml&lt;/code&gt; with some default MySQL configurations.&lt;/p&gt;

&lt;h1&gt;
  
  
  Switching databases in an existing Rails 6 application
&lt;/h1&gt;

&lt;p&gt;Rails 6 adds the handy &lt;code&gt;rails db:system:change&lt;/code&gt; command that will automatically create the code needed to switch databases, which involves editing the &lt;code&gt;config/database.yml&lt;/code&gt; file and adding the &lt;code&gt;mysql2&lt;/code&gt; gem to the &lt;code&gt;Gemfile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Use the following command from within your Rails application directory (you can also change to other databases, too. See [here](&lt;a href="https://gorails.com/episodes/rails-6-db-system-change-command%5D:" rel="noopener noreferrer"&gt;https://gorails.com/episodes/rails-6-db-system-change-command]:&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails db:system:change --to=mysql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will ask you if you want to overwrite the &lt;code&gt;config/database.yml&lt;/code&gt; file. Type &lt;code&gt;y&lt;/code&gt; and press enter and you'll see that Rails has updated the following files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;force  config/database.yml
 gsub  Gemfile
 gsub  Gemfile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This adds the &lt;code&gt;mysql&lt;/code&gt; gem to the Gemfile. Before installing it, open up the Gemfile, look for the line that starts with &lt;code&gt;gem mysql&lt;/code&gt;, and check which version of the gem it's using. It may be an older version, so you can check the &lt;a href="https://rubygems.org/gems/mysql2/" rel="noopener noreferrer"&gt;Ruby Gems directory&lt;/a&gt; for the newest version and use that instead if you like.&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;bundle install&lt;/code&gt; to install the &lt;code&gt;mysql2&lt;/code&gt; gem. If everything goes well, all you need to do is create the database (skip down to the "Create the database" section below). I ran into an error, which I'll discuss below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Manually configure Rails for MySQL
&lt;/h2&gt;

&lt;p&gt;To manually set up MySQL, first, remove the &lt;code&gt;gem sqlite3&lt;/code&gt; line from the Gemfile and add &lt;code&gt;gem mysql2&lt;/code&gt; in its place.&lt;/p&gt;

&lt;p&gt;Configure the &lt;code&gt;config/database.yml&lt;/code&gt; like below. These are just basic configurations provided by Rails (some comments cut out to save space), but adjust as needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# config/database.yml&lt;/span&gt;

&lt;span class="c1"&gt;# MySQL. Versions 5.5.8 and up are supported.&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# Install the MySQL driver&lt;/span&gt;
&lt;span class="c1"&gt;#   gem install mysql2&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# Ensure the MySQL gem is defined in your Gemfile&lt;/span&gt;
&lt;span class="c1"&gt;#   gem 'mysql2'&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# And be sure to use new-style password hashing:&lt;/span&gt;
&lt;span class="c1"&gt;#   https://dev.mysql.com/doc/refman/5.7/en/password-hashing.html&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nl"&gt;&amp;amp;default&lt;/span&gt;
  &lt;span class="na"&gt;adapter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql2&lt;/span&gt;
  &lt;span class="na"&gt;encoding&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;utf8mb4&lt;/span&gt;
  &lt;span class="na"&gt;pool&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %&amp;gt;&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;socket&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/tmp/mysql.sock&lt;/span&gt;

&lt;span class="na"&gt;development&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*default&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;myapp_development&lt;/span&gt;

&lt;span class="c1"&gt;# Warning: The database defined as "test" will be erased and&lt;/span&gt;
&lt;span class="c1"&gt;# re-generated from your development database when you run "rake".&lt;/span&gt;
&lt;span class="c1"&gt;# Do not set this db to the same as development or production.&lt;/span&gt;
&lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*default&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;myapp_test&lt;/span&gt;

&lt;span class="na"&gt;production&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*default&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;myapp_production&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;myapp&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= ENV['PACHISLO_DATABASE_PASSWORD'] %&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Error when installing the mysql2 gem
&lt;/h1&gt;

&lt;p&gt;When trying to install the &lt;code&gt;mysql&lt;/code&gt; gem, I got a crazy long error like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ERROR:  Error installing mysql2:
    ERROR: Failed to build gem native extension.

    current directory: /Users/morinoko/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/mysql2-0.5.2/ext/mysql2
/Users/morinoko/.rbenv/versions/2.6.3/bin/ruby -I /Users/morinoko/.rbenv/versions/2.6.3/lib/ruby/2.6.0 -r ./siteconf20190926-66829-1k4yip5.rb extconf.rb
checking for rb_absint_size()... yes
checking for rb_absint_singlebit_p()... yes
checking for rb_wait_for_single_fd()... yes
-----
Using mysql_config at /usr/local/bin/mysql_config
-----
checking for mysql.h... yes
checking for errmsg.h... yes
checking for SSL_MODE_DISABLED in mysql.h... yes
checking for SSL_MODE_PREFERRED in mysql.h... yes
checking for SSL_MODE_REQUIRED in mysql.h... yes
checking for SSL_MODE_VERIFY_CA in mysql.h... yes
checking for SSL_MODE_VERIFY_IDENTITY in mysql.h... yes
checking for MYSQL.net.vio in mysql.h... yes
checking for MYSQL.net.pvio in mysql.h... no
checking for MYSQL_ENABLE_CLEARTEXT_PLUGIN in mysql.h... yes
checking for SERVER_QUERY_NO_GOOD_INDEX_USED in mysql.h... yes
checking for SERVER_QUERY_NO_INDEX_USED in mysql.h... yes
checking for SERVER_QUERY_WAS_SLOW in mysql.h... yes
checking for MYSQL_OPTION_MULTI_STATEMENTS_ON in mysql.h... yes
checking for MYSQL_OPTION_MULTI_STATEMENTS_OFF in mysql.h... yes
checking for my_bool in mysql.h... no
-----
Don't know how to set rpath on your system, if MySQL libraries are not in path mysql2 may not load
-----
-----
Setting libpath to /usr/local/Cellar/mysql/8.0.17_1/lib
-----
creating Makefile

current directory: /Users/morinoko/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/mysql2-0.5.2/ext/mysql2
make "DESTDIR=" clean

current directory: /Users/morinoko/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/mysql2-0.5.2/ext/mysql2
make "DESTDIR="
compiling client.c
compiling infile.c
compiling mysql2_ext.c
compiling result.c
compiling statement.c
linking shared-object mysql2/mysql2.bundle
ld: library not found for -lssl
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [mysql2.bundle] Error 1

make failed, exit code 2

Gem files will remain installed in /Users/morinoko/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/mysql2-0.5.2 for inspection.
Results logged to /Users/morinoko/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/extensions/x86_64-darwin-18/2.6.0-static/mysql2-0.5.2/gem_make.out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After some googling, it seems like this error sometimes shows up if you don't have command-line tools installed (or it got removed when upgrading the mac OS).&lt;/p&gt;

&lt;p&gt;Try to install them with:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;If it installs, that may have fixed your problem. Run &lt;code&gt;bundle install&lt;/code&gt; again and it should work.&lt;/p&gt;

&lt;p&gt;For me, however, I got a notice telling me that the command line tools were already installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;xcode-select: error: command line tools are already installed, use "Software Update" to install updates
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To fix this, run the installer with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo open /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo installer -pkg /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg -target /
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(I used the first command)&lt;/p&gt;

&lt;p&gt;It turns out that this headers package was not included (missing?) in the newest version of Xcode, so the above command allows you to install it manually.&lt;/p&gt;

&lt;p&gt;Now try running &lt;code&gt;bundle install&lt;/code&gt; again and hopefully it will work (if not, you'll have to keep googling)!&lt;/p&gt;

&lt;h1&gt;
  
  
  Create the database
&lt;/h1&gt;

&lt;p&gt;You will have to create the database from scratch and re-run any migrations if you had some already.&lt;/p&gt;

&lt;p&gt;First, since Rails overwrote the &lt;code&gt;config/database.yml&lt;/code&gt; file, make sure you open it up and make any necessary changes like editing the database names.&lt;/p&gt;

&lt;p&gt;When everything is configured correctly, create the database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create the database
rails db:create

#=&amp;gt; Created database 'mydatabase_development'
#=&amp;gt; Created database 'mydatabase_pachislo_test'

# Run migrations
rails db:migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you should be able to boot up your application with &lt;code&gt;rails server&lt;/code&gt;!&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://rubygems.org/gems/mysql2/" rel="noopener noreferrer"&gt;mysql2 Ruby Gems page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://gorails.com/episodes/rails-6-db-system-change-command" rel="noopener noreferrer"&gt;Article &amp;amp; video&lt;/a&gt; on the Rails 6's new &lt;code&gt;rails db:system:change&lt;/code&gt; command&lt;/li&gt;
&lt;li&gt;Ruby on Rails Guides: &lt;a href="https://guides.rubyonrails.org/configuring.html#configuring-a-mysql-or-mariadb-database" rel="noopener noreferrer"&gt;Configuring a MySQL or MariaDB Database&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://qiita.com/gonzaemon111/items/ea181ba3ff582a124213" rel="noopener noreferrer"&gt;Japanese article on how to fix macOS-related problem&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rails</category>
      <category>mysql</category>
    </item>
    <item>
      <title>Adding Custom JavaScript in Rails 6</title>
      <dc:creator>Felice Forby</dc:creator>
      <pubDate>Wed, 21 Aug 2019 09:38:53 +0000</pubDate>
      <link>https://forem.com/morinoko/adding-custom-javascript-in-rails-6-1ke6</link>
      <guid>https://forem.com/morinoko/adding-custom-javascript-in-rails-6-1ke6</guid>
      <description>&lt;p&gt;In Rails 6, JavaScript assets are no longer included with the &lt;code&gt;app/assets/&lt;/code&gt; directory and instead have been moved into a separate directory &lt;code&gt;app/javascript&lt;/code&gt; handled by Webpacker. That's great, but when I wanted to add some custom javascript of my own, there wasn't any clear documentation that described how it should be done.&lt;/p&gt;

&lt;p&gt;After some experimentation and digging around on the internet, here are a couple of methods that seem to work. Note that I'm not a javascript expert by any means, so if there is a better way—or other ways that I'm missing—let me know in the comments!&lt;/p&gt;

&lt;h1&gt;
  
  
  Method 1: Create a custom directory and require it in &lt;code&gt;application.js&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;If you look at &lt;code&gt;application.js&lt;/code&gt;, the comment at the top suggests that you "place your actual application logic in a relevant structure within app/javascript and only use these pack files to reference that code so it'll be compiled."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/javascript/packs/application.js&lt;/span&gt;

&lt;span class="c1"&gt;// This file is automatically compiled by Webpack, along with any other files&lt;/span&gt;
&lt;span class="c1"&gt;// present in this directory. You're encouraged to place your actual application logic in&lt;/span&gt;
&lt;span class="c1"&gt;// a relevant structure within app/javascript and only use these pack files to reference&lt;/span&gt;
&lt;span class="c1"&gt;// that code so it'll be compiled.&lt;/span&gt;

&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@rails/ujs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turbolinks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@rails/activestorage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;channels&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can set this up by adding a custom directory within the &lt;code&gt;app/javascript/&lt;/code&gt;, e.g. &lt;code&gt;custom/&lt;/code&gt;, and then require the files within in &lt;code&gt;application.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example, if you have a javascript file named &lt;code&gt;home.js&lt;/code&gt; in the &lt;code&gt;app/javascript/custom/&lt;/code&gt; directory, you can get it to load with &lt;code&gt;require()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/javascript/packs/application.js&lt;/span&gt;

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

&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@rails/ujs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turbolinks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@rails/activestorage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;channels&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;custom/home&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since it's required in &lt;code&gt;application.js&lt;/code&gt;, the custom javascript will be compiled along with all the other javascript into a timestamped &lt;code&gt;application.js&lt;/code&gt; file that looks something like &lt;code&gt;application-a03d1868c0a3f825e53e.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is loaded by the &lt;code&gt;&amp;lt;%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %&amp;gt;&lt;/code&gt; tag in the &lt;code&gt;app/views/layouts/application.html.erb&lt;/code&gt;, automatically created when you make a new Rails app.&lt;/p&gt;

&lt;p&gt;For a cleaner look, you could also name the javascript file &lt;code&gt;index.js&lt;/code&gt; and require it with a simple reference to the directory like &lt;code&gt;require("custom")&lt;/code&gt; because &lt;code&gt;require()&lt;/code&gt; looks for an &lt;code&gt;index.js&lt;/code&gt; file when given a path to a directory (if there is no &lt;code&gt;index.js&lt;/code&gt;, it will fail).&lt;/p&gt;

&lt;h1&gt;
  
  
  Method 2: Add custom JavaScipt within the &lt;code&gt;app/javascript/packs&lt;/code&gt; directory
&lt;/h1&gt;

&lt;p&gt;If for some reason you don't want to create another directory, you could opt to add custom javascript files within the &lt;code&gt;app/javascript/packs&lt;/code&gt; directory. Then, require the files in &lt;code&gt;application.js&lt;/code&gt; with &lt;code&gt;require()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example, if you have a file named &lt;code&gt;custom.js&lt;/code&gt; in &lt;code&gt;app/javascript/packs&lt;/code&gt;, require it like below and it will be compiled into the timestamped &lt;code&gt;application.js&lt;/code&gt; file with all the other javascript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/javascript/packs/application.js&lt;/span&gt;

&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@rails/ujs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turbolinks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@rails/activestorage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;channels&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;packs/custom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Method 3: Using &lt;code&gt;javascript_pack_tag&lt;/code&gt; for separate JavaScript files (packs)
&lt;/h1&gt;

&lt;p&gt;If you don't want your custom javascript to be compiled into the &lt;code&gt;application.js&lt;/code&gt; with everything else, you can get Rails to compile it into a separate file, or "pack."&lt;/p&gt;

&lt;p&gt;To do so, add a custom file within &lt;code&gt;app/javascript/packs&lt;/code&gt;, e.g. &lt;code&gt;custom.js&lt;/code&gt;, then use the &lt;code&gt;javascript_pack_tag&lt;/code&gt; helper where the file is needed in the views like so: &lt;code&gt;&amp;lt;%= javascript_pack_tag 'custom' %&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The custom javascript will be compiled &lt;em&gt;separately&lt;/em&gt; from the rest of the javascript into a timestamped &lt;code&gt;custom.js&lt;/code&gt; that looks something like this: &lt;code&gt;custom-a03d1756c0a3f825e53e.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here's how it might look if you added the custom javascript just before the ending &lt;code&gt;body&lt;/code&gt; tag in the &lt;code&gt;layouts/views/application.html.erb&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;My App&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;csrf_meta_tags&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;csp_meta_tag&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;stylesheet_link_tag&lt;/span&gt; &lt;span class="s1"&gt;'application'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;media: &lt;/span&gt;&lt;span class="s1"&gt;'all'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'data-turbolinks-track'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'reload'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;javascript_pack_tag&lt;/span&gt; &lt;span class="s1"&gt;'application'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'data-turbolinks-track'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'reload'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;body&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;controller_name&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;action_name&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="s1"&gt;'layouts/header'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;

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

    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="s1"&gt;'layouts/footer'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;

    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;javascript_pack_tag&lt;/span&gt; &lt;span class="s1"&gt;'custom'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>rails</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Dynamic method handling with #method_missing and #respond_to_missing? in Ruby and Rails</title>
      <dc:creator>Felice Forby</dc:creator>
      <pubDate>Fri, 09 Aug 2019 06:21:55 +0000</pubDate>
      <link>https://forem.com/morinoko/dynamic-method-handling-with-methodmissing-and-respondtomissing-in-ruby-and-rails-oac</link>
      <guid>https://forem.com/morinoko/dynamic-method-handling-with-methodmissing-and-respondtomissing-in-ruby-and-rails-oac</guid>
      <description>&lt;p&gt;I just finished reading "&lt;a href="https://www.manning.com/books/the-well-grounded-rubyist-third-edition" rel="noopener noreferrer"&gt;The Well-Grounded Rubyist&lt;/a&gt;" and finally learned about the mysterious &lt;code&gt;#method_missing&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;#method_missing&lt;/code&gt; gets called whenever an object receives a method call that it doesn't know how to handle. Maybe it was never defined, misspelled, or for some reason, ruby can't find it on the object's method look-up path.&lt;/p&gt;

&lt;p&gt;The cool thing is is that you can use &lt;code&gt;#method_missing&lt;/code&gt; to catch certain methods that you want to dynamically handle. Here's an example borrowed from "&lt;a href="https://www.manning.com/books/the-well-grounded-rubyist-third-edition" rel="noopener noreferrer"&gt;The Well-Grounded Rubyist&lt;/a&gt;":&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;Student&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;method_missing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_with?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"grade_for_"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"You got an A in &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&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="nf"&gt;last&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;capitalize&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!"&lt;/span&gt;
    &lt;span class="k"&gt;else&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;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code would allow you to dynamically any method like &lt;code&gt;grade_for_english&lt;/code&gt;, &lt;code&gt;grade_for_science&lt;/code&gt;, etc. called on Student objects without needing to explicitly define several similar methods for each subject.&lt;/p&gt;

&lt;p&gt;The name of the method that was called is always provided as a symbol through the &lt;code&gt;method&lt;/code&gt; argument, so you can use it accordingly within your redefined version. The &lt;code&gt;*args&lt;/code&gt; parameter grabs up any of the arguments that were passed along. It can also take an optional block, but I won't get into that here.&lt;/p&gt;

&lt;p&gt;Make sure you always include &lt;code&gt;super&lt;/code&gt; at the end of the redefined &lt;code&gt;#method_missing&lt;/code&gt; so that any methods that cannot actually be handled in the end get passed back to the original definition of &lt;code&gt;#method_missing&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Thinking about my personal projects, I realized that &lt;code&gt;#method_missing&lt;/code&gt; would finally let me solve one of the problems that had been bugging me for a while, so I'll use that as a real-world albeit simple example to illustrate how I used &lt;code&gt;#method_missing&lt;/code&gt; to refactor my code.&lt;/p&gt;

&lt;h1&gt;
  
  
  Background &amp;amp; Original Code
&lt;/h1&gt;

&lt;p&gt;I have a basic web app for a farmer that sells organic vegetables as a boxed set, kind of like a CSA but on a one-time basis instead of a seasonal one. Anyway, the site is available in both English and Japanese so the data for objects needs to be stored in both languages. In this case, I have a class called &lt;code&gt;VeggieBox&lt;/code&gt; that keeps track of the seasonal veggie boxes.  &lt;/p&gt;

&lt;p&gt;I set up the app so that it pulls out the data from the database depending on the page's locale (&lt;code&gt;:en&lt;/code&gt; or &lt;code&gt;:ja&lt;/code&gt;). This enables me to share a single view file between the languages instead of separate views for each language.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;VeggieBox&lt;/code&gt; class makes objects with a title and description. To handle the different languages, the attributes are stored as &lt;code&gt;title_ja&lt;/code&gt;, &lt;code&gt;title_en&lt;/code&gt;, &lt;code&gt;description_ja&lt;/code&gt;, and &lt;code&gt;description_en&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's create a sample box now:&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="vi"&gt;@veggie_box&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;VeggieBox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="vi"&gt;@veggie_box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title_en&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Summer box"&lt;/span&gt;
&lt;span class="vi"&gt;@veggie_box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title_ja&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"夏のボックス"&lt;/span&gt;
&lt;span class="vi"&gt;@veggie_box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;description_en&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Tons of delicious summer veggies!!"&lt;/span&gt;
&lt;span class="vi"&gt;@veggie_box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;description_ja&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"美味しい夏野菜いっぱい！！"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because the view file is shared, I had to figure out how to display the correct data depending on whether the user was looking at the English or the Japanese site. To do so, I originally created &lt;code&gt;#localized_title&lt;/code&gt; and &lt;code&gt;#localized_description&lt;/code&gt; that used &lt;code&gt;#send&lt;/code&gt; to parse in the I18n locale and call the appropriate method:&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="c1"&gt;# app/models/veggie_box.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VeggieBox&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="c1"&gt;# ... other methods&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;localized_title&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;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"title_&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;I18n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locale&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&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;localized_description&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;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"description_&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;I18n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locale&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&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;Depending on which page the user views, the locale is set to either &lt;code&gt;en&lt;/code&gt; or &lt;code&gt;ja&lt;/code&gt;. So, if the user is on the English page, &lt;code&gt;@veggie_box.localized_title&lt;/code&gt; would be equivalent to saying &lt;code&gt;@veggie_box.title_en&lt;/code&gt; and pulling out the correct text in the view is as simple as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"description"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="vi"&gt;@veggie_box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;localized_title&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="vi"&gt;@veggie_box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;localized_description&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's a fairly simple solution, but not as flexible as it could be. What happens if I started adding more and more attributes to the &lt;code&gt;VeggieBox&lt;/code&gt; class? I would have to add a new &lt;code&gt;localize_***&lt;/code&gt; instance method for every single attribute!&lt;/p&gt;

&lt;p&gt;That's where &lt;code&gt;#method_missing&lt;/code&gt; comes in to save the day.&lt;/p&gt;

&lt;h1&gt;
  
  
  Refactor 1
&lt;/h1&gt;

&lt;p&gt;Instead of having to use methods that have &lt;code&gt;localized_&lt;/code&gt; attached to it, I decided to simplify it to the base attribute name so that I could just write &lt;code&gt;@veggie_box.title&lt;/code&gt; or &lt;code&gt;@veggie_box.description&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;My first attempt to use &lt;code&gt;#method_missing&lt;/code&gt; was something like this:&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="c1"&gt;# app/models/veggie_box.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VeggieBox&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="c1"&gt;# ... other methods&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;method_missing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"description"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;"title"&lt;/span&gt;
      &lt;span class="n"&gt;localized_method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;I18n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locale&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&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;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;localized_method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&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;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the app were to encounter something like &lt;code&gt;@veggie_box.title&lt;/code&gt;, it wouldn't immediately know what to do because the VeggieBox object is calling a method that isn't explicitly defined; in this case &lt;code&gt;title&lt;/code&gt;. It gets redirected to the &lt;code&gt;#method_missing&lt;/code&gt; method defined in the &lt;code&gt;VeggieBox&lt;/code&gt; class, which catches the unknown method &lt;code&gt;title&lt;/code&gt; in the if-clause &lt;code&gt;if method == "description" || "title"&lt;/code&gt;. Instead of throwing a NoMethodError, the call to &lt;code&gt;title&lt;/code&gt; gets processed into &lt;code&gt;title_en&lt;/code&gt; if the user was looking at the English page, or &lt;code&gt;title_ja&lt;/code&gt; if it was the Japanese page.&lt;/p&gt;

&lt;p&gt;We can try it out in the console:&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="no"&gt;I18n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:en&lt;/span&gt;
&lt;span class="vi"&gt;@veggie_box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt;
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Summer box"&lt;/span&gt;

&lt;span class="no"&gt;I18n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:ja&lt;/span&gt;
&lt;span class="vi"&gt;@veggie_box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt;
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"夏のボックス"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Slightly better, but the method names are still hard-coded into the &lt;code&gt;if&lt;/code&gt;-clause!&lt;/p&gt;

&lt;p&gt;My next refactor will get rid of the hard-coding in the &lt;code&gt;#method-missing&lt;/code&gt; definition.&lt;/p&gt;

&lt;h1&gt;
  
  
  Refactor 2
&lt;/h1&gt;

&lt;p&gt;To get rid of the hard-coded values, I decided to transform the method name into the localized attribute method (e.g. &lt;code&gt;title_ja&lt;/code&gt;) by adding on the locale and then simply checking whether or not the veggie box object responds to that method. If so, the localized method is called on the object with send. If not, it gets sent to &lt;code&gt;super&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is the refactored 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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;method_missing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;localized_method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;I18n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locale&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&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;respond_to?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;localized_method&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;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;localized_method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;else&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if another locale-based attribute were to be added to the &lt;code&gt;VeggieBox&lt;/code&gt; class, &lt;code&gt;#method_missing&lt;/code&gt; will be able to handle it without editing the code.&lt;/p&gt;

&lt;p&gt;There is one slight problem that comes up when using &lt;code&gt;#method_missing&lt;/code&gt; though, which I'll solve in the final refactor.&lt;/p&gt;

&lt;h1&gt;
  
  
  Refactor 3
&lt;/h1&gt;

&lt;p&gt;Although &lt;code&gt;#method_missing&lt;/code&gt; will let your objects properly handle certain method calls dynamically, it doesn't allow them act like "real methods". That means ruby won't recognize them in other places, for example, when you use &lt;code&gt;object.respond_to?&lt;/code&gt;:&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="vi"&gt;@veggie_box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;respond_to?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;)&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="vi"&gt;@veggie_box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;respond_to?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:description&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;respond_to?&lt;/code&gt; returns &lt;code&gt;false&lt;/code&gt; for the methods handled by &lt;code&gt;#method_missing&lt;/code&gt;! Well, that's not right because it technically does respond to these methods even though they aren't defined.&lt;/p&gt;

&lt;p&gt;Things like &lt;code&gt;object.method&lt;/code&gt;, which let you turn methods into objects, won't work either:&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="vi"&gt;@veggie_box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;NameError&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;undefined&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="sb"&gt;`title' for class `&lt;/span&gt;&lt;span class="c1"&gt;#&amp;lt;Class:0x00007fc56289b2a8&amp;gt;')&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I realized this after checking the &lt;a href="https://rubystyle.guide/#no-method-missing" rel="noopener noreferrer"&gt;Ruby Style Guide's section on metaprogramming&lt;/a&gt; and &lt;a href="http://blog.marc-andre.ca/2010/11/15/methodmissing-politely/" rel="noopener noreferrer"&gt;this great article&lt;/a&gt;. They recommended also defining &lt;code&gt;#respond_to_missing?&lt;/code&gt; when using &lt;code&gt;#method_missing&lt;/code&gt;, which allows ruby to properly recognize that your objects do indeed respond to the meta-programmed methods. (Actually, the Ruby Style Guide recommends &lt;em&gt;not&lt;/em&gt; using &lt;code&gt;#method_missing&lt;/code&gt; at all... oops).&lt;/p&gt;

&lt;p&gt;Here's how I defined &lt;code&gt;#respond_to_missing?&lt;/code&gt; in my case:&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;respond_to_missing?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;localized_method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;I18n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locale&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="n"&gt;attribute_names&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;localized_method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;super&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, I used Rails' ActiveRecord method &lt;code&gt;#attribute_names&lt;/code&gt; to make sure the attributes were registered to the class. If so, it passes the &lt;code&gt;respond_to&lt;/code&gt; test.&lt;/p&gt;

&lt;p&gt;Each object would now return &lt;code&gt;true&lt;/code&gt; when asked if they respond to &lt;code&gt;#title&lt;/code&gt; or &lt;code&gt;#description&lt;/code&gt;.&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="vi"&gt;@veggie_box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;respond_to?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;

&lt;span class="vi"&gt;@veggie_box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;respond_to?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:description&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The methods can now also be objectified:&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="nb"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@veggie_box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="no"&gt;I18n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:en&lt;/span&gt;
&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Summer box"&lt;/span&gt;

&lt;span class="no"&gt;I18n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:ja&lt;/span&gt;
&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"夏のボックス"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Tests for Confidence
&lt;/h1&gt;

&lt;p&gt;Considering this was the first time I used &lt;code&gt;#method_missing&lt;/code&gt;, I wasn't 100% confident that the code would work correctly, so I added a test in the test suite (MiniTest) for the meta-programmed methods to give myself more confidence. Even if you are 100% confident, it would be a good idea to have a test anyway :)&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;assert_respond_to&lt;/code&gt; tests make sure that instances of veggie boxes actually respond to the meta-programmed methods. The subsequent &lt;code&gt;assert_equal&lt;/code&gt; tests first set the locale to &lt;code&gt;:en&lt;/code&gt; or &lt;code&gt;:ja&lt;/code&gt; and make sure the meta-programmed methods return the same values as the original attribute methods.&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="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'test_helper'&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VeggieBoxTest&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;TestCase&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;
    &lt;span class="c1"&gt;# sets up a test object from a fixture file&lt;/span&gt;
    &lt;span class="vi"&gt;@veggie_box&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;veggie_boxes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:box_one&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# ...other tests...&lt;/span&gt;

  &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="s2"&gt;"should respond correctly to localized methods"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# Make sure it actually responds to the meta-programmed methods&lt;/span&gt;
    &lt;span class="n"&gt;assert_respond_to&lt;/span&gt; &lt;span class="vi"&gt;@veggie_box&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:title&lt;/span&gt;
    &lt;span class="n"&gt;assert_respond_to&lt;/span&gt; &lt;span class="vi"&gt;@veggie_box&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:description&lt;/span&gt;

    &lt;span class="c1"&gt;# Make sure the method gets the correct values for each locale by &lt;/span&gt;
    &lt;span class="c1"&gt;# comparing to the original attributes&lt;/span&gt;
    &lt;span class="no"&gt;I18n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:ja&lt;/span&gt;
    &lt;span class="n"&gt;assert_equal&lt;/span&gt; &lt;span class="vi"&gt;@veggie_box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title_ja&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt;
    &lt;span class="n"&gt;assert_equal&lt;/span&gt; &lt;span class="vi"&gt;@veggie_box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;description_ja&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;description&lt;/span&gt;

    &lt;span class="no"&gt;I18n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:en&lt;/span&gt;
    &lt;span class="n"&gt;assert_equal&lt;/span&gt; &lt;span class="vi"&gt;@veggie_box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title_en&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt;
    &lt;span class="n"&gt;assert_equal&lt;/span&gt; &lt;span class="vi"&gt;@veggie_box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;description_en&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;description&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;Hope you enjoyed the article and if you haven't used &lt;code&gt;#method_missing&lt;/code&gt; before, hopefully this will help!&lt;/p&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;"&lt;a href="https://www.manning.com/books/the-well-grounded-rubyist-third-edition" rel="noopener noreferrer"&gt;The Well-Grounded Rubyist&lt;/a&gt;" by David A. Black and Joseph Leo III&lt;/li&gt;
&lt;li&gt;&lt;a href="https://rubystyle.guide/#no-method-missing" rel="noopener noreferrer"&gt;Ruby Style Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://blog.marc-andre.ca/2010/11/15/methodmissing-politely/" rel="noopener noreferrer"&gt;Method_missing, Politely&lt;/a&gt; blog article&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.ruby-lang.org/en/2.6.0/BasicObject.html#method-i-method_missing" rel="noopener noreferrer"&gt;Ruby Documentation on method_missing&lt;/a&gt; (English)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.ruby-lang.org/ja/latest/method/BasicObject/i/method_missing.html" rel="noopener noreferrer"&gt;Ruby Documentation on method_missing&lt;/a&gt; (Japanese - has a nice code example even if you can't read the explanation)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>metaprogramming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Useful Git Commands For Removing Accidentally Pushed or Committed Files</title>
      <dc:creator>Felice Forby</dc:creator>
      <pubDate>Mon, 22 Jul 2019 05:05:46 +0000</pubDate>
      <link>https://forem.com/morinoko/useful-git-commands-for-removing-accidentally-pushed-or-committed-files-2ld</link>
      <guid>https://forem.com/morinoko/useful-git-commands-for-removing-accidentally-pushed-or-committed-files-2ld</guid>
      <description>&lt;p&gt;I find myself needing to reset commits often because I committed a file I didn't want to or forgot to add something to a commit. Every once in a while, I also need to remove the file from the remote repository (but not locally) because I accidentally pushed it. I always forget the commands, so here they are for everyone's reference :) &lt;/p&gt;

&lt;h2&gt;
  
  
  Remove a file you already pushed to the git repository
&lt;/h2&gt;

&lt;p&gt;You can use the following command to delete a file from your git repo, for example, if you accidentally pushed it up or if you just don’t want it there any anymore.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--cached&lt;/span&gt; name_of_file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will not delete it locally, so it is safe on your computer if you want to keep it in there for reference without sharing on Git. To prevent it from being pushed to Git again, just add the file to your &lt;code&gt;.gitignore&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Of course, if you just don’t need the file any more at all, simply delete it from your system as well.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BUT!&lt;/strong&gt; If the file had sensitive data like passwords or secret keys, then you need to do a little bit more because the commits can still be found in the repository's history. &lt;/p&gt;

&lt;h2&gt;
  
  
  If the pushed file has sensitive data like passwords
&lt;/h2&gt;

&lt;p&gt;As noted by &lt;a href="https://dev.to/oscherler/comment/d9ao"&gt;Ölbaum's comment&lt;/a&gt; below (thanks!), the above method will not &lt;em&gt;completely&lt;/em&gt; remove the file from the commit history.&lt;/p&gt;

&lt;p&gt;To remove the sensitive file from your history as well, you can use an open-source tool called the &lt;a href="https://rtyley.github.io/bfg-repo-cleaner/" rel="noopener noreferrer"&gt;BFG Repo-Cleaner&lt;/a&gt; or use git's &lt;code&gt;git filter-branch&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;BFG Repo-Cleaner apparently makes it much easier and faster to get the job done compared to &lt;code&gt;filter-branch&lt;/code&gt;. It allows you to delete files or, alternatively, replace the passwords or keys within the file with the text &lt;code&gt;***REMOVED***&lt;/code&gt;. You can also remove huge files that you accidently pushed.&lt;/p&gt;

&lt;p&gt;I haven't used BFG myself, but check out &lt;a href="https://rtyley.github.io/bfg-repo-cleaner/" rel="noopener noreferrer"&gt;BFG Repo-Cleaner's documentation and download page&lt;/a&gt; to see how to use it. The instructions are pretty strait forward.&lt;/p&gt;

&lt;p&gt;To learn about the &lt;code&gt;git filter-branch&lt;/code&gt;, check out git's &lt;a href="https://help.github.com/en/articles/removing-sensitive-data-from-a-repository#using-filter-branch" rel="noopener noreferrer"&gt;Using filter-branch&lt;/a&gt; article on their help site and the &lt;a href="https://git-scm.com/docs/git-filter-branch" rel="noopener noreferrer"&gt;git filter-branch documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Remove a file you accidentally committed in your last commit (but haven’t pushed yet)
&lt;/h2&gt;

&lt;p&gt;I have a habit of committing everything with &lt;code&gt;git add .&lt;/code&gt; so sometimes I accidentally add files that I actually want to have in a separate commit.&lt;/p&gt;

&lt;p&gt;To remove certain files from a commit that hasn’t been pushed yet, first, undo the last commit with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git reset &lt;span class="nt"&gt;--soft&lt;/span&gt; HEAD^1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--cached&lt;/span&gt; &amp;lt;file-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to remove the file you don’t want to commit. This removes it from the commit and sets it back to an untracked file. You should be able to confirm by doing a quick git status.&lt;/p&gt;

&lt;p&gt;Now you can commit the other files as usual by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"my commit message"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The removed file or files can then be added into a separate commit!&lt;/p&gt;

</description>
      <category>git</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Handy Git Shortcuts (Aliases) and How to Set Them Up</title>
      <dc:creator>Felice Forby</dc:creator>
      <pubDate>Mon, 08 Jul 2019 02:55:44 +0000</pubDate>
      <link>https://forem.com/morinoko/handy-git-shortcuts-aliases-and-how-to-set-them-up-47g4</link>
      <guid>https://forem.com/morinoko/handy-git-shortcuts-aliases-and-how-to-set-them-up-47g4</guid>
      <description>&lt;p&gt;If you’re using git, these handy short codes will speed up your workflow. The following are the basic abbreviated git commands that are recommended on the git website. I'm always forgetting how to do this when I need to set up git on new computer so posting this as a reference.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;co&lt;/code&gt; for checkout&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;br&lt;/code&gt; for branch&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ci&lt;/code&gt; for commit&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;st&lt;/code&gt; for status&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to Set Up
&lt;/h2&gt;

&lt;p&gt;To set up an alias, you use the git config command with the --global tag so that it applies to all of your git repositories.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; alias.&amp;lt;YOUR CHOSEN SHORTCUT&amp;gt; &amp;lt;THE ORIGINAL GIT COMMAND&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So to set up the basic shortcuts I mentioned above, open your terminal and put in the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; alias.co checkout
git config &lt;span class="nt"&gt;--global&lt;/span&gt; alias.br branch
git config &lt;span class="nt"&gt;--global&lt;/span&gt; alias.ci commit
git config &lt;span class="nt"&gt;--global&lt;/span&gt; alias.st status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your all set to go! You can use &lt;code&gt;co&lt;/code&gt; in place of &lt;code&gt;checkout&lt;/code&gt; and so on. For example, for &lt;code&gt;git commit&lt;/code&gt;, you can now do something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git ci &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"add CSS styles"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See the official git documentation &lt;a href="https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

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