Skip to content

Commit

Permalink
Updating the tutorial with lots of little fixes. Fixes #1180
Browse files Browse the repository at this point in the history
  • Loading branch information
jwoertink committed Apr 2, 2023
1 parent 620069d commit 0fe5003
Show file tree
Hide file tree
Showing 8 changed files with 48 additions and 30 deletions.
8 changes: 6 additions & 2 deletions src/actions/guides/tutorial/00_overview.cr
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ class Guides::Tutorial::Overview < GuideAction
* installed Lucky. `lucky -v` should be #{LuckyCliVersion.current_tag}.
* installed [Postgres](#{Guides::GettingStarted::Installing.path(anchor: Guides::GettingStarted::Installing::ANCHOR_POSTGRESQL)}). `psql --version` should be `>= #{LuckyDependencyVersions.min_compatible_postgres_version}`
* installed [Node](#{Guides::GettingStarted::Installing.path(anchor: Guides::GettingStarted::Installing::ANCHOR_NODE)}). `node -v` should be `>= v#{LuckyDependencyVersions.min_compatible_node_version}` (used for building css and javascript)
* installed a [Process Manager](#{Guides::GettingStarted::Installing.path(anchor: Guides::GettingStarted::Installing::ANCHOR_PROC_MANAGER)}). (used for booting Webpack and Lucky at the same time)
## The Wizard
Expand Down Expand Up @@ -136,7 +135,12 @@ class Guides::Tutorial::Overview < GuideAction
## Browsing your Application
Open up your favorite browser, and head over to `http://127.0.0.1:3001`. You should see the Lucky home page.
Open up your favorite browser, and head over to `http://127.0.0.1:3000`. This URL will be printed
in your terminal log output.
> To change the port your app runs on, update the `port` option in the `config/watch.yml` file.
You should now see the Lucky home page.
Click the "VIEW YOUR NEW APP" button to be taken to a "Sign Up" page. Because the wizard set us up
with Authentication, we now have the ability to create a User account, and log in. Make your account!
Expand Down
4 changes: 2 additions & 2 deletions src/actions/guides/tutorial/01_new_resource.cr
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class Guides::Tutorial::NewResource < GuideAction
### Generating the model
Let's run our generator cli task. Enter this command in your terminal:
Let's run our generator CLI task. Enter this command in your terminal:
```bash
lucky gen.resource.browser Fortune text:String
Expand All @@ -50,7 +50,7 @@ class Guides::Tutorial::NewResource < GuideAction
This migration file will generate a SQL statement for us that will create our "fortunes" table and add the columns our
table needs like `text`, as well as a few other columns Avram gives to us for free: `id`, `created_at`, and `updated_at`.
To execute this code, we will run the `db.migrate` cli task. Enter `lucky db.migrate`:
To execute this code, we will run the `db.migrate` CLI task. Enter `lucky db.migrate`:
```bash
lucky db.migrate
Expand Down
12 changes: 7 additions & 5 deletions src/actions/guides/tutorial/02_assocations.cr
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class Guides::Tutorial::Associations < GuideAction
### Generating a new migration
We will use the `gen.migration` cli task to create a new migration file that will add a reference to User from the
We will use the `gen.migration` CLI task to create a new migration file that will add a reference to users from the
"fortunes" table. Generate the migration like this:
```
Expand Down Expand Up @@ -58,7 +58,7 @@ class Guides::Tutorial::Associations < GuideAction
Each time we generate a new migration, we must run it so it will update our database.
However, if we run our migration right now, we would see an error. Lucky ensures type-safety by
adding the foreign key constraints and references. By specifying `user : User` for the type, we tell
Lucky that this association is required. We could make it optional by using Crystal Nil Union `user : User?`,
Lucky that this association is required. We could make it optional by making the type nilable with `user : User?`,
but this is an easy fix, so we will keep the code as is.
> This error will only happen if you have fortune records. To see the error, run `lucky db.migrate`.
Expand All @@ -68,13 +68,15 @@ class Guides::Tutorial::Associations < GuideAction
Since we don't need any fortunes we created when playing with our app, we can just delete all of them to start
fresh. This gives us a chance to see how we can run "one-off" queries similar to other frameworks that use REPL consoles.
We will use the `exec` cli task which will open a code editor allowing us to write arbitrary Crystal code, including some Avram
We will use the `exec` CLI task which will open a code editor allowing us to write arbitrary Crystal code, including some Avram
queries. Enter `lucky exec`.
```bash
lucky exec
```
> This will open with VIM be default. To use a different editor, use the `-e` or `--editor` flag. (e.g. `lucky exec -e code`)
Once your code editor opens, you can write your query code below all of the comments. We will use the `FortuneQuery` object
which is defined in `src/queries/fortune_query.cr`.
Expand Down Expand Up @@ -106,7 +108,7 @@ class Guides::Tutorial::Associations < GuideAction
Associations work in two parts; the database, and the model. We update the database by writing our migration, so now we just need
to update the models.
Open up the file `src/models/user.cr`. This `User` model was generated when we ran our setup wizard.
Open up the file `src/models/user.cr`. This `User` model was generated when we ran our setup wizard by saying `y` to authentication.
At the bottom of the `table` block, we will add this new code:
Expand Down Expand Up @@ -147,7 +149,7 @@ class Guides::Tutorial::Associations < GuideAction
* Boot your application. (`lucky dev`)
* Sign in, and try to create a fortune. Notice it fails
* View your logs to see "Failed to save SaveFortune".
* Use `lucky exec` to truncate all `User` records.
* Use `lucky exec` to truncate all `User` records with the `UserQuery` object.
* Then use your app to make a new user record, because we still need one 😄
We will update the forms later in the tutorial.
Expand Down
6 changes: 3 additions & 3 deletions src/actions/guides/tutorial/03_design.cr
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ class Guides::Tutorial::Design < GuideAction
It's nice that we can boot our application and see a home page, but we know that page won't stick around.
We will swap it out for our own Home page to make this site a little more ours.
First, we should create a new `Page`. We will use the `gen.page` cli task. Enter `lucky gen.page Home::IndexPage`.
First, we should create a new `Page`. We will use the `gen.page` CLI task. Enter `lucky gen.page Home::IndexPage`.
```bash
lucky gen.page Home::IndexPage
```
This will generate a new `Page` class in `src/pages/homes/index_page.cr` which we will need to make a small change
This will generate a new `Page` class in `src/pages/home/index_page.cr` which we will need to make a small change
in. Open that file, and update this code:
```diff
# src/pages/homes/index_page.cr
# src/pages/home/index_page.cr
- class Home::IndexPage < MainLayout
+ class Home::IndexPage < AuthLayout
```
Expand Down
14 changes: 10 additions & 4 deletions src/actions/guides/tutorial/04_using_components.cr
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,17 @@ class Guides::Tutorial::UsingComponents < GuideAction
we can see all of the markup that would go in our website's `<head>` tags are here. They are in the `render`
method (required for all components).
At the top of this file are two `needs` lines. The `needs page_title : String` and `needs context : HTTP::Server::Context`.
You will find `needs` in several different classes in Lucky. It's used for type-safety when a class requires specific data.
At the top of this file you will see a line that starts with `needs`. The `needs page_title : String`.
This tells the `Shared::LayoutHead` component that it requires the `page_title` value to be passed in
when mounting this component. (e.g. `mount Shared::Header, page_title: "Clover App"`)
Each `needs` specified will create a method with that name that will return the value type specified.
We use `needs` in several different classes in Lucky. It's used for type-safety when a class requires specific data.
## Reusing Components
We currently have two separate layouts, but our custom footer is only in the `AuthLayout`. Let's create a
new component that will allow us to render our footer in both layouts:
new component that will allow us to render our footer in both layouts with the `gen.component` CLI task:
```bash
lucky gen.component Shared::Footer
```
Expand Down Expand Up @@ -58,7 +62,7 @@ class Guides::Tutorial::UsingComponents < GuideAction
As an added benefit, if you inspect your page's markup, you'll see HTML comments wrapped around each
component. This allows you to see which component is responsible for the markup being rendered.
When creating your own components that require specific data (i.e. page_title), you will add your `needs`
When creating your own components that require specific data (i.e. `page_title`), you will add your `needs`
for that data, then in your `mount`, you'll pass each as a named argument. (e.g. `mount Shared::Footer, copyright_year: 3099`)
> For more information on components, read the [Components](#{Guides::Frontend::RenderingHtml.path(anchor: Guides::Frontend::RenderingHtml::ANCHOR_COMPONENTS)})
Expand All @@ -73,6 +77,8 @@ class Guides::Tutorial::UsingComponents < GuideAction
* Generate a new component for a nav bar
* Mount your new component in both layouts
* Add a `needs` line to your component, and pass in the data
* Display the value of that `needs` method in your component
MD
end
end
20 changes: 13 additions & 7 deletions src/actions/guides/tutorial/05_operations_factories.cr
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class Guides::Tutorial::OperationsFactories < GuideAction
### Playing with SaveOperation
We can get a quick feel for these by using the `exec` cli task in our terminal:
We can get a quick feel for these by using the `exec` CLI task in our terminal:
```bash
lucky exec
Expand All @@ -50,7 +50,9 @@ class Guides::Tutorial::OperationsFactories < GuideAction
end
```
Once done, save and exit the file. It will compile and print out a `Hash(String, Array(String))` object, and `nil`.
> Note that the `password` and `password_confirmation` are intentionally different.
Once done, save and exit the file. It will compile and print out an errors object of type `Hash(String, Array(String))`, and `nil` for `saved_user` because this failed to save.
Our SaveOperation has a `create` method which takes named args of what the operation requires from us. It
also takes a block that will pass the operation instance and the saved user (if one exists). The `operation` has
an `errors` method allowing us to inspect what errors we get back and why we don't have a `saved_user` object.
Expand All @@ -75,8 +77,9 @@ class Guides::Tutorial::OperationsFactories < GuideAction
### Factory breakdown
Every Factory is directly tied to a SaveOperation which means that all columns in the Model are available in the Factory.
The column methods in the Factory take an argument to set their value. You can also use the `sequence()` method
to generate a new number each time you generate a new Factory record to keep things a bit more dynamic.
The column methods in the Factory take an argument to set their value. (e.g. `email("[email protected]")`)
You can also use the `sequence()` method to generate a new number each time you generate a new Factory record
to keep things a bit more dynamic.
## Create a New Factory
Expand All @@ -88,7 +91,9 @@ class Guides::Tutorial::OperationsFactories < GuideAction
class FortuneFactory < Avram::Factory
def initialize
text "Have a Lucky day! \#{rand(100)} \#{rand(100)} \#{rand(100)}"
# Default assign to user 1
# Default assign to user 1 for now
# We will show how to override this further down
user_id 1
end
end
Expand All @@ -97,7 +102,8 @@ class Guides::Tutorial::OperationsFactories < GuideAction
We must add a value for every required column. The auto-generated columns `id`, `created_at`, and `updated_at` are automatically
assigned a value.
> It's important that the name of this class matches the name of the model (`Fortune`), and then ends in `Factory` (`FortuneFactory`).
> It's important that the name of this class matches the name of the model (`Fortune`), and then ends in `Factory` (i.e. `FortuneFactory`).
> See more on the [Factories](#{Guides::Testing::CreatingTestData.path}) guide
### Adding sample data
Expand All @@ -121,7 +127,7 @@ class Guides::Tutorial::OperationsFactories < GuideAction
end
```
With that file updated we can now run our `db.seed.sample_data` cli task to execute this code:
With that file updated we can now run our `db.seed.sample_data` CLI task to execute this code:
```bash
lucky db.seed.sample_data
Expand Down
6 changes: 3 additions & 3 deletions src/actions/guides/tutorial/06_queries.cr
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,11 @@ class Guides::Tutorial::Queries < GuideAction
Try this...
* Create a new `latest` method in your `FortuneQuery` class.
* Update your `Home::Index` action to use the new `latest` method.
* Create a new `latest` method in your `FortuneQuery` class that fetches the last 10 records created.
* Update your `Home::Index` action to use the new `latest` method instead of the limit and ordering.
* Add a new `name : String` column to your `User` model. (hint: generate a new migration)
* Update your `UserFactory` to generate a random `name`.
* Update existing user records with a random name. (hint: the guides mention "bulk updating")
* Update existing user records with a random name. (hint: search the guides (`ctrl-k`) for mention of "bulk updating")
* Update the fortunes to display the user's name that wrote it.
MD
Expand Down
8 changes: 4 additions & 4 deletions src/actions/guides/tutorial/07_beyond_basics.cr
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class Guides::Tutorial::BeyondBasics < GuideAction
no `user_id` is set. We can get this value from our `current_user` method as this is available
once we've logged in.
We will need to update many of Fortune actions, as well as our `SaveFortune` operation to include
We will need to update our Fortune actions, as well as our `SaveFortune` operation to include
this.
### Updating the operation
Expand Down Expand Up @@ -44,7 +44,7 @@ class Guides::Tutorial::BeyondBasics < GuideAction
With the addition of the `needs` any time we instantiate the `SaveFortune`, we must pass in the `current_user` object.
For now this is in the following fortune actions: `Fortunes::New`, `Fortunes::Create`, `Fortunes::Edit`, and `Fortunes::Update`.
We will start the `Fortunes::New` action in `src/actions/fortunes/new.cr`. Update with this code:
We will start in the `Fortunes::New` action in `src/actions/fortunes/new.cr`. Update with this code:
```crystal
# src/actions/fortunes/new.cr
Expand Down Expand Up @@ -89,7 +89,7 @@ class Guides::Tutorial::BeyondBasics < GuideAction
### Adding an action mixin
Mixins are just modules you can reuse in multiple classes. You'll find some existing mixins in the
`src/actions/mixins/` directory. We will create a new on called `OnlyAllowCurrentUser` in `src/actions/mixins/only_allow_current_user.cr`.
`src/actions/mixins/` directory. We will create a new one called `OnlyAllowCurrentUser` in `src/actions/mixins/only_allow_current_user.cr`.
The idea of this mixin will be to check that the `current_user` owns the `fortune`. If not, then we will raise an error.
Add this file with this code:
Expand Down Expand Up @@ -148,7 +148,7 @@ class Guides::Tutorial::BeyondBasics < GuideAction
Save your files, boot your app, and give it a shot. Try editing a fortune that doesn't belong to you; you
should see the [exception page](https://github.com/crystal-loot/exception_page) with a code snippet, and
stack trace. This page is helpful when debugging, but only shows up in development. To see what your users
will see, open up `config/error_handler.cr`, and set the `show_debug_output` setting to `false`.
will see in production, open up `config/error_handler.cr`, and set the `show_debug_output` setting to `false`.
Once your app recompiles, try the action again, and you'll now see the default Lucky error page with
your custom message, and the 401 status. Be sure to set that setting back once you've had a chance to
Expand Down

0 comments on commit 0fe5003

Please sign in to comment.