Guides: Quickstart - build a discussion forum
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
Want to build just an API with no front end? Use the
—-apioption when creating the app. Check out the “building a JSON API” guide.
Customizing the generated
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
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 can be customized by adding a few new columns with the
# 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
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
# 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
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
lucky gen.migration CreateTopics to generate a migration.
The generator will create a default migration. Let’s modify it to create a topics table
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
createwill automatically add
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
Now that the migration is written, run
lucky db.migrate to run the migration and create the table.
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:
# 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:
class Topics::Index < BrowserAction action do render IndexPage, topics: TopicQuery.new end end
action macro will automatically create a route to this action. I’m this case,
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:
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