Guest User

Untitled

a guest
Jan 19th, 2019
353
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.03 KB | None | 0 0
  1. # Guides: Quickstart - build a discussion forum
  2. #lucky
  3.  
  4. ## First things first
  5.  
  6. * If you want to follow along, install Lucky
  7. * Learn some Crystal from the official docs if you’re not already familiar
  8.  
  9. You can also just read through this to see if Lucky looks interesting.
  10.  
  11. ## What we’re building
  12. We’ll be building an application that allows users to create new forums, start and comment in discussions, and upvote answers. It’ll also send email notifications and go over how to test the application. We’ll hit on most of what it takes to build an application in Lucky.
  13.  
  14. ## Create a new Lucky application
  15. Let’s call our new app “Chatter”. To create a new application, run `lucky init chatter` . This will create a new Lucky application with files and folders that will help you create server rendered HTML and JSON APIs.
  16.  
  17. Follow the install instructions that appear after the application is created and you should see the Lucky name and logo after running `lucky dev`
  18.  
  19. > *Want to build just an API with no front end?* Use the `—-api` option when creating the app. Check out the “building a JSON API” guide.
  20.  
  21. ## Customizing the generated `User` model
  22. Lucky generates files for signing in, signing up, and resetting your password. To do that, Lucky also generates a `User` model. By default it only has an `email`, and `encrypted_password`.
  23.  
  24. In our application, we also want to require people to set a username, and optionally add their full name.
  25.  
  26. ### Add username and full name to the `User` model
  27.  
  28. The generated `User` model can be customized by adding a few new columns with the `column` macro:
  29.  
  30. ```crystal
  31. # in src/models/user.cr
  32. class User < BaseModel
  33. table :users do
  34. # These columns are in the generated file
  35. column email : String
  36. column encrypted_password : String
  37. # These are the new ones we’ll add
  38. column username : String
  39. column name : String?
  40. end
  41. end
  42. ```
  43.  
  44. You’ll note that we add a `?` to the type for the user’s name. That tells Lucky that the `name` column might be `nil`. The `username` on the other hand does not have a `?` because it is a required field.
  45.  
  46. ### Adding the new `User` columns to the migration
  47.  
  48. Lucky uses “migrations” to manage tables, columns, and indices your app will need. Lucky generates a migration that creates the user table. Let’s modify it to add our new columns. You can find this migration in the `db/migrations folder`:
  49.  
  50. ```crystal
  51. # in db/migrations/create_users_xxxxxx.cr
  52. class CreateUsers < LuckyMigrator::Migration
  53. table :users do
  54. # These columns are in the auto generated file
  55. add email : String, unique: true
  56. add encrypted_password : String
  57. # These are the new ones
  58. add username : String, unique: true
  59. add name : String?
  60. end
  61. end
  62. ```
  63.  
  64. You’ll note that the migration definition is similar to the model. This is done to minimize the amount of syntax you need to learn.
  65.  
  66. When Lucky sees a migration with a type that ends with `?`, it will allow the column to have `null` values in the database.
  67.  
  68. When the column type does *not* have a `?` Lucky will set the column to `NOT NULL` .
  69.  
  70. > Lucky can do a lot. This guide will skip many of the options available in Lucky so that it’s easier to get going. Check out the migrations guide for an in-depth look at migrations and the available options.
  71.  
  72. ### Running the migration
  73.  
  74. When we create the app, Lucky runs all migrations when we run `bin/setup`. That means our users table was already created. Since we don’t have any records in the database, let’s rollback our migration and rerun it. his is such a common thing to do during development that we have a task that does this: `lucky db.redo`. This runs `lucky do.rollback` and `lucky db.migrate.one`.
  75.  
  76. ## List all the topics
  77. Our forum will allow people to post multiple topics. First, let’s create a new `Topic` model and database table.
  78.  
  79. ### Create topics table with LuckyMigrator
  80.  
  81. First, run `lucky gen.migration CreateTopics` to generate a migration.
  82.  
  83. The generator will create a default migration. Let’s modify it to create a topics table
  84.  
  85. ```crystal
  86. class CreateTopics::V11111 < LuckyMigrator::Migration
  87. def migrate
  88. create :topics do
  89. add title : String
  90. add_belongs_to creator : User
  91. end
  92. end
  93.  
  94. def rollback
  95. drop :topics
  96. end
  97. end
  98. ```
  99.  
  100. > `create` will automatically add `id`, `created_at` and `updated_at`columns.
  101.  
  102. Since we want our topics to be associated with the user that created them, we use `add_belongs_to`. We give the name of the relation (`creator`) and the type (`User`). Lucky will then create an indexed column called `creator_id` that has a foreign key to the`id` column on the `users` table.
  103.  
  104. Now that the migration is written, run `lucky db.migrate` to run the migration and create the table.
  105.  
  106. ### Create the `Topic` model
  107.  
  108. Let’s create our model with `lucky gen.model Topic`. This command will create 3 files: model, form, and query. For now we’ll focus on the model:
  109.  
  110. ```crystal
  111. # in src/models/topic.cr
  112. class Topic < BaseModel
  113. table :topics do
  114. column title : String
  115. belongs_to creator : User
  116. end
  117. end
  118. ```
  119.  
  120. You’ll notice that we use the same syntax in migrations as we do in the migration. This tells Lucky what column to use and what model type it should be.
  121.  
  122. ### Create an action for showing all topics
  123.  
  124. Let’s create an action with `lucky gen.action.browser Topics::Index`. This will create a bare bones `Topics::Index`. Let’s make it do something:
  125.  
  126. ```crystal
  127. class Topics::Index < BrowserAction
  128. action do
  129. render IndexPage, topics: TopicQuery.new
  130. end
  131. end
  132. ```
  133.  
  134. The `action` macro will automatically create a route to this action. I’m this case, `/topics`.
  135.  
  136. The `render` method will render the `IndexPage` and pass all the topics to it.
  137.  
  138. > Link to more in-depth guides
  139.  
  140. ### Create a page to list all topics
  141.  
  142. Let’s create a new page with `lucky gen.page Topics::IndexPage`. We’ll edit it to render some topics:
  143.  
  144. ```crystal
  145. class Topics::IndexPage < MainLayout
  146. needs topics : TopicQuery
  147.  
  148. def content
  149. h1 “All Topics”
  150. ul do
  151. @topics.each do |topic|
  152. li topic.title
  153. end
  154. end
  155. end
  156. end
  157. ```
Add Comment
Please, Sign In to add comment