Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Guides: Quickstart - build a discussion forum
- #lucky
- ## First things first
- * If you want to follow along, install Lucky
- * Learn some Crystal from the official docs if you’re not already familiar
- You can also just read through this to see if Lucky looks interesting.
- ## What we’re building
- 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.
- ## Create a new Lucky application
- 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.
- Follow the install instructions that appear after the application is created and you should see the Lucky name and logo after running `lucky dev`
- > *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.
- ## Customizing the generated `User` model
- 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`.
- In our application, we also want to require people to set a username, and optionally add their full name.
- ### Add username and full name to the `User` model
- The generated `User` model can be customized by adding a few new columns with the `column` macro:
- ```crystal
- # in src/models/user.cr
- class User < BaseModel
- table :users do
- # These columns are in the generated file
- column email : String
- column encrypted_password : String
- # These are the new ones we’ll add
- column username : String
- column name : String?
- end
- end
- ```
- 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.
- ### Adding the new `User` columns to the migration
- 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`:
- ```crystal
- # in db/migrations/create_users_xxxxxx.cr
- class CreateUsers < LuckyMigrator::Migration
- table :users do
- # These columns are in the auto generated file
- add email : String, unique: true
- add encrypted_password : String
- # These are the new ones
- add username : String, unique: true
- add name : String?
- end
- end
- ```
- 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.
- When Lucky sees a migration with a type that ends with `?`, it will allow the column to have `null` values in the database.
- When the column type does *not* have a `?` Lucky will set the column to `NOT NULL` .
- > 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.
- ### Running the migration
- 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`.
- ## List all the topics
- Our forum will allow people to post multiple topics. First, let’s create a new `Topic` model and database table.
- ### Create topics table with LuckyMigrator
- First, run `lucky gen.migration CreateTopics` to generate a migration.
- The generator will create a default migration. Let’s modify it to create a topics table
- ```crystal
- class CreateTopics::V11111 < LuckyMigrator::Migration
- def migrate
- create :topics do
- add title : String
- add_belongs_to creator : User
- end
- end
- def rollback
- drop :topics
- end
- end
- ```
- > `create` will automatically add `id`, `created_at` and `updated_at`columns.
- 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.
- Now that the migration is written, run `lucky db.migrate` to run the migration and create the table.
- ### Create the `Topic` model
- 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:
- ```crystal
- # in src/models/topic.cr
- class Topic < BaseModel
- table :topics do
- column title : String
- belongs_to creator : User
- end
- end
- ```
- 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.
- ### Create an action for showing all topics
- 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:
- ```crystal
- class Topics::Index < BrowserAction
- action do
- render IndexPage, topics: TopicQuery.new
- end
- end
- ```
- The `action` macro will automatically create a route to this action. I’m this case, `/topics`.
- The `render` method will render the `IndexPage` and pass all the topics to it.
- > Link to more in-depth guides
- ### Create a page to list all topics
- Let’s create a new page with `lucky gen.page Topics::IndexPage`. We’ll edit it to render some topics:
- ```crystal
- class Topics::IndexPage < MainLayout
- needs topics : TopicQuery
- def content
- h1 “All Topics”
- ul do
- @topics.each do |topic|
- li topic.title
- end
- end
- end
- end
- ```
Add Comment
Please, Sign In to add comment