The Exact Same App in Hyperstack part II — Hold on to your socks!

Catmando
5 min readMar 26, 2019

--

In part I of this series, we took a small Todo App written in React and compared it to the same app written in Hyperstack.

The result is a highly readable piece of Ruby code about half the size of the original React app.

That alone is pretty cool unless you really like to hammer on your keyboard.

In part-II I hope to blow your socks off.

We are going to use a single command line and a Rails generator to add 2 lines of code plus a configuration file to our application. Now our Todos will be saved to the server database and will be synchronized across all browsers.

Yes, 2 lines of code and you will then be able to add a Todo in browser 1, and it will immediately appear in browsers 2 and 3. Change a Todo in browser 2 and the change will be reflected in the other browsers.

Our entire application will still be less than 50 lines of code.

How is that even possible?

I’m sure you want to get started but before we do I want to explain why this is possible. It appears like magic but its just good use of existing stable technology.

  • By using the same language on the server and browser we immediately eliminate all the boilerplate, adapters, connectors, controllers, digesters, responders, reducers, APIs, and other confusticators that really do nothing but translate from one syntactic world to another.
  • We leverage Rails’ Active Record to build and manage the low-level server-side connection between the database and our higher level Ruby Todo abstraction for us.
  • Finally, we use Ruby as our single language, which is simply more concise without losing readability than many other languages. Its also stable has been around for years with good documentation and an incredibly helpful community.

Let's Go! — Creating the Database Model

The key here is that we want to save (or persist) the state of the Todos to a server someplace. That way if I leave the app, and come back later, even on a different machine I will see the state of the data just as I left it.

To do this (no pun intended) we need a database table (which we will call todos) and a Ruby class called Todowhich gives us access to that table.

Notice the relationship between todos (table name) and Todo (class name.) This is called convention over configuration, and is one of the reasons we get so much done for so little. Instead of wiring up todos to Todo the framework by default assumes the connection for us.

Because Hyperstack is built on top of Rails, this is easy. All we do is enter into our command line:bundle exec rails generate model Todo title:string

By the way if you want to follow along you can clone the github repo containing part i of the code: https://github.com/hyperstack-org/todo-compare

This runs a Rails generator which will create the skeleton Todo model class, and create a migration which will add the necessary tables and columns to the database.

The next step is to run the migration created in the step above:

bundle exec rake db:migrate

Besides the migration, Rails created a model class and put it in the app/models/todo.rb file:

# app/models/todo.rbclass Todo < ApplicationRecord
end

Because we want our model to be visible both on the server and the client we will move it to the app/hyperstack/model/ directory:

Our final app/hyperstack directory looks like this:

app/hyperstack
├── components
│ ├── hyper_component.rb
│ ├── todo_index.rb
│ └── todo_item.rb
├── models
│ ├── application_record.rb
│ └── todo.rb <-- we just moved this here
├── operations
└── stores

Updating our Component to use the Model

If you are following along you can start your local server by running
bundle exec foreman start. To fully appreciate what is happening open the app in two different browser windows…

In part-I we used an array called @list to store our Todos.

Now that we have the Todos in our database we can directly access them using the Todo model class. We will use three of the methods that every ActiveRecord model class has: create, each, and destroy. In addition because our Todo class has a title column, we can use the title method to get that the value of that field for each record.

The resulting code looks like this:

Here are the differences:

# original:def create_new_todo_item
mutate @list << { todo: @todo }, @todo = nil
end
# using the Todo model:def create_new_todo_item
Todo.create(title: @title)
@title = nil
end

Instead of pushing a new hash onto the @list we call the Todo’s create method. For consistency, we change the name of the @todo state variable to @title which still needs to be reset.

# original:@list.each do |item|
TodoItem(key: item, item: item[:todo])
.on(:delete_item) { mutate @list.delete(item) }
end
# using the Todo model:Todo.each do |item|
TodoItem(key: item, item: item.title)
.on(:delete_item) { item.destroy }
end

In the original, we iterated over the @list array, mounting a TodoItem for each item in the list.

In our new version we iterate over all the Todos in the todo table, and again for each item, we mount a TodoItem which is accessed by a method name matching the column name we want.

To destroy the item, we just call the item.destroy method.

You may notice that there is only one call to mutate. This is because the Todo class keeps tracks of mutations internally, so we only need to track state changes to the local @title state variable.

That’s It!

Each browser viewing the Todos will get a copy of the data necessary (in this case each todo’s title), and as items are created or destroyed, the changes will be posted to the server, and then broadcast out to the other browsers. This will cause the underlying React engine to update any changed components.

While this only shows a simple case, Hyperstack implements all the key methods of ActiveRecord so you can have complex relationships between models, you can scope (or filter) data, use single-type-inheritance and polymorphic relationships. And access control can be completely specified using Hyperstack’s policy system.

In our next installment, we will use some of these features to make our Todo app more robust.

Stay tuned…

P.S. If you want to know more right now visit the Hyperstack site.

--

--

Catmando

AKA Mitch VanDuyn, is the founder and chief mad scientist at CatPrint.com, an internet printing company.