Skip to content

Commit 5f31936

Browse files
committed
updated todo tutorial
1 parent fb8cc47 commit 5f31936

1 file changed

Lines changed: 73 additions & 55 deletions

File tree

docs/tutorial/todo.md

Lines changed: 73 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# TodoMVC Tutorial
1+
todo# TodoMVC Tutorial
22

33
*Based on Ruby on Rails 5.2.x*
44

@@ -30,25 +30,44 @@ You will write less than 100 lines of code, and the tutorial should take about 1
3030

3131
Basic knowledge of Ruby is needed, knowledge of Ruby on Rails is helpful.
3232

33-
3433
### Chapter 1: Setting Things Up
3534

3635
First you need to create a new project for this tutorial.
3736
```shell
38-
rails new todo-demo --skip-test --template=https://rawgit.com/hyperstack-org/hyperstack/edge/install/rails-webpacker.rb
37+
rails new todo-demo --skip-test
3938
```
40-
This command will create a new Rails project and run the template file to set up Hyperstack within this project.
39+
This command will create a new Rails project.
4140

4241
**Caution:** *you can name the app anything you want, we recommend todo-demo, but whatever you do DON'T call it todo,
4342
as this name will be needed later!*
4443

45-
**Note:** *if you like you can read the contents of the template file by pasting the
46-
[url](https://rawgit.com/hyperstack-org/hyperstack/edge/install/rails-webpacker.rb) (the part after `--template=`) in a browser.
47-
It shows how a Hyperstack Rails project differs from a plain Rails project.*
44+
Now
4845
```shell
4946
cd todo-demo
5047
```
51-
Will change the working directory to your new todo rails project.
48+
which will change the working directory to your new todo rails project.
49+
50+
Now run
51+
```shell
52+
bundle add 'rails-hyperstack' --version "~> 1.0.alpha1.0"
53+
```
54+
55+
which will install the `rails-hyperstack` 'gem' into the system.
56+
57+
Once the gem is installed run
58+
```shell
59+
bundle exec rails hyperstack:install
60+
```
61+
62+
to complete the hyperstack installation.
63+
64+
Finally find the `config/initializers/hyperstack.rb` file, and make sure that this line is **not** commented out:
65+
66+
```ruby
67+
Hyperstack.import 'hyperstack/component/jquery', client_only: true
68+
```
69+
70+
> Ignore any comments saying that it should be commented out, this is a typo in the current installer
5271
5372
#### Start the Rails app
5473

@@ -67,7 +86,7 @@ Hyperstack will need a moment to start and pre-compile with the first request.
6786
#### Make a Simple Change
6887

6988
Bring up your favorite editor on the `todo-demo` directory. You will see folders like `app`, `bin`, `config` and `db`.
70-
These have all been preinitialized by Rails and the Hyperstack template you used to build the app.
89+
These have all been preinitialized by Rails and Hyperstack gems.
7190

7291
Now find the `app/hyperstack/components/app.rb` file. It looks like this:
7392

@@ -143,7 +162,7 @@ t.boolean :completed, null: false, default: false
143162
...
144163
```
145164
For details on 'why' see [this blog post.](https://robots.thoughtbot.com/avoid-the-threestate-boolean-problem)
146-
Basically this insures `completed` is treated as a true boolean, and will avoid having to check between `false` and `null` later on.
165+
Basically this insures `completed` is treated as a real boolean, and will avoid having to check between `false` and `null` later on.
147166

148167
Now run:
149168
```shell
@@ -222,7 +241,7 @@ After saving you will see the following error displayed:
222241
in App (created by Hyperstack::Internal::Component::TopLevelRailsComponent)
223242
in Hyperstack::Internal::Component::TopLevelRailsComponent**
224243

225-
because have not defined the three subcomponents. Lets define them now:
244+
because we have not defined the three subcomponents. Lets define them now:
226245

227246
Add three new ruby files to the `app/hyperstack/components` folder:
228247

@@ -281,7 +300,7 @@ To display each Todo we will create a TodoItem component that takes a parameter:
281300
class TodoItem < HyperComponent
282301
param :todo
283302
render(LI) do
284-
@Todo.title
303+
todo.title
285304
end
286305
end
287306
```
@@ -318,8 +337,7 @@ As you can see components can take parameters (or props in react.js terminology.
318337
>*Rails uses the terminology params (short for parameters) which have a similar purpose to React props,
319338
so to make the transition more natural for Rails programmers Hyperstack uses params, rather than props.*
320339

321-
Params are declared using the `param` macro and are accessed via Ruby *instance variables*.
322-
Notice that the instance variable name is *CamelCased* so that it is easily distinguished from other instance variables.
340+
Params are declared using the `param` macro which creates an *accessor* method of the same name within the component.
323341

324342
Our `Index` component *mounts* a new `TodoItem` with each `Todo` record and passes the `Todo` to the `TodoItem` component as the parameter.
325343

@@ -344,8 +362,8 @@ First add an `INPUT` html tag to your TodoItem component like this:
344362
class TodoItem < HyperComponent
345363
param :todo
346364
render(LI) do
347-
INPUT(type: :checkbox, checked: @Todo.completed)
348-
@Todo.title
365+
INPUT(type: :checkbox, checked: todo.completed)
366+
todo.title
349367
end
350368
end
351369
```
@@ -365,9 +383,9 @@ To make our checkbox input change its own state, we will add an `event handler`
365383
class TodoItem < HyperComponent
366384
param :todo
367385
render(LI) do
368-
INPUT(type: :checkbox, checked: @Todo.completed)
369-
.on(:change) { @Todo.update(completed: !@Todo.completed) }
370-
@Todo.title
386+
INPUT(type: :checkbox, checked: todo.completed)
387+
.on(:change) { todo.update(completed: !todo.completed) }
388+
todo.title
371389
end
372390
end
373391
```
@@ -386,10 +404,10 @@ We will finish up by adding a *delete* link at the end of the Todo item:
386404
class TodoItem < HyperComponent
387405
param :todo
388406
render(LI) do
389-
INPUT(type: :checkbox, checked: @Todo.completed)
390-
.on(:change) { @Todo.update(completed: !@Todo.completed) }
391-
SPAN { @Todo.title } # See note below...
392-
A { ' -X-' }.on(:click) { @Todo.destroy }
407+
INPUT(type: :checkbox, checked: todo.completed)
408+
.on(:change) { todo.update(completed: !todo.completed) }
409+
SPAN { todo.title } # See note below...
410+
A { ' -X-' }.on(:click) { todo.destroy }
393411
end
394412
end
395413
```
@@ -574,27 +592,27 @@ Add a new component like this:
574592
class EditItem < HyperComponent
575593
param :todo
576594
render do
577-
INPUT(defaultValue: @Todo.title)
595+
INPUT(defaultValue: todo.title)
578596
.on(:enter) do |evt|
579-
@Todo.update(title: evt.target.value)
597+
todo.update(title: evt.target.value)
580598
end
581599
end
582600
end
583601
```
584602
Before we use this component let's understand how it works.
585603
+ It receives a `todo` param which will be edited by the user;
586604
+ The `title` of the todo is displayed as the initial value of the input;
587-
+ When the user types the enter key the `@Todo` is updated.
605+
+ When the user types the enter key the `todo` is updated.
588606

589607
Now update the `TodoItem` component replacing
590608

591609
```ruby
592-
SPAN { @Todo.title }
610+
SPAN { todo.title }
593611
```
594612
with
595613

596614
```ruby
597-
EditItem(todo: @Todo)
615+
EditItem(todo: todo)
598616
```
599617
Try it out by changing the text of some our your Todos followed by the enter key. Then refresh the page to see that the Todos have changed.
600618

@@ -624,9 +642,9 @@ class EditItem < HyperComponent
624642
after_mount { jQ[dom_node].focus } # add
625643

626644
render do
627-
INPUT(defaultValue: @Todo.title)
645+
INPUT(defaultValue: todo.title)
628646
.on(:enter) do |evt|
629-
@Todo.update(title: evt.target.value)
647+
todo.update(title: evt.target.value)
630648
saved! # add
631649
end
632650
.on(:blur) { cancel! } # add
@@ -653,15 +671,15 @@ class TodoItem < HyperComponent
653671
param :todo
654672
render(LI) do
655673
if @editing
656-
EditItem(todo: @Todo)
674+
EditItem(todo: todo)
657675
.on(:saved, :cancel) { mutate @editing = false }
658676
else
659-
INPUT(type: :checkbox, checked: @Todo.completed)
660-
.on(:change) { @Todo.update(completed: !@Todo.completed) }
661-
LABEL { @Todo.title }
677+
INPUT(type: :checkbox, checked: todo.completed)
678+
.on(:change) { todo.update(completed: !todo.completed) }
679+
LABEL { todo.title }
662680
.on(:double_click) { mutate @editing = true }
663681
A { ' -X-' }
664-
.on(:click) { @Todo.destroy }
682+
.on(:click) { todo.destroy }
665683
end
666684
end
667685
end
@@ -724,12 +742,12 @@ new Todo records, but even though they are changing React *does not* update the
724742
React has a special param called `key`. React uses this to uniquely identify mounted components. It's used to keep track of lists of components,
725743
in this case it can also be used to indicate that the component needs to be remounted when the value of `key` is changed.
726744

727-
All objects in Hyperstack respond to the `to_key` method which will return a suitable unique key id, so all we have to do is pass `@Todo` as the key param,
728-
this will insure that as `@Todo` changes, we will re-initialize the `INPUT` tag.
745+
All objects in Hyperstack respond to the `to_key` method which will return a suitable unique key id, so all we have to do is pass `todo` as the key param,
746+
this will insure that as `todo` changes, we will re-initialize the `INPUT` tag.
729747

730748
```ruby
731749
...
732-
INPUT(defaultValue: @Todo.title, key: @Todo) # add the special key param
750+
INPUT(defaultValue: todo.title, key: todo) # add the special key param
733751
...
734752
```
735753

@@ -809,9 +827,9 @@ class EditItem < HyperComponent
809827
other :etc # can be named anything you want
810828
after_mount { jQ[dom_node].focus }
811829
render do
812-
INPUT(@Etc, defaultValue: @Todo.title, key: @Todo)
830+
INPUT(etc, defaultValue: todo.title, key: todo)
813831
.on(:enter) do |evt|
814-
@Todo.update(title: evt.target.value)
832+
todo.update(title: evt.target.value)
815833
saved!
816834
end
817835
.on(:blur) { cancel! }
@@ -826,15 +844,15 @@ class TodoItem < HyperComponent
826844
param :todo
827845
render(LI, class: 'todo-item') do # add the todo-item class
828846
if @editing
829-
EditItem(class: :edit, todo: @Todo) # add the edit class
847+
EditItem(class: :edit, todo: todo) # add the edit class
830848
.on(:saved, :cancel) { mutate @editing = false }
831849
else
832-
INPUT(type: :checkbox, class: :toggle, checked: @Todo.completed) # add the toggle class
833-
.on(:change) { @Todo.update(completed: !@Todo.completed) }
834-
LABEL { @Todo.title }
850+
INPUT(type: :checkbox, class: :toggle, checked: todo.completed) # add the toggle class
851+
.on(:change) { todo.update(completed: !todo.completed) }
852+
LABEL { todo.title }
835853
.on(:double_click) { mutate @editing = true }
836854
A(class: :destroy) # add the destroy class and remove the -X- placeholder
837-
.on(:click) { @Todo.destroy }
855+
.on(:click) { todo.destroy }
838856
end
839857
end
840858
end
@@ -877,8 +895,8 @@ render(DIV, class: :footer) do
877895

878896
```ruby
879897
...
880-
INPUT(@Etc, placeholder: 'What is left to do today?',
881-
defaultValue: @Todo.title, key: @Todo)
898+
INPUT(etc, placeholder: 'What is left to do today?',
899+
defaultValue: todo.title, key: todo)
882900
.on(:enter) do |evt|
883901
...
884902
```
@@ -971,15 +989,15 @@ class TodoItem < HyperComponent
971989
param :todo
972990
render(LI, class: 'todo-item') do
973991
if @editing
974-
EditItem(class: :edit, todo: @Todo)
992+
EditItem(class: :edit, todo: todo)
975993
.on(:saved, :cancel) { mutate @editing = false }
976994
else
977-
INPUT(type: :checkbox, class: :toggle, checked: @Todo.completed)
978-
.on(:change) { @Todo.update(completed: !@Todo.completed) }
979-
LABEL { @Todo.title }
995+
INPUT(type: :checkbox, class: :toggle, checked: todo.completed)
996+
.on(:change) { todo.update(completed: !todo.completed) }
997+
LABEL { todo.title }
980998
.on(:double_click) { mutate @editing = true }
981999
A(class: :destroy)
982-
.on(:click) { @Todo.destroy }
1000+
.on(:click) { todo.destroy }
9831001
end
9841002
end
9851003
end
@@ -992,10 +1010,10 @@ class EditItem < HyperComponent
9921010
other :etc
9931011
after_mount { jQ[dom_node].focus }
9941012
render do
995-
INPUT(@Etc, placeholder: 'What is left to do today?',
996-
defaultValue: @Todo.title, key: @Todo)
1013+
INPUT(etc, placeholder: 'What is left to do today?',
1014+
defaultValue: todo.title, key: todo)
9971015
.on(:enter) do |evt|
998-
@Todo.update(title: evt.target.value)
1016+
todo.update(title: evt.target.value)
9991017
saved!
10001018
end
10011019
.on(:blur) { cancel! }

0 commit comments

Comments
 (0)