<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Hinchy</title>
    <description>The latest articles on DEV Community by Hinchy (@hinchy).</description>
    <link>https://dev.to/hinchy</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%2F263688%2F515932e6-100c-4c49-8f70-82e867459440.png</url>
      <title>DEV Community: Hinchy</title>
      <link>https://dev.to/hinchy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hinchy"/>
    <language>en</language>
    <item>
      <title>Setting up a CRUD app in Lucky</title>
      <dc:creator>Hinchy</dc:creator>
      <pubDate>Fri, 15 Jan 2021 04:21:55 +0000</pubDate>
      <link>https://dev.to/hinchy/setting-up-a-crud-app-in-lucky-jo1</link>
      <guid>https://dev.to/hinchy/setting-up-a-crud-app-in-lucky-jo1</guid>
      <description>&lt;p&gt;I primarily use Ruby on Rails at work, and Rails, like Ludo from The Labyrinth, is a large and &lt;em&gt;very&lt;/em&gt; helpful beast. Did you want to create a model and all of its CRUD routes at the same time? Type in &lt;code&gt;rails g scaffold Post title content&lt;/code&gt;, run a migration and you're there.&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%2Fq0o9q5cm9kreqw57dbxw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fq0o9q5cm9kreqw57dbxw.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the &lt;a href="https://www.luckyframework.org/" rel="noopener noreferrer"&gt;Lucky framework&lt;/a&gt;, your hand isn't held quite so much. Creating CRUD functionality touches several sections of the framework which are covered separately in the &lt;a href="https://www.luckyframework.org/guides/getting-started/why-lucky" rel="noopener noreferrer"&gt;docs&lt;/a&gt; - actions, pages, routes, and forms and so on - but as there aren't a squillion tutorials online (like there are for Rails) I found it a bit hard to grasp.&lt;/p&gt;

&lt;p&gt;As a result, I'm putting it all in a single guide to try and show how everything hangs together in a simple CRUD app.&lt;/p&gt;

&lt;p&gt;This guide won't get into the nitty gritty of Crystal or Lucky, nor is it exhaustive. Rather it's a way to draw parallels between Rails and Lucky through a commonly built, minimal feature (CRUD for a resource) in a way that would have helped &lt;em&gt;me&lt;/em&gt; to learn Lucky coming from Rails.&lt;/p&gt;

&lt;p&gt;The repo for this demonstration &lt;code&gt;tipapp&lt;/code&gt; project can be found &lt;a href="https://github.com/jfhinchcliffe/tipapp" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What The CRUD?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Create,_read,_update_and_delete" rel="noopener noreferrer"&gt;CRUD&lt;/a&gt; stands for Create, Read, Update and Delete. These are common actions that you may want to perform on a resource in an application.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are we doing to do?
&lt;/h2&gt;

&lt;p&gt;We're going to create a basic Lucky app which saves coding tips.&lt;/p&gt;

&lt;p&gt;At work I pair a lot and I often see a colleague do something cool with their editor that I have no idea how to do. I ask them how to do it, they tell me, I nod, and the information promptly falls out of my ears. With this app, I'll never forget a handy tip again!&lt;/p&gt;

&lt;h2&gt;
  
  
  Before we start...
&lt;/h2&gt;

&lt;p&gt;Make sure you have Crystal and Lucky installed. The official guide can be found &lt;a href="https://www.luckyframework.org/guides/getting-started/installing" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you go to a terminal, typing the commands &lt;code&gt;lucky -v&lt;/code&gt;, &lt;code&gt;crystal -v&lt;/code&gt;, &lt;code&gt;psql --version&lt;/code&gt;, &lt;code&gt;node -v&lt;/code&gt; and &lt;code&gt;yarn -v&lt;/code&gt; should return the version of Lucky, Crystal, Postgres, Node and Yarn you have installed respectively. If they don't error, you should be ready to roll.&lt;/p&gt;

&lt;h3&gt;
  
  
  Note
&lt;/h3&gt;

&lt;p&gt;I've got my &lt;code&gt;psql&lt;/code&gt; database running locally in Docker on port &lt;code&gt;5432&lt;/code&gt;. See the &lt;a href="https://github.com/jfhinchcliffe/tipapp/blob/main/docker-compose.yml" rel="noopener noreferrer"&gt;docker-compose.yml&lt;/a&gt; file on the example repo for an example if you don't want to install Postgres locally. If you &lt;em&gt;do&lt;/em&gt; have Postgres running locally... ignore this note and continue living your life.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 - Create a new Lucky app 🌱
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Related Documentation - &lt;a href="https://www.luckyframework.org/guides/getting-started/starting-project" rel="noopener noreferrer"&gt;Starting a Lucky Project&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In your terminal, type &lt;code&gt;lucky init&lt;/code&gt; and you'll be taken through the setup of a new Lucky app.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enter the name of your project - I'm calling it &lt;code&gt;tipapp&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Choose whether you'd like it to be a 'full' app, or 'API Only' - Select &lt;code&gt;full&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Choose whether you'd like authentication generated for you - Select &lt;code&gt;y&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The app should be generated for you.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run &lt;code&gt;cd tipapp&lt;/code&gt; to navigate into your shiny new Lucky app.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;script/setup&lt;/code&gt; to install all JS dependencies, Crystal shards, setup the DB and perform various other little machinations for your new project (&lt;em&gt;warning&lt;/em&gt;: this may take a little while)&lt;/li&gt;
&lt;li&gt;After setup is complete, run &lt;code&gt;lucky dev&lt;/code&gt; and wait while your app shakes the dust from its shoulders and shambles on over to &lt;code&gt;http://localhost:3001&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 2 - Create the Tip Resource 🏭
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Related Documentation - &lt;a href="https://www.luckyframework.org/guides/database/models" rel="noopener noreferrer"&gt;Database Models&lt;/a&gt;, &lt;a href="https://www.luckyframework.org/guides/database/migrations" rel="noopener noreferrer"&gt;Migrating Data&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We need something to CRUD, so let's add the &lt;code&gt;Tip&lt;/code&gt; model.&lt;br&gt;
Much like Rails, we get a generator with Lucky which we can use to create a model. Our &lt;code&gt;Tip&lt;/code&gt; model will have the following properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;category&lt;/code&gt; - eg Bash, SQL, Ruby&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;description&lt;/code&gt; - a detailed writeup of the tip&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;user_id&lt;/code&gt; - the ID of the User who created this Tip&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can generate this model and a few other required files (query, migration etc.) with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="n"&gt;lucky&lt;/span&gt; &lt;span class="n"&gt;gen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;model&lt;/span&gt; &lt;span class="no"&gt;Tip&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="ss"&gt;:String&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="ss"&gt;:String&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="ss"&gt;:Int64&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Review your migration file (eg &lt;code&gt;tipapp/db/migrations/20210114223610_create_tips.cr&lt;/code&gt;) to confirm the fields are correct, and then to put the new table in the database, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="n"&gt;lucky&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;migrate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All things going well, you'll now have a &lt;code&gt;tips&lt;/code&gt; table in your database.&lt;/p&gt;

&lt;p&gt;To create the &lt;a href="https://www.luckyframework.org/guides/database/models#model-associations" rel="noopener noreferrer"&gt;association&lt;/a&gt; between the &lt;code&gt;User&lt;/code&gt; and the &lt;code&gt;Tip&lt;/code&gt;, add the following to your &lt;code&gt;tipapp/src/models/user.cr&lt;/code&gt; file within the table block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="n"&gt;tips&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Tip&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and within your &lt;code&gt;Tip&lt;/code&gt; file at &lt;code&gt;tipapp/src/models/tip.cr&lt;/code&gt;, inside the table block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now our app knows that a &lt;code&gt;Tip&lt;/code&gt; belongs to a &lt;code&gt;User&lt;/code&gt;, and a &lt;code&gt;User&lt;/code&gt; can have many &lt;code&gt;Tips&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 - Seed Some Data! 🐿️
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Related Documentation - &lt;a href="https://luckyframework.org/guides/database/database-setup#seeding-data" rel="noopener noreferrer"&gt;Seeding Data&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We want to seed &lt;code&gt;User&lt;/code&gt; and &lt;code&gt;Tip&lt;/code&gt; information to the database, so first, create a &lt;code&gt;SaveUser&lt;/code&gt; operation with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# tipapp/src/operations/save_user.cr&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SaveUser&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;SaveOperation&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 will allow us to save a &lt;code&gt;User&lt;/code&gt; from our seed file.&lt;/p&gt;

&lt;p&gt;Replace the &lt;code&gt;call&lt;/code&gt; method in your seeds file with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# tipapp/tasks/create_sample_seeds.cr&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;
    &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="no"&gt;UserQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"test-account@test.com"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;first?&lt;/span&gt;
      &lt;span class="no"&gt;SaveUser&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;email: &lt;/span&gt;&lt;span class="s2"&gt;"test-account@test.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;encrypted_password: &lt;/span&gt;&lt;span class="no"&gt;Authentic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_encrypted_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="no"&gt;SaveTip&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;user_id: &lt;/span&gt;&lt;span class="no"&gt;UserQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"test-account@test.com"&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="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;category: &lt;/span&gt;&lt;span class="s2"&gt;"git"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;description: &lt;/span&gt;&lt;span class="s2"&gt;"`git log --oneline` will display a lost of recent commit subjects, without the body"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="no"&gt;SaveTip&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;user_id: &lt;/span&gt;&lt;span class="no"&gt;UserQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"test-account@test.com"&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="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;category: &lt;/span&gt;&lt;span class="s2"&gt;"vscode"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;description: &lt;/span&gt;&lt;span class="s2"&gt;"`command + alt + arrow` will toggle between VS Code terminal windows"&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;"Done adding sample data"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and run &lt;code&gt;lucky db.create_sample_seeds&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Congratulations! That was a big step, but now you should have an app with authentication, a &lt;code&gt;User&lt;/code&gt;, some &lt;code&gt;Tips&lt;/code&gt; and the required associations between them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4.1 - The 'R' in CRUD - Creating an Index Page for all Tips 📝
&lt;/h2&gt;

&lt;p&gt;Lucky uses Actions to route requests to their appropriate pages. To create an action for &lt;code&gt;Tips::Index&lt;/code&gt;, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="n"&gt;lucky&lt;/span&gt; &lt;span class="n"&gt;gen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;browser&lt;/span&gt; &lt;span class="no"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Index&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And head to &lt;code&gt;http://localhost:3001/tips&lt;/code&gt; to see the plaintext output of this file.&lt;/p&gt;

&lt;p&gt;We want to render something a little more interesting than plaintext, so edit the &lt;code&gt;Tips::Index&lt;/code&gt; action to point at a yet-to-be-created page called &lt;code&gt;Tips::IndexPage&lt;/code&gt;, along with all of the current_user's tips:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="c1"&gt;# tipapp/src/actions/tips/index.cr&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Index&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;BrowserAction&lt;/span&gt;
    &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"/tips"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="no"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;IndexPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;tips: &lt;/span&gt;&lt;span class="no"&gt;UserQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preload_tips&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;current_user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;tips&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;You should be getting type errors letting you know that we have no &lt;code&gt;Tips::IndexPage&lt;/code&gt;, so let's create it in the pages directory at &lt;code&gt;tipapp/src/pages/tips/index_page.cr&lt;/code&gt;. We'll render a simple table which iterates over the tips using the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="c1"&gt;# tipapp/src/pages/tips/index_page.cr&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;IndexPage&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;MainLayout&lt;/span&gt;
  &lt;span class="n"&gt;needs&lt;/span&gt; &lt;span class="n"&gt;tips&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Tip&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;content&lt;/span&gt;
    &lt;span class="n"&gt;h1&lt;/span&gt; &lt;span class="s2"&gt;"Tips"&lt;/span&gt;
    &lt;span class="n"&gt;table&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;tr&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;th&lt;/span&gt; &lt;span class="s2"&gt;"ID"&lt;/span&gt;
        &lt;span class="n"&gt;th&lt;/span&gt; &lt;span class="s2"&gt;"Category"&lt;/span&gt;
        &lt;span class="n"&gt;th&lt;/span&gt; &lt;span class="s2"&gt;"Description"&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="n"&gt;tips&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;tip&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
        &lt;span class="n"&gt;tr&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
          &lt;span class="n"&gt;td&lt;/span&gt; &lt;span class="n"&gt;tip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;
          &lt;span class="n"&gt;td&lt;/span&gt; &lt;span class="n"&gt;tip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;category&lt;/span&gt;
          &lt;span class="n"&gt;td&lt;/span&gt; &lt;span class="n"&gt;tip&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;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;Check out &lt;code&gt;http://localhost:3001/tips&lt;/code&gt; to see your current_user's tips.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4.2 - The 'R' in CRUD - Creating a Show page for a Tip 🖼️
&lt;/h2&gt;

&lt;p&gt;This step will be pretty similar to the Index page. To create an action for the &lt;code&gt;Tips&lt;/code&gt; show page, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="n"&gt;lucky&lt;/span&gt; &lt;span class="n"&gt;gen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;browser&lt;/span&gt; &lt;span class="no"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Show&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And update the generated file to point at a &lt;code&gt;Tips::Show&lt;/code&gt; page, using the &lt;code&gt;:tip_id&lt;/code&gt; as param to find the relevant &lt;code&gt;Tip&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="c1"&gt;# tipapp/src/actions/tips/show.cr&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Show&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;BrowserAction&lt;/span&gt;
  &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"/tips/:tipid"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="no"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ShowPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;tip: &lt;/span&gt;&lt;span class="no"&gt;TipQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&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;tipid&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;Next, create the &lt;code&gt;Tips::Show&lt;/code&gt; page and add the following code to show the &lt;code&gt;Tip&lt;/code&gt; information:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="c1"&gt;# tipapp/src/pages/tips/show_page.cr&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ShowPage&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;MainLayout&lt;/span&gt;
  &lt;span class="n"&gt;needs&lt;/span&gt; &lt;span class="n"&gt;tip&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Tip&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;content&lt;/span&gt;
    &lt;span class="n"&gt;h1&lt;/span&gt; &lt;span class="s2"&gt;"Tip #&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;tip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

    &lt;span class="n"&gt;para&lt;/span&gt; &lt;span class="s2"&gt;"Category: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;tip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;category&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;para&lt;/span&gt; &lt;span class="s2"&gt;"Description &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;tip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;description&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;p&gt;Visit the &lt;code&gt;tips&lt;/code&gt; path with the ID of a Tip - eg. &lt;code&gt;http://localhost:3001/tips/2&lt;/code&gt; and voila! A beautiful show page. Clearly, design is my passion.&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%2Fzbsr3dkv1309ftmf88kv.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%2Fzbsr3dkv1309ftmf88kv.png" alt="show Tip page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5 - The 'C' in CRUD - Creating a Tip 🧱
&lt;/h2&gt;

&lt;p&gt;Now things are getting interesting! We want to be able to create a new &lt;code&gt;Tip&lt;/code&gt; by entering the information into a form at &lt;code&gt;http://localhost:3001/tips/new&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;First, we need an Action that will handle that route:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="n"&gt;lucky&lt;/span&gt; &lt;span class="n"&gt;gen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;browser&lt;/span&gt; &lt;span class="no"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;New&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in that action, we want to create a new instance of &lt;code&gt;SaveTip&lt;/code&gt; and pass it to the &lt;code&gt;Tips::NewPage&lt;/code&gt; as &lt;code&gt;operation&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="c1"&gt;# tipapp/src/actions/tips/new.cr&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;New&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;BrowserAction&lt;/span&gt;
    &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"/tips/new"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="no"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;NewPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;operation: &lt;/span&gt;&lt;span class="no"&gt;SaveTip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;Tips::NewPage&lt;/code&gt; page should construct a form for the &lt;code&gt;Tip&lt;/code&gt; like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="c1"&gt;# tipapp/src/pages/tips/new_page.cr&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;NewPage&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;MainLayout&lt;/span&gt;
    &lt;span class="n"&gt;needs&lt;/span&gt; &lt;span class="n"&gt;operation&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;SaveTip&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;content&lt;/span&gt;
      &lt;span class="n"&gt;h1&lt;/span&gt; &lt;span class="s2"&gt;"Create New Tip"&lt;/span&gt;

      &lt;span class="n"&gt;form_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Tip&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;label_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Category"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;text_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;attrs: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:required&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;label_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Description"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;text_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;attrs: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:required&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;submit&lt;/span&gt; &lt;span class="s2"&gt;"Create Tip"&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;And just for something different, we need to permit the &lt;code&gt;category&lt;/code&gt; and &lt;code&gt;description&lt;/code&gt; params in the SaveTip Operation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# tipapp/src/operations/save_tip.cr&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SaveTip&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Tip&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;SaveOperation&lt;/span&gt;
    &lt;span class="n"&gt;permit_columns&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whew! Done! Now navigate to the &lt;code&gt;http://localhost:3001/tips/new&lt;/code&gt;, create your new tip and you should see it once you're redirected to the &lt;code&gt;http://localhost:3001/tips&lt;/code&gt; page! This app is going to make &lt;em&gt;billions!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Interlude - 🎶 Gettin' Linky wit' it 🎵
&lt;/h2&gt;

&lt;p&gt;With all these routes, the app is a bit of a pain to navigate around at the moment. Let's add a few links to make our lives a bit easier.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the &lt;code&gt;tipapp/src/pages/tips/index_page.cr&lt;/code&gt; file, create a link to the 'New Tip' page using &lt;code&gt;link "New Tip", to: Tips::New&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;In the &lt;code&gt;tipapp/src/pages/tips/index_page.cr&lt;/code&gt; file, in the table of Tips, create a link to each Tip's show page using &lt;code&gt;link "New Tip", to: Tips::New&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;In the MainLayout page at &lt;code&gt;tipapp/src/pages/main_layout.cr&lt;/code&gt;, add a link to &lt;code&gt;Tips::Index&lt;/code&gt; after the &lt;code&gt;render_signed_in_user&lt;/code&gt; method so we can always get back to our Tips:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s2"&gt;"    |    "&lt;/span&gt;
&lt;span class="n"&gt;link&lt;/span&gt; &lt;span class="s2"&gt;"Tips Index Page"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="no"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Index&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now it certainly ain't pretty, but it's less of a hassle to navigate around the app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6 - The 'U' in CRUD - Updating a Tip 🎨
&lt;/h2&gt;

&lt;p&gt;Once again, generate an Action, this time we want the action to display the form of the &lt;code&gt;Tip&lt;/code&gt; we'd like to update:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="n"&gt;lucky&lt;/span&gt; &lt;span class="n"&gt;gen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;browser&lt;/span&gt; &lt;span class="no"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Edit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In that action, we want to get the ID of the &lt;code&gt;Tip&lt;/code&gt; we're editing, and return that as an argument to a &lt;code&gt;Tips::EditPage&lt;/code&gt; like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# tipapp/src/actions/tips/edit.cr&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Edit&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;BrowserAction&lt;/span&gt;
    &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"/tips/:tipid/edit"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;tip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;TipQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&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;tipid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tip&lt;/span&gt;
        &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="no"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;EditPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;tip: &lt;/span&gt;&lt;span class="n"&gt;tip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;operation: &lt;/span&gt;&lt;span class="no"&gt;SaveTip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="n"&gt;flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Tip with id &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;tipid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; not found"&lt;/span&gt;
        &lt;span class="n"&gt;redirect&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="no"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Index&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;While we're at it, we need to create an action for the route that we'll send the updated &lt;code&gt;Tip&lt;/code&gt; information to, so create yet &lt;em&gt;another&lt;/em&gt; action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="n"&gt;lucky&lt;/span&gt; &lt;span class="n"&gt;gen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;browser&lt;/span&gt; &lt;span class="no"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Update&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And use this action to update the &lt;code&gt;Tip&lt;/code&gt; or redirect back to the Edit page if we have errors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# tipapp/src/actions/tips/update.cr&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Update&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;BrowserAction&lt;/span&gt;
    &lt;span class="n"&gt;put&lt;/span&gt; &lt;span class="s2"&gt;"/tips/:tipid"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;tip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;TipQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&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;tipid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="no"&gt;SaveTip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tip&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="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;saved?&lt;/span&gt;
          &lt;span class="n"&gt;flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;success&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Tip with id &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;tipid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; updated"&lt;/span&gt;
          &lt;span class="n"&gt;redirect&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="no"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Index&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
          &lt;span class="n"&gt;flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Tip with id &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;tipid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; could not be saved"&lt;/span&gt;
          &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="no"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;EditPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;operation: &lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;tip: &lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;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;Finally, we need to create the &lt;code&gt;Tips::EditPage&lt;/code&gt; with a form for the Tip we're updating:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# tipapp/src/pages/tips/edit_page.cr&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;EditPage&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;MainLayout&lt;/span&gt;
    &lt;span class="n"&gt;needs&lt;/span&gt; &lt;span class="n"&gt;tip&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Tip&lt;/span&gt;
    &lt;span class="n"&gt;needs&lt;/span&gt; &lt;span class="n"&gt;operation&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;SaveTip&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;content&lt;/span&gt;
      &lt;span class="n"&gt;h1&lt;/span&gt; &lt;span class="s2"&gt;"Edit Tip"&lt;/span&gt;

      &lt;span class="n"&gt;form_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tip&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;label_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Category"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;text_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;attrs: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:required&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;label_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Description"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;text_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;attrs: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:required&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;submit&lt;/span&gt; &lt;span class="s2"&gt;"Update Tip"&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;So now put the ID of a Tip in your URL - eg &lt;code&gt;http://localhost:3001/tips/5/edit&lt;/code&gt; - and change the details to confirm you can update it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7 - The 'D' in CRUD - Deleting a Tip 💣
&lt;/h2&gt;

&lt;p&gt;The final step! And thankfully, a simple one. First, add a Delete action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="n"&gt;lucky&lt;/span&gt; &lt;span class="n"&gt;gen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;browser&lt;/span&gt; &lt;span class="no"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Delete&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And set up the action to destroy the Task based the ID passed in as a param:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# tipapp/src/actions/tips/delete.cr&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Delete&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;BrowserAction&lt;/span&gt;
    &lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="s2"&gt;"/tips/:tipid"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;tip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;TipQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&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;tipid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tip&lt;/span&gt;
        &lt;span class="n"&gt;tip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete&lt;/span&gt;
        &lt;span class="n"&gt;flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Tip with id &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;tipid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; deleted"&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="n"&gt;flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Tip with id &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;tipid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; not found"&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="n"&gt;redirect&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="no"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&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;And that's it for deletion! We'll confirm it's all working in the next section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 8 - Clean up and Confirm! 💅
&lt;/h2&gt;

&lt;p&gt;Our app, if the stars have aligned, should be up and working. We just need a few more little niceties before we can fully test it out.&lt;/p&gt;

&lt;p&gt;Firstly, on the &lt;code&gt;Tips::Index page&lt;/code&gt;, update the table to include links to the Show, Edit and Delete routes for each Tip:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="c1"&gt;# tipapp/src/pages/tips/index_page.cr&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;td&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;ul&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;li&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;link&lt;/span&gt; &lt;span class="s2"&gt;"Edit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="no"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Edit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="n"&gt;li&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;link&lt;/span&gt; &lt;span class="s2"&gt;"Show"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="no"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Show&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="n"&gt;li&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;link&lt;/span&gt; &lt;span class="s2"&gt;"Delete"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="no"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Delete&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And on the &lt;code&gt;Tips::Show&lt;/code&gt; page at, add the same links so that the &lt;code&gt;Tip&lt;/code&gt; can be updated or deleted from there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="c1"&gt;# tipapp/src/pages/tips/show_page.cr&lt;/span&gt;
&lt;span class="n"&gt;ul&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;li&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;link&lt;/span&gt; &lt;span class="s2"&gt;"Edit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="no"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Edit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="n"&gt;li&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;link&lt;/span&gt; &lt;span class="s2"&gt;"Show"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="no"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Show&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="n"&gt;li&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;link&lt;/span&gt; &lt;span class="s2"&gt;"Delete"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="no"&gt;Tips&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Delete&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="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;And that's it! Witness its magnificence!&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%2Fztbezoxez2dbeyu98nq2.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%2Fztbezoxez2dbeyu98nq2.png" alt="The finished product!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To confirm it's working, go to the index page and create, update, and delete some tips.&lt;/p&gt;

&lt;h2&gt;
  
  
  Denouement ⌛
&lt;/h2&gt;

&lt;p&gt;I'm thoroughly enjoying working with Lucky and Crystal. The addition of types is an incredible time-saver and the similarity to Ruby makes Crystal a pleasure to work with. With any luck the language will get a bit more popular and more guides like these will become available to get people up and running.&lt;/p&gt;

&lt;p&gt;Any feedback or things I've gotten wrong, please let me know.&lt;/p&gt;

</description>
      <category>lucky</category>
      <category>crystal</category>
      <category>crud</category>
    </item>
  </channel>
</rss>
