You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/getting-started/quick-start.md
+59-38Lines changed: 59 additions & 38 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,18 +1,16 @@
1
-
# Quick Start \[WIP\]
1
+
# Tutorial
2
2
3
-
{% hint style="danger" %}
4
-
Migration to 2.0.0 in progress
5
-
{% endhint %}
3
+
## Create a reactive Twitter clone in pure Ruby
6
4
7
5
In this step-by-step guide, I will show you how to create a Twitter clone in pure Ruby with Matestack, following the great screencasts from Chris McCord [Phoenix LiveView Twitter Clone](https://youtu.be/MZvmYaFkNJI) and Nate Hopkins [Stimulus Reflex Twitter Clone](https://youtu.be/F5hA79vKE_E). We will use the Gem `matestack-ui-core`, which enables us to implement our UI in some Ruby classes rather than writing ERB, HAML or Slim views. Furthermore we don't need to touch JavaScript in order to create reactive UI features, such as updating the DOM without a full browser page reload or syncing multiple web clients through Action Cable!
8
6
9
-
I've added a screencast \(two parts\)showing you what you will be doing in this tutorial:
7
+
I've added a small demo showing you what you will be creating in this tutorial:
_This guide utilizes the full power of Matestack and uses `matestack-ui-core` as a complete substitute for Rails views. If you only want to create UI components in pure Ruby on existing Rails views, please check out_[_this guide_](https://docs.matestack.io/docs/ui_components/100-rails_integration)
14
12
15
-
## Setup
13
+
###Setup
16
14
17
15
*[x] Create a new Rails app and install some dependencies:
18
16
@@ -29,7 +27,7 @@ yarn add matestack-ui-core
29
27
rails g scaffold Post body:text likes_count:integer username:string
30
28
```
31
29
32
-
## Model & Database
30
+
###Model & Database
33
31
34
32
*[x] Modify generated migration in order to add defaults:
35
33
@@ -70,7 +68,7 @@ class Post < ApplicationRecord
70
68
end
71
69
```
72
70
73
-
## Import Matestack's JavaScript
71
+
###Import Matestack's JavaScript
74
72
75
73
Previously, in version 1.5, Vue and Vuex were imported automatically. Now this must be done manually which is the webpacker way. You can import it in `app/javascript/packs/application.js` or in another pack if you need.
@@ -141,7 +139,7 @@ On `app/views/layouts/application.html.erb` do:
141
139
142
140
*[x] Delete all generated `app/views/posts` views - we don't need them!
143
141
144
-
## Controller
142
+
###Controller
145
143
146
144
*[x] Add Matestack's helper to your application controller:
147
145
@@ -194,7 +192,7 @@ class PostsController < ApplicationController
194
192
end
195
193
```
196
194
197
-
## Matestack App and Pages
195
+
###Matestack App and Pages
198
196
199
197
*[x] Add a `matestack` folder and create a Matestack app and a Matestack `Post` index page file:
200
198
@@ -246,7 +244,7 @@ class TwitterClone::Pages::Posts::Index < Matestack::Ui::Page
246
244
end
247
245
```
248
246
249
-
## Add Matestack to the Controller
247
+
###Add Matestack to the Controller
250
248
251
249
*[x] Reference Matestack's app and page on the controller and `index` action:
252
250
@@ -280,7 +278,7 @@ rails s
280
278
281
279
You should see the heading "Twitte Clone" and that's it. We don't have any posts in our database, so we need a `form` to create one!
282
280
283
-
## Add a Reactive Form
281
+
###Add a Reactive Form
284
282
285
283
*[x] Add a reactive `form` to the index page
286
284
*[x] Use the `form_config_helper` method returning a config hash in order to inject a hash into the form without polluting the code
@@ -387,11 +385,11 @@ end
387
385
388
386
*[x] Navigate to `localhost:3000/posts`
389
387
390
-
You should see a basic index page with a form at the top. When submitting the form without any values, ActiveRecord errors should appear below the input fields without a browser page reload. When submitting valid data, the form should reset automatically without a browser page reload, but you will still have to reload the browser in order to see the new post!
388
+
You should see a basic index page with a form at the top. When submitting the form without any values, ActiveRecord errors should appear below the input fields without a browser page reload. When submitting valid data, the form should reset automatically without a browser page reload, but you will still have to reload the browser in order to see the new post!
391
389
392
390
To get that reactivity to work, we need make use of the `async` component.
393
391
394
-
## Add Matestack's Async Component
392
+
###Add Matestack's Async Component
395
393
396
394
*[x] Add `success: {emit: "submitted"}` to the form config
397
395
*[x] Wrap the `post_list_partial` with an `async`, configured to rerender when the event `submitted` is received
@@ -437,7 +435,7 @@ Cool! Now you should see the list automatically updating itself after form submi
437
435
438
436
Now we need to add some `action` components in order to "like" the posts.
439
437
440
-
## Enable "likes"
438
+
###Enable "likes"
441
439
442
440
*[x] Add the `like` route:
443
441
@@ -525,7 +523,7 @@ When you click the "Like" button on a post, you will see the counter increasing
525
523
526
524
Great! We added a reactive form and reactive actions. We can now add some reactive feedback on top using the toggle component!
527
525
528
-
## Add Reactive Feedback Using the `toggle` Component
526
+
###Add Reactive Feedback Using the `toggle` Component
529
527
530
528
*[x] Add failure event submission to the form config like: `failure: {emit: "form_failed"},`
531
529
*[x] Add a `toggle` component in order to render the success message for 5 seconds
@@ -588,7 +586,7 @@ Great! Now we get instant feedback after performing successful or unsuccessful f
588
586
589
587
All of the above described reactivity only applies for one client. A second user wouldn't see the new post, unless he reloads his browser page. But of course, we want to sync all connected clients! It's time to integrate ActionCable!
590
588
591
-
## Integrate Action Cable
589
+
###Integrate Action Cable
592
590
593
591
*[x] Generate an ActionCabel channel
594
592
@@ -758,7 +756,7 @@ Wow! We just had to copy and paste a JavaScript snippet once in order to integra
758
756
759
757
We will take a short break before adding the next cool reactivity feature and refactor a little bit! Matestack encourages you to create a readable and maintainable UI implemetation. Therefore we will move some complexity from the current index page to a self contained Matestack component!
760
758
761
-
## Create a Matestack Component
759
+
###Create a Matestack Component
762
760
763
761
*[x] Create a components folder within the matestack folder
*[x] Move code from the index page to the new component
771
-
*[x] adjust references to the given post parameter to be called as a method of the context object (`context.post.id`)
769
+
*[x] adjust references to the given post parameter to be called as a method of the context object \(`context.post.id`\)
772
770
773
771
`app/matestack/components/post.rb`
774
772
@@ -798,7 +796,6 @@ class Components::Post < Matestack::Ui::Component
798
796
end
799
797
```
800
798
801
-
802
799
*[x] Adjust the index page in order to use the new component
803
800
804
801
`app/matestack/twitter_clone/posts/index.rb`
@@ -854,10 +851,9 @@ end
854
851
855
852
Everything should be the same! We just refactored some code in order to better manage complexity.
856
853
854
+
### Component Registry
857
855
858
-
## Component Registry
859
-
860
-
Components can be invoked as we have done above (`Components::Post.(post: post)`). But sometimes the namespace can get a little long and in the interest of keeping our code beautiful, we can register our components so we can call them like:
856
+
Components can be invoked as we have done above \(`Components::Post.(post: post)`\). But sometimes the namespace can get a little long and in the interest of keeping our code beautiful, we can register our components so we can call them like:
861
857
862
858
```ruby
863
859
# ...
@@ -874,7 +870,7 @@ Components can be invoked as we have done above (`Components::Post.(post: post)`
874
870
# ...
875
871
```
876
872
877
-
Let's refactor and set up a component registry and register our component.
873
+
Let's refactor and set up a component registry and register our component.
@@ -934,23 +929,21 @@ class TwitterClone::Pages::Posts::Index < Matestack::Ui::Page
934
929
end
935
930
```
936
931
937
-
938
932
**Test the current state again**
939
933
940
934
*[x] Navigate to `localhost:3000/posts`
941
935
942
936
Everything should be the same after this small refactoring.
943
937
944
-
945
-
## The Cable Component
938
+
### The Cable Component
946
939
947
940
Now we will cover the last topic of this guide:
948
941
949
942
As described before, the `async` rerenders it's whole body. The `async` wrapping the whole post list therefore rerenders ALL posts. If our list of posts grows, the performance of the rerendering will decrease. In a lot of usecases, this will not be an issue since the UI is not too big/too complex. So go ahead and use `async` everywhere you're not rerendering big or complex UIs and enjoy the simplicity of that rerendering approach!
950
943
951
944
But now imagine, your post list will be too big at some point. We should switch the reactivity approach to a more granular one. Let's use the `cable` component alongside our already added ActionCable introduction and reuse pretty much all written code!
952
945
953
-
## Use the `cable` Component For List Rerendering
946
+
###Use the `cable` Component For List Rerendering
954
947
955
948
*[x] Use the `cable` instead of the `async` component
956
949
@@ -1023,7 +1016,7 @@ You probably don't realize any difference on the UI, but now ONLY the fresh post
1023
1016
1024
1017
The `cable` component can `prepend`, `append`, `update` and `delete` elements within its body or `replace` its whole body with something pushed from the server. We want to use the `update` feature in order to rerender a specific post when liked:
1025
1018
1026
-
## Adjust the `cable` Component for Post Rerendering
1019
+
###Adjust the `cable` Component for Post Rerendering
1027
1020
1028
1021
*[x] Add the `update_on` config to the `cable` config
1029
1022
@@ -1088,8 +1081,6 @@ end
1088
1081
1089
1082
*[x] Adjust the ActionCable broadcast on the `like` action on the post controller
1090
1083
1091
-
# todo: cable__liked_post not working here
1092
-
1093
1084
`app/controllers/posts_controller.rb`
1094
1085
1095
1086
```ruby
@@ -1157,7 +1148,7 @@ Ok, let's lazy load the list of posts in order to speed up initial page load whe
1157
1148
1158
1149
Relax, it's super simple:
1159
1150
1160
-
## Lazy Load the Post List With Async's `defer` Feature
1151
+
###Lazy Load the Post List With Async's `defer` Feature
1161
1152
1162
1153
*[x] Wrap an `async` component around the `cable` component
1163
1154
*[x] Configure this `async` to defer its rendering
Speaking of fade effects: Let's add a second page in order to show, how you can use Matestacks app and `transition` component in order to implement dynamic page transitions without full browser page reload and without adding any JavaScript!
1245
1236
1246
-
## Implement Dynamic Page Transitions
1237
+
###Implement Dynamic Page Transitions
1247
1238
1248
1239
We will create a profile page in order to save the username in a session cookie rather than asking for the username on the post form! Obviously, you would use proper user management via something like `devise` in a real world example!
1249
1240
@@ -1268,7 +1259,6 @@ end
1268
1259
*[x] Remove the username input from the post form
1269
1260
*[x] Remove the toggle components from the post index page; we will add them to the app in a moment, enabling the new profile page to trigger them as well!
1270
1261
*[ ]
1271
-
1272
1262
`app/matestack/twitter_clone/posts/index.rb`
1273
1263
1274
1264
```ruby
@@ -1582,11 +1572,12 @@ end
1582
1572
1583
1573
And now, let's do something that isn't possible in Twitter: Editing. Tweets. Inline. In pure Ruby! \(Just because it's nice to showcase that\)
1584
1574
1585
-
## Inline Editing
1575
+
###Inline Editing
1586
1576
1587
1577
*[x] Add an edit form
1588
1578
*[x] Add an `onclick` component emit an event indicating that we want to show the form now
1589
1579
*[x] Wrap your code into toggle components, switching the currently visible content
1580
+
*[x] Adjust the cable component to react to an additional event
0 commit comments